UpdraftPlus WordPress Backup Plugin - Version 1.11.28

Version Description

  • 27/Feb/2016 =

  • FIX: When saving settings on multisite, some connections to remote storage could drop and need to be re-made

  • FIX: Fix an inoperative button in the Clone dialog box

  • TWEAK: Updated readme to reflect > 700,000 active sites

  • TWEAK: When cloning a site and mod_rewrite is not available, give a warning pre-restore

  • TWEAK: Options saving on multisite is now much more efficient (in terms of database requests required)

  • TWEAK: Improve the scheduling algorithm in the case of hosts that allow very long runs times, and a network outage on the cloud storage

  • TWEAK: When connecting to updraftplus.com to claim a licence (paid versions), use the newer JSON-based protocol

  • TWEAK: Many and various internal improvements to structure of the admin page HTML, CSS and JS

  • TWEAK: The boxes for adding extra addresses for reporting, and extra DBs, now fade in

Download this release

Release Info

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

Code changes from version 1.11.27 to 1.11.28

admin.php CHANGED
@@ -218,7 +218,6 @@ class UpdraftPlus_Admin {
218
  $this->setup_all_admin_notices_udonly($service);
219
 
220
  add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'), 99999);
221
-
222
  }
223
 
224
  public function updraft_ajaxrestore() {
@@ -439,10 +438,6 @@ class UpdraftPlus_Admin {
439
 
440
  wp_enqueue_script('jquery-blockui', UPDRAFTPLUS_URL.'/includes/jquery.blockUI.js', array('jquery'), '2.70.0');
441
 
442
- $selectric_file = @constant('SCRIPT_DEBUG') ? 'jquery.selectric.js' : 'jquery.selectric.min.js';
443
- wp_enqueue_script('selectric', UPDRAFTPLUS_URL."/includes/selectric/$selectric_file", array('jquery'), '1.9.3');
444
- wp_enqueue_style('selectric', UPDRAFTPLUS_URL.'/includes/selectric/selectric.css', array(), '1.9.3');
445
-
446
  wp_enqueue_script('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.js', array('jquery'), '20150925');
447
  wp_enqueue_style('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.css', array(), '20150925');
448
 
@@ -462,7 +457,7 @@ class UpdraftPlus_Admin {
462
  $mday_selector .= "\n\t<option value='" . $mday_index . "' $selected>" . $mday_index . '</option>';
463
  }
464
 
465
- wp_localize_script( 'updraftplus-admin-ui', 'updraftlion', array(
466
  'sendonlyonwarnings' => __('Send a report only when there are warnings/errors', 'updraftplus'),
467
  'wholebackup' => __('When the Email storage method is enabled, also send the entire backup', 'updraftplus'),
468
  'emailsizelimits' => esc_attr(sprintf(__('Be aware that mail servers tend to have size limits; typically around %s Mb; backups larger than any limits will likely not arrive.','updraftplus'), '10-20')),
@@ -547,15 +542,18 @@ class UpdraftPlus_Admin {
547
  'unsavedsettingsbackup' => __('You have made changes to your settings, and not saved.', 'updraftplus')."\n".__('You should save your changes to ensure that they are used for making your backup.','updraftplus'),
548
  'dayselector' => $day_selector,
549
  'mdayselector' => $mday_selector,
550
- 'ud_url' => UPDRAFTPLUS_URL,
551
  'day' => __('day', 'updraftplus'),
552
  'inthemonth' => __('in the month', 'updraftplus'),
553
  'days' => __('day(s)', 'updraftplus'),
554
  'hours' => __('hour(s)', 'updraftplus'),
555
  'weeks' => __('week(s)', 'updraftplus'),
556
  'forbackupsolderthan' => __('For backups older than', 'updraftplus'),
 
557
  'processing' => __('Processing...', 'updraftplus'),
558
  'pleasefillinrequired' => __('Please fill in the required information.', 'updraftplus'),
 
 
 
559
  ) );
560
  }
561
 
@@ -678,33 +676,8 @@ class UpdraftPlus_Admin {
678
  </script>
679
  <?php
680
 
681
- $this->render_admin_css();
682
-
683
  }
684
 
685
- public function render_admin_css() {
686
- $images_dir = UPDRAFTPLUS_URL.'/images/icons';
687
- ?>
688
- <style type="text/css">
689
- .selectric-items .ico-updraftvault{ background: url(<?php echo $images_dir; ?>/updraftvault.png) no-repeat; }
690
- .selectric-items .ico-dropbox { background: url(<?php echo $images_dir; ?>/dropbox.png) no-repeat; }
691
- .selectric-items .ico-s3 { background: url(<?php echo $images_dir; ?>/s3.png) no-repeat; }
692
- .selectric-items .ico-cloudfiles { background: url(<?php echo $images_dir; ?>/cloudfiles.png) no-repeat; }
693
- .selectric-items .ico-googledrive { background: url(<?php echo $images_dir; ?>/googledrive.png) no-repeat; }
694
- .selectric-items .ico-onedrive { background: url(<?php echo $images_dir; ?>/onedrive.png) no-repeat; }
695
- .selectric-items .ico-azure { background: url(<?php echo $images_dir; ?>/azure.png) no-repeat; }
696
- .selectric-items .ico-ftp { background: url(<?php echo $images_dir; ?>/folder.png) no-repeat; }
697
- .selectric-items .ico-copycom { background: url(<?php echo $images_dir; ?>/copycom.png) no-repeat; }
698
- .selectric-items .ico-sftp { background: url(<?php echo $images_dir; ?>/folder.png) no-repeat; }
699
- .selectric-items .ico-webdav { background: url(<?php echo $images_dir; ?>/webdav.png) no-repeat; }
700
- .selectric-items .ico-s3generic { background: url(<?php echo $images_dir; ?>/folder.png) no-repeat; }
701
- .selectric-items .ico-googlecloud { background: url(<?php echo $images_dir; ?>/googlecloud.png) no-repeat; }
702
- .selectric-items .ico-openstack { background: url(<?php echo $images_dir; ?>/openstack.png) no-repeat; }
703
- .selectric-items .ico-dreamobjects { background: url(<?php echo $images_dir; ?>/dreamobjects.png) no-repeat; }
704
- .selectric-items .ico-email { background: url(<?php echo $images_dir; ?>/email.png) no-repeat; }
705
- </style>
706
- <?php
707
- }
708
 
709
  private function disk_space_check($space) {
710
  global $updraftplus;
@@ -1273,6 +1246,7 @@ class UpdraftPlus_Admin {
1273
  }
1274
 
1275
  if (isset($elements['db'])) {
 
1276
  // Analyse the header of the database file + display results
1277
  list ($mess2, $warn2, $err2, $info) = $updraftplus->analyse_db_file($timestamp, $res);
1278
  $mess = array_merge($mess, $mess2);
@@ -1484,30 +1458,43 @@ class UpdraftPlus_Admin {
1484
  echo @json_encode($history_status);
1485
 
1486
  } elseif (isset($_POST['subaction']) && $_POST['subaction'] == 'credentials_test') {
1487
- $method = (preg_match("/^[a-z0-9]+$/", $_POST['method'])) ? $_POST['method'] : "";
1488
-
1489
- require_once(UPDRAFTPLUS_DIR."/methods/$method.php");
1490
- $objname = "UpdraftPlus_BackupModule_$method";
1491
 
1492
- $this->logged = array();
1493
- # TODO: Add action for WP HTTP SSL stuff
1494
- set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
1495
- if (method_exists($objname, "credentials_test")) {
1496
- $obj = new $objname;
1497
- $obj->credentials_test();
1498
- }
1499
- if (count($this->logged) >0) {
1500
- echo "\n\n".__('Messages:', 'updraftplus')."\n";
1501
- foreach ($this->logged as $err) {
1502
- echo "* $err\n";
1503
- }
1504
- }
1505
- restore_error_handler();
1506
  }
1507
  die;
1508
 
1509
  }
1510
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1511
  // Relevant options (array keys): backup_timestamp, delete_remote,
1512
  public function delete_set($opts) {
1513
 
@@ -2554,7 +2541,7 @@ class UpdraftPlus_Admin {
2554
  <div id="updraft-navtab-settings-content" <?php if (3 != $tabflag) echo 'class="updraft-hidden"'; ?> style="<?php if (3 != $tabflag) echo 'display:none;'; ?>">
2555
  <h2 class="updraft_settings_sectionheading"><?php _e('Backup Contents And Schedule','updraftplus');?></h2>
2556
  <?php UpdraftPlus_Options::options_form_begin(); ?>
2557
- <?php $this->settings_formcontents($last_backup_html); ?>
2558
  </form>
2559
  </div>
2560
 
@@ -3674,16 +3661,26 @@ class UpdraftPlus_Admin {
3674
  } else {
3675
  $dir_info .= __('Backup directory specified exists, but is <b>not</b> writable.','updraftplus');
3676
  }
3677
- $dir_info .= ' <span class="directory-permissions"><a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir').'">'.__('Click here to attempt to create the directory and set the permissions','updraftplus').'</a></span>, '.__('or, to reset this option','updraftplus').' <a href="#" onclick="jQuery(\'#updraft_dir\').val(\'updraft\'); return false;">'.__('click here','updraftplus').'</a>. '.__('If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process.','updraftplus').'</span>';
3678
  }
3679
  return $dir_info;
3680
  }
3681
 
3682
- private function settings_formcontents($last_backup_html) {
3683
 
3684
  global $updraftplus;
3685
 
3686
  $updraft_dir = $updraftplus->backups_dir_location();
 
 
 
 
 
 
 
 
 
 
3687
 
3688
  ?>
3689
  <table class="form-table">
@@ -3691,7 +3688,7 @@ class UpdraftPlus_Admin {
3691
  <th><?php _e('Files backup schedule','updraftplus'); ?>:</th>
3692
  <td>
3693
  <div style="float:left; clear:both;">
3694
- <select id="updraft_interval" name="updraft_interval" onchange="jQuery(document).trigger('updraftplus_interval_changed'); updraft_check_same_times();">
3695
  <?php
3696
  $intervals = $this->get_intervals();
3697
  $selected_interval = UpdraftPlus_Options::get_updraft_option('updraft_interval', 'manual');
@@ -3701,7 +3698,7 @@ class UpdraftPlus_Admin {
3701
  echo ">".htmlspecialchars($descrip)."</option>\n";
3702
  }
3703
  ?>
3704
- </select> <span id="updraft_files_timings"><?php echo apply_filters('updraftplus_schedule_showfileopts', '<input type="hidden" name="updraftplus_starttime_files" value="">', $selected_interval); ?></span>
3705
 
3706
 
3707
  <?php
@@ -3720,7 +3717,7 @@ class UpdraftPlus_Admin {
3720
  </tr>
3721
 
3722
  <?php if (defined('UPDRAFTPLUS_EXPERIMENTAL') && UPDRAFTPLUS_EXPERIMENTAL) { ?>
3723
- <tr id="updraft_incremental_row">
3724
  <th><?php _e('Incremental file backup schedule', 'updraftplus'); ?>:</th>
3725
  <td>
3726
  <?php do_action('updraftplus_incremental_cell', $selected_interval); ?>
@@ -3734,7 +3731,7 @@ class UpdraftPlus_Admin {
3734
  <th><?php _e('Database backup schedule','updraftplus'); ?>:</th>
3735
  <td>
3736
  <div style="float:left; clear:both;">
3737
- <select id="updraft_interval_database" name="updraft_interval_database" onchange="updraft_check_same_times();">
3738
  <?php
3739
  $selected_interval_db = UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'));
3740
  foreach ($intervals as $cronsched => $descrip) {
@@ -3743,8 +3740,7 @@ class UpdraftPlus_Admin {
3743
  echo ">$descrip</option>\n";
3744
  }
3745
  ?>
3746
- </select> <span id="updraft_same_schedules_message"><?php echo apply_filters('updraftplus_schedule_sametimemsg', '');?></span><span id="updraft_db_timings"><?php echo apply_filters('updraftplus_schedule_showdbopts', '<input type="hidden" name="updraftplus_starttime_db" value="">', $selected_interval_db); ?></span>
3747
-
3748
 
3749
  <?php
3750
  $updraft_retain_db = max((int)UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain), 1);
@@ -3758,7 +3754,7 @@ class UpdraftPlus_Admin {
3758
  </td>
3759
  </tr>
3760
  <tr class="backup-interval-description">
3761
- <th><?php do_action('updraftplus_timeconfig_extrarow_header'); ?></th>
3762
  <td><div>
3763
  <?php
3764
  echo apply_filters('updraftplus_fixtime_ftinfo', '<p>'.__('To fix the time at which a backup should take place,','updraftplus').' ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), '.__('or to configure more complex schedules', 'updraftplus').', <a href="https://updraftplus.com/shop/updraftplus-premium/">'.htmlspecialchars(__('use UpdraftPlus Premium', 'updraftplus')).'</a></p>');
@@ -3770,41 +3766,42 @@ class UpdraftPlus_Admin {
3770
  <h2 class="updraft_settings_sectionheading"><?php _e('Sending Your Backup To Remote Storage','updraftplus');?></h2>
3771
 
3772
  <?php
3773
- $debug_mode = (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) ? 'checked="checked"' : "";
3774
- // Should be one of s3, dropbox, ftp, googledrive, email, or whatever else is added
3775
  $active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
3776
  ?>
3777
 
3778
  <table class="form-table width-900">
3779
  <tr>
3780
- <th><?php _e('Choose your remote storage','updraftplus'); do_action('updraftplus_after_remote_storage_heading');?>:</th>
3781
- <td><?php
3782
-
3783
- if (false === apply_filters('updraftplus_storage_printoptions', false, $active_service)) {
 
 
3784
  if (is_array($active_service)) $active_service = $updraftplus->just_one($active_service);
3785
- ?>
3786
-
3787
- <select name="updraft_service" id="updraft-service" class="icon-dropdown">
3788
- <option value="none" <?php
3789
- if ('none' === $active_service) echo ' selected="selected"'; ?>><?php _e('None','updraftplus'); ?></option>
3790
- <?php
3791
- foreach ($updraftplus->backup_methods as $method => $description) {
3792
- echo "<option value=\"$method\"";
3793
- if ($active_service === $method || (is_array($active_service) && in_array($method, $active_service))) echo ' selected="selected"';
3794
- echo '>'.$description;
3795
- echo "</option>\n";
3796
  }
 
 
 
 
 
 
 
 
 
 
3797
  ?>
3798
- </select>
3799
-
3800
- <?php echo '<p><a href="https://updraftplus.com/shop/morestorage/">'.htmlspecialchars(__('You can send a backup to more than one destination with an add-on.','updraftplus')).'</a></p>'; ?>
3801
-
3802
- </td>
3803
- </tr>
3804
-
3805
- <?php } ?>
3806
 
3807
- <tr class="updraftplusmethod none" style="display:none;">
3808
  <td></td>
3809
  <td><em><?php echo htmlspecialchars(__('If you choose no remote storage, then the backups remain on the web-server. This is not recommended (unless you plan to manually copy them to your computer), as losing the web-server would mean losing both your website and the backups in one event.', 'updraftplus'));?></em></td>
3810
  </tr>
@@ -3850,12 +3847,15 @@ class UpdraftPlus_Admin {
3850
  ?>
3851
  </td>
3852
  </tr>
 
 
 
3853
  <tr class="backup-crypt-description">
3854
  <td></td>
3855
 
3856
  <td>
3857
 
3858
- <a href="#" onclick="jQuery('#updraftplus_db_decrypt').val(jQuery('#updraft_encryptionphrase').val()); jQuery('#updraft-manualdecrypt-modal').slideToggle(); return false;"><?php _e('You can manually decrypt an encrypted database here.','updraftplus');?></a>
3859
 
3860
  <div id="updraft-manualdecrypt-modal" class="updraft-hidden" style="display:none;">
3861
  <p><h3><?php _e("Manually decrypt a database backup file" ,'updraftplus');?></h3></p>
@@ -3887,6 +3887,8 @@ class UpdraftPlus_Admin {
3887
 
3888
  </td>
3889
  </tr>
 
 
3890
 
3891
  <?php
3892
  #'<a href="https://updraftplus.com/shop/updraftplus-premium/">'.__("This feature is part of UpdraftPlus Premium.", 'updraftplus').'</a>'
@@ -3934,33 +3936,7 @@ class UpdraftPlus_Admin {
3934
 
3935
  <script type="text/javascript">
3936
  /* <![CDATA[ */
3937
-
3938
- jQuery(document).ready(function() {
3939
- <?php
3940
- $really_is_writable = $updraftplus->really_is_writable($updraft_dir);
3941
- if (!$really_is_writable) echo "jQuery('.backupdirrow').show();\n";
3942
- ?>
3943
- <?php
3944
- if (!empty($active_service)) {
3945
- if (is_array($active_service)) {
3946
- foreach ($active_service as $serv) {
3947
- echo "jQuery('.${serv}').show();\n";
3948
- }
3949
- } else {
3950
- echo "jQuery('.${active_service}').show();\n";
3951
- }
3952
- } else {
3953
- echo "jQuery('.none').show();\n";
3954
- }
3955
- foreach ($updraftplus->backup_methods as $method => $description) {
3956
- // already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
3957
- $call_method = "UpdraftPlus_BackupModule_$method";
3958
- if (method_exists($call_method, 'config_print_javascript_onready')) {
3959
- $method_objects[$method]->config_print_javascript_onready();
3960
- }
3961
- }
3962
- ?>
3963
- });
3964
  /* ]]> */
3965
  </script>
3966
  <table class="form-table width-900">
@@ -3970,7 +3946,7 @@ class UpdraftPlus_Admin {
3970
 
3971
  <tr>
3972
  <th><?php _e('Expert settings','updraftplus');?>:</th>
3973
- <td><a id="enableexpertmode" href="#enableexpertmode"><?php _e('Show expert settings','updraftplus');?></a> - <?php _e("click this to show some further options; don't bother with this unless you have a problem or are curious.",'updraftplus');?> <?php do_action('updraftplus_expertsettingsdescription'); ?></td>
3974
  </tr>
3975
  <?php
3976
  $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
@@ -3986,7 +3962,7 @@ class UpdraftPlus_Admin {
3986
 
3987
  <tr class="expertmode updraft-hidden" style="display:none;">
3988
  <th><?php _e('Split archives every:','updraftplus');?></th>
3989
- <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'), 400); ?></td>
3990
  </tr>
3991
 
3992
  <tr class="deletelocal expertmode updraft-hidden" style="display:none;">
@@ -3999,28 +3975,33 @@ class UpdraftPlus_Admin {
3999
  <td><input type="text" name="updraft_dir" id="updraft_dir" style="width:525px" value="<?php echo htmlspecialchars($this->prune_updraft_dir_prefix($updraft_dir)); ?>" /></td>
4000
  </tr>
4001
  <tr class="expertmode backupdirrow updraft-hidden" style="display:none;">
4002
- <td></td><td>
 
4003
  <span id="updraft_writable_mess">
4004
  <?php
4005
- //moved into function for ajax save
4006
- $dir_info = $this->really_writable_message($really_is_writable, $updraft_dir);
4007
- echo $dir_info.'</span> '.__("This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. It is relative to your content directory (which by default is called wp-content).", 'updraftplus').' '.__("<b>Do not</b> place it inside your uploads or plugins directory, as that will cause recursion (backups of backups of backups of...).",'updraftplus');?></td>
4008
-
 
 
 
 
4009
  </tr>
4010
 
4011
  <tr class="expertmode updraft-hidden" style="display:none;">
4012
- <th><?php _e('Use the server\'s SSL certificates','updraftplus');?>:</th>
4013
- <td><input type="checkbox" id="updraft_ssl_useservercerts" name="updraft_ssl_useservercerts" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_useservercerts"><?php _e('By default UpdraftPlus uses its own store of SSL certificates to verify the identity of remote sites (i.e. to make sure it is talking to the real Dropbox, Amazon S3, etc., and not an attacker). We keep these up to date. However, if you get an SSL error, then choosing this option (which causes UpdraftPlus to use your web server\'s collection instead) may help.','updraftplus');?></label></td>
4014
  </tr>
4015
 
4016
  <tr class="expertmode updraft-hidden" style="display:none;">
4017
  <th><?php _e('Do not verify SSL certificates','updraftplus');?>:</th>
4018
- <td><input type="checkbox" id="updraft_ssl_disableverify" name="updraft_ssl_disableverify" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_disableverify"><?php _e('Choosing this option lowers your security by stopping UpdraftPlus from verifying the identity of encrypted sites that it connects to (e.g. Dropbox, Google Drive). It means that UpdraftPlus will be using SSL only for encryption of traffic, and not for authentication.','updraftplus');?> <?php _e('Note that not all cloud backup methods are necessarily using SSL authentication.', 'updraftplus');?></label></td>
4019
  </tr>
4020
 
4021
  <tr class="expertmode updraft-hidden" style="display:none;">
4022
  <th><?php _e('Disable SSL entirely where possible', 'updraftplus');?>:</th>
4023
- <td><input type="checkbox" id="updraft_ssl_nossl" name="updraft_ssl_nossl" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_nossl"><?php _e('Choosing this option lowers your security by stopping UpdraftPlus from using SSL for authentication and encrypted transport at all, where possible. Note that some cloud storage providers do not allow this (e.g. Dropbox), so with those providers this setting will have no effect.','updraftplus');?> <a href="https://updraftplus.com/faqs/i-get-ssl-certificate-errors-when-backing-up-andor-restoring/"><?php _e('See this FAQ also.', 'updraftplus');?></a></label></td>
4024
  </tr>
4025
 
4026
  <?php do_action('updraftplus_configprint_expertoptions'); ?>
@@ -4029,17 +4010,16 @@ class UpdraftPlus_Admin {
4029
  <td></td>
4030
  <td>
4031
  <?php
4032
- $ws_ad = $updraftplus->wordshell_random_advert(1);
4033
  if ($ws_ad) {
4034
- ?>
4035
- <p class="wordshell-advert">
4036
- <?php echo $ws_ad; ?>
4037
- </p>
4038
- <?php
4039
- }
4040
- ?>
4041
  </td>
4042
  </tr>
 
4043
  <tr>
4044
  <td></td>
4045
  <td>
@@ -4047,10 +4027,48 @@ class UpdraftPlus_Admin {
4047
  <input type="submit" class="button-primary" id="updraftplus-settings-save" value="<?php _e('Save Changes','updraftplus');?>" />
4048
  </td>
4049
  </tr>
 
4050
  </table>
4051
  <?php
4052
  }
4053
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4054
  // $include_more can be (bool) or (string)"sometimes"
4055
  public function files_selector_widgetry($prefix = '', $show_exclusion_options = true, $include_more = true) {
4056
 
@@ -4064,7 +4082,9 @@ class UpdraftPlus_Admin {
4064
  $included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key", apply_filters("updraftplus_defaultoption_include_".$key, true))) ? 'checked="checked"' : "";
4065
  if ('others' == $key || 'uploads' == $key) {
4066
 
4067
- $ret .= '<input class="updraft_include_entity" id="'.$prefix.'updraft_include_'.$key.'" type="checkbox" name="updraft_include_'.$key.'" value="1" '.$included.'> <label '.(('others' == $key) ? 'title="'.sprintf(__('Your wp-content directory server path: %s', 'updraftplus'), WP_CONTENT_DIR).'" ' : '').' for="'.$prefix.'updraft_include_'.$key.'">'.(('others' == $key) ? __('Any other directories found inside wp-content', 'updraftplus') : htmlspecialchars($info['description'])).'</label><br>';
 
 
4068
 
4069
  if ($show_exclusion_options) {
4070
  $include_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_'.$key.'_exclude', ('others' == $key) ? UPDRAFT_DEFAULT_OTHERS_EXCLUDE : UPDRAFT_DEFAULT_UPLOADS_EXCLUDE);
@@ -4083,7 +4103,10 @@ class UpdraftPlus_Admin {
4083
  } else {
4084
 
4085
  if ($key != 'more' || true === $include_more || ('sometimes' === $include_more && !empty($include_more_paths))) {
4086
- $ret .= "<input class=\"updraft_include_entity\" id=\"".$prefix."updraft_include_$key\" type=\"checkbox\" name=\"updraft_include_$key\" value=\"1\" $included /><label for=\"".$prefix."updraft_include_$key\"".((isset($info['htmltitle'])) ? ' title="'.htmlspecialchars($info['htmltitle']).'"' : '')."> ".htmlspecialchars($info['description']);
 
 
 
4087
 
4088
  $ret .= "</label><br>";
4089
  $ret .= apply_filters("updraftplus_config_option_include_$key", '', $prefix);
@@ -5129,6 +5152,11 @@ ENDHERE;
5129
 
5130
  $relevant_keys = $updraftplus->get_settings_keys();
5131
 
 
 
 
 
 
5132
  foreach ($settings as $key => $value) {
5133
  // $exclude_keys = array('option_page', 'action', '_wpnonce', '_wp_http_referer');
5134
 
@@ -5140,14 +5168,14 @@ ENDHERE;
5140
  }
5141
  }
5142
 
5143
- $updated = UpdraftPlus_Options::update_updraft_option($key, $value);
5144
 
5145
  // Add information on what has changed to array to loop through to update links etc.
5146
  if ($updated){
5147
  $return_array['changed'][$key] = $value;
5148
- } elseif ($key == 'updraft_interval'){ //To schedule a database when the interval is not changed.
5149
  $updraftplus->schedule_backup($value);
5150
- } elseif ($key == 'updraft_interval_database'){
5151
  $updraftplus->schedule_backup_database($value);
5152
  }
5153
  } else {
218
  $this->setup_all_admin_notices_udonly($service);
219
 
220
  add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'), 99999);
 
221
  }
222
 
223
  public function updraft_ajaxrestore() {
438
 
439
  wp_enqueue_script('jquery-blockui', UPDRAFTPLUS_URL.'/includes/jquery.blockUI.js', array('jquery'), '2.70.0');
440
 
 
 
 
 
441
  wp_enqueue_script('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.js', array('jquery'), '20150925');
442
  wp_enqueue_style('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.css', array(), '20150925');
443
 
457
  $mday_selector .= "\n\t<option value='" . $mday_index . "' $selected>" . $mday_index . '</option>';
458
  }
459
 
460
+ wp_localize_script('updraftplus-admin-ui', 'updraftlion', array(
461
  'sendonlyonwarnings' => __('Send a report only when there are warnings/errors', 'updraftplus'),
462
  'wholebackup' => __('When the Email storage method is enabled, also send the entire backup', 'updraftplus'),
463
  'emailsizelimits' => esc_attr(sprintf(__('Be aware that mail servers tend to have size limits; typically around %s Mb; backups larger than any limits will likely not arrive.','updraftplus'), '10-20')),
542
  'unsavedsettingsbackup' => __('You have made changes to your settings, and not saved.', 'updraftplus')."\n".__('You should save your changes to ensure that they are used for making your backup.','updraftplus'),
543
  'dayselector' => $day_selector,
544
  'mdayselector' => $mday_selector,
 
545
  'day' => __('day', 'updraftplus'),
546
  'inthemonth' => __('in the month', 'updraftplus'),
547
  'days' => __('day(s)', 'updraftplus'),
548
  'hours' => __('hour(s)', 'updraftplus'),
549
  'weeks' => __('week(s)', 'updraftplus'),
550
  'forbackupsolderthan' => __('For backups older than', 'updraftplus'),
551
+ 'ud_url' => UPDRAFTPLUS_URL,
552
  'processing' => __('Processing...', 'updraftplus'),
553
  'pleasefillinrequired' => __('Please fill in the required information.', 'updraftplus'),
554
+ 'test_settings' => __('Test %s Settings', 'updraftplus'),
555
+ 'testing_settings' => __('Testing %s Settings...', 'updraftplus'),
556
+ 'settings_test_result' => __('%s settings test result:', 'updraftplus'),
557
  ) );
558
  }
559
 
676
  </script>
677
  <?php
678
 
 
 
679
  }
680
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
 
682
  private function disk_space_check($space) {
683
  global $updraftplus;
1246
  }
1247
 
1248
  if (isset($elements['db'])) {
1249
+
1250
  // Analyse the header of the database file + display results
1251
  list ($mess2, $warn2, $err2, $info) = $updraftplus->analyse_db_file($timestamp, $res);
1252
  $mess = array_merge($mess, $mess2);
1458
  echo @json_encode($history_status);
1459
 
1460
  } elseif (isset($_POST['subaction']) && $_POST['subaction'] == 'credentials_test') {
1461
+
1462
+ $this->do_credentials_test($_POST);
1463
+ die;
 
1464
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1465
  }
1466
  die;
1467
 
1468
  }
1469
 
1470
+ // This echoes output; so, you will need to do output buffering if you want to capture it
1471
+ public function do_credentials_test($test_settings) {
1472
+
1473
+ $method = (!empty($test_settings['method']) && preg_match("/^[a-z0-9]+$/", $test_settings['method'])) ? $test_settings['method'] : "";
1474
+
1475
+ $objname = "UpdraftPlus_BackupModule_$method";
1476
+
1477
+ $this->logged = array();
1478
+ # TODO: Add action for WP HTTP SSL stuff
1479
+ set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
1480
+
1481
+ if (!class_exists($objname)) include_once(UPDRAFTPLUS_DIR."/methods/$method.php");
1482
+
1483
+ # TODO: Add action for WP HTTP SSL stuff
1484
+ if (method_exists($objname, "credentials_test")) {
1485
+ $obj = new $objname;
1486
+ $obj->credentials_test($test_settings);
1487
+ }
1488
+
1489
+ if (count($this->logged) >0) {
1490
+ echo "\n\n".__('Messages:', 'updraftplus')."\n";
1491
+ foreach ($this->logged as $err) {
1492
+ echo "* $err\n";
1493
+ }
1494
+ }
1495
+ restore_error_handler();
1496
+ }
1497
+
1498
  // Relevant options (array keys): backup_timestamp, delete_remote,
1499
  public function delete_set($opts) {
1500
 
2541
  <div id="updraft-navtab-settings-content" <?php if (3 != $tabflag) echo 'class="updraft-hidden"'; ?> style="<?php if (3 != $tabflag) echo 'display:none;'; ?>">
2542
  <h2 class="updraft_settings_sectionheading"><?php _e('Backup Contents And Schedule','updraftplus');?></h2>
2543
  <?php UpdraftPlus_Options::options_form_begin(); ?>
2544
+ <?php $this->settings_formcontents(); ?>
2545
  </form>
2546
  </div>
2547
 
3661
  } else {
3662
  $dir_info .= __('Backup directory specified exists, but is <b>not</b> writable.','updraftplus');
3663
  }
3664
+ $dir_info .= '<span class="directory-permissions"><a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir').'">'.__('Click here to attempt to create the directory and set the permissions','updraftplus').'</a></span>, '.__('or, to reset this option','updraftplus').' <a href="#" class="updraft_backup_dir_reset">'.__('click here','updraftplus').'</a>. '.__('If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process.','updraftplus').'</span>';
3665
  }
3666
  return $dir_info;
3667
  }
3668
 
3669
+ public function settings_formcontents($options = array()) {
3670
 
3671
  global $updraftplus;
3672
 
3673
  $updraft_dir = $updraftplus->backups_dir_location();
3674
+ $really_is_writable = $updraftplus->really_is_writable($updraft_dir);
3675
+
3676
+ $default_options = array(
3677
+ 'include_database_decrypter' => true,
3678
+ 'include_adverts' => true,
3679
+ 'include_save_button' => true
3680
+ );
3681
+ foreach ($default_options as $k => $v) {
3682
+ if (!isset($options[$k])) $options[$k] = $v;
3683
+ }
3684
 
3685
  ?>
3686
  <table class="form-table">
3688
  <th><?php _e('Files backup schedule','updraftplus'); ?>:</th>
3689
  <td>
3690
  <div style="float:left; clear:both;">
3691
+ <select class="updraft_interval" name="updraft_interval">
3692
  <?php
3693
  $intervals = $this->get_intervals();
3694
  $selected_interval = UpdraftPlus_Options::get_updraft_option('updraft_interval', 'manual');
3698
  echo ">".htmlspecialchars($descrip)."</option>\n";
3699
  }
3700
  ?>
3701
+ </select> <span class="updraft_files_timings"><?php echo apply_filters('updraftplus_schedule_showfileopts', '<input type="hidden" name="updraftplus_starttime_files" value="">', $selected_interval); ?></span>
3702
 
3703
 
3704
  <?php
3717
  </tr>
3718
 
3719
  <?php if (defined('UPDRAFTPLUS_EXPERIMENTAL') && UPDRAFTPLUS_EXPERIMENTAL) { ?>
3720
+ <tr class="updraft_incremental_row">
3721
  <th><?php _e('Incremental file backup schedule', 'updraftplus'); ?>:</th>
3722
  <td>
3723
  <?php do_action('updraftplus_incremental_cell', $selected_interval); ?>
3731
  <th><?php _e('Database backup schedule','updraftplus'); ?>:</th>
3732
  <td>
3733
  <div style="float:left; clear:both;">
3734
+ <select class="updraft_interval_database" name="updraft_interval_database">
3735
  <?php
3736
  $selected_interval_db = UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'));
3737
  foreach ($intervals as $cronsched => $descrip) {
3740
  echo ">$descrip</option>\n";
3741
  }
3742
  ?>
3743
+ </select> <span class="updraft_same_schedules_message"><?php echo apply_filters('updraftplus_schedule_sametimemsg', '');?></span><span class="updraft_db_timings"><?php echo apply_filters('updraftplus_schedule_showdbopts', '<input type="hidden" name="updraftplus_starttime_db" value="">', $selected_interval_db); ?></span>
 
3744
 
3745
  <?php
3746
  $updraft_retain_db = max((int)UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain), 1);
3754
  </td>
3755
  </tr>
3756
  <tr class="backup-interval-description">
3757
+ <th></th>
3758
  <td><div>
3759
  <?php
3760
  echo apply_filters('updraftplus_fixtime_ftinfo', '<p>'.__('To fix the time at which a backup should take place,','updraftplus').' ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), '.__('or to configure more complex schedules', 'updraftplus').', <a href="https://updraftplus.com/shop/updraftplus-premium/">'.htmlspecialchars(__('use UpdraftPlus Premium', 'updraftplus')).'</a></p>');
3766
  <h2 class="updraft_settings_sectionheading"><?php _e('Sending Your Backup To Remote Storage','updraftplus');?></h2>
3767
 
3768
  <?php
3769
+ $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode') ? 'checked="checked"' : "";
 
3770
  $active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
3771
  ?>
3772
 
3773
  <table class="form-table width-900">
3774
  <tr>
3775
+ <th><?php
3776
+ echo __('Choose your remote storage','updraftplus').'<br>'.apply_filters('updraftplus_after_remote_storage_heading_message', '<em>'.__('(tap on an icon to select or unselect)', 'updraftplus').'</em>');
3777
+ ?>:</th>
3778
+ <td>
3779
+ <div id="remote-storage-container">
3780
+ <?php
3781
  if (is_array($active_service)) $active_service = $updraftplus->just_one($active_service);
3782
+
3783
+ //Change this to give a class that we can exclude
3784
+ $multi = apply_filters('updraftplus_storage_printoptions_multi', '');
3785
+
3786
+ foreach($updraftplus->backup_methods as $method => $description) {
3787
+ echo "<input name=\"updraft_service[]\" class=\"updraft_servicecheckbox $method $multi\" id=\"updraft_servicecheckbox_$method\" type=\"checkbox\" value=\"$method\"";
3788
+ if ($active_service === $method || (is_array($active_service) && in_array($method, $active_service))) echo ' checked="checked"';
3789
+ echo " data-labelauty=\"".esc_attr($description)."\">";
 
 
 
3790
  }
3791
+ ?>
3792
+
3793
+
3794
+ <?php
3795
+ if (false === apply_filters('updraftplus_storage_printoptions', false, $active_service)) {
3796
+
3797
+ echo '</div>';
3798
+ echo '<p><a href="https://updraftplus.com/shop/morestorage/">'.htmlspecialchars(__('You can send a backup to more than one destination with an add-on.','updraftplus')).'</a></p>';
3799
+ echo '</td></tr>';
3800
+ }
3801
  ?>
3802
+
 
 
 
 
 
 
 
3803
 
3804
+ <tr class="updraftplusmethod none ud_nostorage" style="display:none;">
3805
  <td></td>
3806
  <td><em><?php echo htmlspecialchars(__('If you choose no remote storage, then the backups remain on the web-server. This is not recommended (unless you plan to manually copy them to your computer), as losing the web-server would mean losing both your website and the backups in one event.', 'updraftplus'));?></em></td>
3807
  </tr>
3847
  ?>
3848
  </td>
3849
  </tr>
3850
+
3851
+ <?php if (!empty($options['include_database_decrypter'])) { ?>
3852
+
3853
  <tr class="backup-crypt-description">
3854
  <td></td>
3855
 
3856
  <td>
3857
 
3858
+ <a href="#" class="updraft_show_decryption_widget"><?php _e('You can manually decrypt an encrypted database here.','updraftplus');?></a>
3859
 
3860
  <div id="updraft-manualdecrypt-modal" class="updraft-hidden" style="display:none;">
3861
  <p><h3><?php _e("Manually decrypt a database backup file" ,'updraftplus');?></h3></p>
3887
 
3888
  </td>
3889
  </tr>
3890
+
3891
+ <?php } ?>
3892
 
3893
  <?php
3894
  #'<a href="https://updraftplus.com/shop/updraftplus-premium/">'.__("This feature is part of UpdraftPlus Premium.", 'updraftplus').'</a>'
3936
 
3937
  <script type="text/javascript">
3938
  /* <![CDATA[ */
3939
+ <?php echo $this->get_settings_js($method_objects, $really_is_writable, $updraft_dir); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3940
  /* ]]> */
3941
  </script>
3942
  <table class="form-table width-900">
3946
 
3947
  <tr>
3948
  <th><?php _e('Expert settings','updraftplus');?>:</th>
3949
+ <td><a class="enableexpertmode" href="#enableexpertmode"><?php _e('Show expert settings','updraftplus');?></a> - <?php _e("click this to show some further options; don't bother with this unless you have a problem or are curious.",'updraftplus');?> <?php do_action('updraftplus_expertsettingsdescription'); ?></td>
3950
  </tr>
3951
  <?php
3952
  $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
3962
 
3963
  <tr class="expertmode updraft-hidden" style="display:none;">
3964
  <th><?php _e('Split archives every:','updraftplus');?></th>
3965
+ <td><input type="text" name="updraft_split_every" class="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'), 400); ?></td>
3966
  </tr>
3967
 
3968
  <tr class="deletelocal expertmode updraft-hidden" style="display:none;">
3975
  <td><input type="text" name="updraft_dir" id="updraft_dir" style="width:525px" value="<?php echo htmlspecialchars($this->prune_updraft_dir_prefix($updraft_dir)); ?>" /></td>
3976
  </tr>
3977
  <tr class="expertmode backupdirrow updraft-hidden" style="display:none;">
3978
+ <td></td>
3979
+ <td>
3980
  <span id="updraft_writable_mess">
3981
  <?php
3982
+ $dir_info = $this->really_writable_message($really_is_writable, $updraft_dir);
3983
+ echo $dir_info;
3984
+ ?>
3985
+ </span>
3986
+ <?php
3987
+ echo __("This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. It is relative to your content directory (which by default is called wp-content).", 'updraftplus').' '.__("<b>Do not</b> place it inside your uploads or plugins directory, as that will cause recursion (backups of backups of backups of...).", 'updraftplus');
3988
+ ?>
3989
+ </td>
3990
  </tr>
3991
 
3992
  <tr class="expertmode updraft-hidden" style="display:none;">
3993
+ <th><?php _e("Use the server's SSL certificates", 'updraftplus');?>:</th>
3994
+ <td><input data-updraft_settings_test="useservercerts" type="checkbox" id="updraft_ssl_useservercerts" name="updraft_ssl_useservercerts" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_useservercerts"><?php _e('By default UpdraftPlus uses its own store of SSL certificates to verify the identity of remote sites (i.e. to make sure it is talking to the real Dropbox, Amazon S3, etc., and not an attacker). We keep these up to date. However, if you get an SSL error, then choosing this option (which causes UpdraftPlus to use your web server\'s collection instead) may help.','updraftplus');?></label></td>
3995
  </tr>
3996
 
3997
  <tr class="expertmode updraft-hidden" style="display:none;">
3998
  <th><?php _e('Do not verify SSL certificates','updraftplus');?>:</th>
3999
+ <td><input data-updraft_settings_test="disableverify" type="checkbox" id="updraft_ssl_disableverify" name="updraft_ssl_disableverify" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_disableverify"><?php _e('Choosing this option lowers your security by stopping UpdraftPlus from verifying the identity of encrypted sites that it connects to (e.g. Dropbox, Google Drive). It means that UpdraftPlus will be using SSL only for encryption of traffic, and not for authentication.','updraftplus');?> <?php _e('Note that not all cloud backup methods are necessarily using SSL authentication.', 'updraftplus');?></label></td>
4000
  </tr>
4001
 
4002
  <tr class="expertmode updraft-hidden" style="display:none;">
4003
  <th><?php _e('Disable SSL entirely where possible', 'updraftplus');?>:</th>
4004
+ <td><input data-updraft_settings_test="nossl" type="checkbox" id="updraft_ssl_nossl" name="updraft_ssl_nossl" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_nossl"><?php _e('Choosing this option lowers your security by stopping UpdraftPlus from using SSL for authentication and encrypted transport at all, where possible. Note that some cloud storage providers do not allow this (e.g. Dropbox), so with those providers this setting will have no effect.','updraftplus');?> <a href="https://updraftplus.com/faqs/i-get-ssl-certificate-errors-when-backing-up-andor-restoring/"><?php _e('See this FAQ also.', 'updraftplus');?></a></label></td>
4005
  </tr>
4006
 
4007
  <?php do_action('updraftplus_configprint_expertoptions'); ?>
4010
  <td></td>
4011
  <td>
4012
  <?php
4013
+ $ws_ad = empty($options['include_adverts']) ? false : $updraftplus->wordshell_random_advert(1);
4014
  if ($ws_ad) {
4015
+ ?>
4016
+ <p class="wordshell-advert">
4017
+ <?php echo $ws_ad; ?>
4018
+ </p>
4019
+ <?php } ?>
 
 
4020
  </td>
4021
  </tr>
4022
+ <?php if (!empty($options['include_save_button'])) { ?>
4023
  <tr>
4024
  <td></td>
4025
  <td>
4027
  <input type="submit" class="button-primary" id="updraftplus-settings-save" value="<?php _e('Save Changes','updraftplus');?>" />
4028
  </td>
4029
  </tr>
4030
+ <?php } ?>
4031
  </table>
4032
  <?php
4033
  }
4034
 
4035
+ private function get_settings_js($method_objects, $really_is_writable, $updraft_dir) {
4036
+
4037
+ global $updraftplus;
4038
+
4039
+ ob_start();
4040
+ ?>
4041
+ jQuery(document).ready(function() {
4042
+ <?php
4043
+ if (!$really_is_writable) echo "jQuery('.backupdirrow').show();\n";
4044
+ ?>
4045
+ <?php
4046
+ if (!empty($active_service)) {
4047
+ if (is_array($active_service)) {
4048
+ foreach ($active_service as $serv) {
4049
+ echo "jQuery('.${serv}').show();\n";
4050
+ }
4051
+ } else {
4052
+ echo "jQuery('.${active_service}').show();\n";
4053
+ }
4054
+ } else {
4055
+ echo "jQuery('.none').show();\n";
4056
+ }
4057
+ foreach ($updraftplus->backup_methods as $method => $description) {
4058
+ // already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
4059
+ $call_method = "UpdraftPlus_BackupModule_$method";
4060
+ if (method_exists($call_method, 'config_print_javascript_onready')) {
4061
+ $method_objects[$method]->config_print_javascript_onready();
4062
+ }
4063
+ }
4064
+ ?>
4065
+ });
4066
+ <?php
4067
+ $ret = ob_get_contents();
4068
+ ob_end_clean();
4069
+ return $ret;
4070
+ }
4071
+
4072
  // $include_more can be (bool) or (string)"sometimes"
4073
  public function files_selector_widgetry($prefix = '', $show_exclusion_options = true, $include_more = true) {
4074
 
4082
  $included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key", apply_filters("updraftplus_defaultoption_include_".$key, true))) ? 'checked="checked"' : "";
4083
  if ('others' == $key || 'uploads' == $key) {
4084
 
4085
+ $data_toggle_exclude_field = $show_exclusion_options ? 'data-toggle_exclude_field="'.$key.'"' : '';
4086
+
4087
+ $ret .= '<input class="updraft_include_entity" id="'.$prefix.'updraft_include_'.$key.'" '.$data_toggle_exclude_field.' type="checkbox" name="updraft_include_'.$key.'" value="1" '.$included.'> <label '.(('others' == $key) ? 'title="'.sprintf(__('Your wp-content directory server path: %s', 'updraftplus'), WP_CONTENT_DIR).'" ' : '').' for="'.$prefix.'updraft_include_'.$key.'">'.(('others' == $key) ? __('Any other directories found inside wp-content', 'updraftplus') : htmlspecialchars($info['description'])).'</label><br>';
4088
 
4089
  if ($show_exclusion_options) {
4090
  $include_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_'.$key.'_exclude', ('others' == $key) ? UPDRAFT_DEFAULT_OTHERS_EXCLUDE : UPDRAFT_DEFAULT_UPLOADS_EXCLUDE);
4103
  } else {
4104
 
4105
  if ($key != 'more' || true === $include_more || ('sometimes' === $include_more && !empty($include_more_paths))) {
4106
+
4107
+ $data_toggle_exclude_field = $show_exclusion_options ? 'data-toggle_exclude_field="'.$key.'"' : '';
4108
+
4109
+ $ret .= "<input class=\"updraft_include_entity\" $data_toggle_exclude_field id=\"".$prefix."updraft_include_$key\" type=\"checkbox\" name=\"updraft_include_$key\" value=\"1\" $included /><label for=\"".$prefix."updraft_include_$key\"".((isset($info['htmltitle'])) ? ' title="'.htmlspecialchars($info['htmltitle']).'"' : '')."> ".htmlspecialchars($info['description']);
4110
 
4111
  $ret .= "</label><br>";
4112
  $ret .= apply_filters("updraftplus_config_option_include_$key", '', $prefix);
5152
 
5153
  $relevant_keys = $updraftplus->get_settings_keys();
5154
 
5155
+ if (method_exists('UpdraftPlus_Options', 'mass_options_update')) {
5156
+ $settings = UpdraftPlus_Options::mass_options_update($settings);
5157
+ $mass_updated = true;
5158
+ }
5159
+
5160
  foreach ($settings as $key => $value) {
5161
  // $exclude_keys = array('option_page', 'action', '_wpnonce', '_wp_http_referer');
5162
 
5168
  }
5169
  }
5170
 
5171
+ $updated = empty($mass_updated) ? UpdraftPlus_Options::update_updraft_option($key, $value) : true;
5172
 
5173
  // Add information on what has changed to array to loop through to update links etc.
5174
  if ($updated){
5175
  $return_array['changed'][$key] = $value;
5176
+ } elseif (empty($mass_updated) && $key == 'updraft_interval') { //To schedule a database when the interval is not changed.
5177
  $updraftplus->schedule_backup($value);
5178
+ } elseif (empty($mass_updated) && $key == 'updraft_interval_database') {
5179
  $updraftplus->schedule_backup_database($value);
5180
  }
5181
  } else {
backup.php CHANGED
@@ -1556,7 +1556,7 @@ class UpdraftPlus_Backup {
1556
  $updraftplus->log(__("Failed to open database file for reading:", 'updraftplus').' '.$table_file.'.gz', 'error');
1557
  $errors++;
1558
  } else {
1559
- while ($line = gzgets($handle, 2048)) { $this->stow($line); }
1560
  gzclose($handle);
1561
  $unlink_files[] = $this->updraft_dir.'/'.$table_file.'.gz';
1562
  }
1556
  $updraftplus->log(__("Failed to open database file for reading:", 'updraftplus').' '.$table_file.'.gz', 'error');
1557
  $errors++;
1558
  } else {
1559
+ while ($line = gzgets($handle, 65536)) { $this->stow($line); }
1560
  gzclose($handle);
1561
  $unlink_files[] = $this->updraft_dir.'/'.$table_file.'.gz';
1562
  }
class-updraftplus.php CHANGED
@@ -2362,8 +2362,19 @@ class UpdraftPlus {
2362
  $this->log("There were errors in the uploads, so the 'resume' event is remaining scheduled");
2363
  $this->jobdata_set('jobstatus', 'resumingforerrors');
2364
  # If there were no errors before moving to the upload stage, on the first run, then bring the resumption back very close. Since this is only attempted on the first run, it is really only an efficiency thing for a quicker finish if there was an unexpected networking event. We don't want to do it straight away every time, as it may be that the cloud service is down - and might be up in 5 minutes time. This was added after seeing a case where resumption 0 got to run for 10 hours... and the resumption 7 that should have picked up the uploading of 1 archive that failed never occurred.
2365
- if (isset($this->error_count_before_cloud_backup) && 0 == $resumption_no && 0 === $this->error_count_before_cloud_backup) {
2366
- $this->reschedule(60);
 
 
 
 
 
 
 
 
 
 
 
2367
  }
2368
  }
2369
 
@@ -2441,6 +2452,18 @@ class UpdraftPlus {
2441
 
2442
  }
2443
 
 
 
 
 
 
 
 
 
 
 
 
 
2444
  public function error_count($level = 'error') {
2445
  $count = 0;
2446
  foreach ($this->errors as $err) {
@@ -2638,7 +2661,7 @@ class UpdraftPlus {
2638
  $how_far_ahead = $new_resume;
2639
  # If it is very long-running, then that would normally be known soon.
2640
  # If the interval is already 12 minutes or more, then try the next resumption 10 minutes from now (i.e. sooner than it would have been). Thus, we are guaranteed to get at least 24 minutes of processing in the first 34.
2641
- if (1 >= $this->current_resumption && $new_resume > 720) $how_far_ahead = 600;
2642
 
2643
  if (!empty($this->newresumption_scheduled) || $force_schedule) $this->reschedule($how_far_ahead);
2644
  $this->jobdata_set('resume_interval', $new_resume);
@@ -2808,7 +2831,7 @@ class UpdraftPlus {
2808
  if ($add_to_list) {
2809
  array_push($dirlist, $candidate);
2810
  $added++;
2811
- $skip_dblog = ($added > 50 && 0 != $added % 100);
2812
  $this->log("finding files: $entry: adding to list ($added)", 'notice', false, $skip_dblog);
2813
  }
2814
  }
@@ -3487,6 +3510,11 @@ class UpdraftPlus {
3487
  }
3488
  // Explicitly set it, allowing the consumer to detect when the result was unknown
3489
  $info['same_url'] = false;
 
 
 
 
 
3490
  } else {
3491
  $info['same_url'] = true;
3492
  }
2362
  $this->log("There were errors in the uploads, so the 'resume' event is remaining scheduled");
2363
  $this->jobdata_set('jobstatus', 'resumingforerrors');
2364
  # If there were no errors before moving to the upload stage, on the first run, then bring the resumption back very close. Since this is only attempted on the first run, it is really only an efficiency thing for a quicker finish if there was an unexpected networking event. We don't want to do it straight away every time, as it may be that the cloud service is down - and might be up in 5 minutes time. This was added after seeing a case where resumption 0 got to run for 10 hours... and the resumption 7 that should have picked up the uploading of 1 archive that failed never occurred.
2365
+ if (isset($this->error_count_before_cloud_backup) && 0 === $this->error_count_before_cloud_backup) {
2366
+ if (0 == $resumption_no) {
2367
+ $this->reschedule(60);
2368
+ } else {
2369
+ // Added 27/Feb/2016 - though the cloud service seems to be down, we still don't want to wait too long
2370
+ $resume_interval = $this->jobdata_get('resume_interval');
2371
+
2372
+ // 15 minutes + 2 for each resumption (a modest back-off)
2373
+ $max_interval = 900 + $resumption_no * 120;
2374
+ if ($resume_interval > $max_interval) {
2375
+ $this->reschedule($max_interval);
2376
+ }
2377
+ }
2378
  }
2379
  }
2380
 
2452
 
2453
  }
2454
 
2455
+ // This function returns 'true' if mod_rewrite could be detected as unavailable; a 'false' result may mean it just couldn't find out the answer
2456
+ public function mod_rewrite_unavailable($check_if_in_use_first = true) {
2457
+ if (function_exists('apache_get_modules')) {
2458
+ global $wp_rewrite;
2459
+ $mods = apache_get_modules();
2460
+ if ((!$check_if_in_use_first || $wp_rewrite->using_mod_rewrite_permalinks()) && ((in_array('core', $mods) || in_array('http_core', $mods)) && !in_array('mod_rewrite', $mods))) {
2461
+ return true;
2462
+ }
2463
+ }
2464
+ return false;
2465
+ }
2466
+
2467
  public function error_count($level = 'error') {
2468
  $count = 0;
2469
  foreach ($this->errors as $err) {
2661
  $how_far_ahead = $new_resume;
2662
  # If it is very long-running, then that would normally be known soon.
2663
  # If the interval is already 12 minutes or more, then try the next resumption 10 minutes from now (i.e. sooner than it would have been). Thus, we are guaranteed to get at least 24 minutes of processing in the first 34.
2664
+ if ($this->current_resumption <= 1 && $new_resume > 720) $how_far_ahead = 600;
2665
 
2666
  if (!empty($this->newresumption_scheduled) || $force_schedule) $this->reschedule($how_far_ahead);
2667
  $this->jobdata_set('resume_interval', $new_resume);
2831
  if ($add_to_list) {
2832
  array_push($dirlist, $candidate);
2833
  $added++;
2834
+ $skip_dblog = (($added > 50 && 0 != $added % 100) || ($added > 2000 && 0 != $added % 500));
2835
  $this->log("finding files: $entry: adding to list ($added)", 'notice', false, $skip_dblog);
2836
  }
2837
  }
3510
  }
3511
  // Explicitly set it, allowing the consumer to detect when the result was unknown
3512
  $info['same_url'] = false;
3513
+
3514
+ if ($this->mod_rewrite_unavailable(false)) {
3515
+ $warn[] = sprintf(__('You are using the %s webserver, but do not seem to have the %s module loaded.', 'updraftplus'), 'Apache', 'mod_rewrite').' '.sprintf(__('You should enable %s to make any pretty permalinks (e.g. %s) work', 'updraftplus'), 'mod_rewrite', 'http://example.com/my-page/');
3516
+ }
3517
+
3518
  } else {
3519
  $info['same_url'] = true;
3520
  }
css/admin.css CHANGED
@@ -249,6 +249,39 @@ a .udp-logo {
249
  top: -20px;
250
  }
251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  /* Taken straight from admin.php */
253
 
254
  #updraft-navtab-settings-content table.form-table p {
@@ -444,59 +477,6 @@ a .udp-logo {
444
  background: red;
445
  }
446
 
447
- /* Selectric dropdown styling */
448
- .selectric-items .ico {
449
- display: inline-block;
450
- vertical-align: middle;
451
- zoom: 1;
452
- *display: inline;
453
- height: 40px;
454
- width: 40px;
455
- margin: 0 6px 0 0;
456
- }
457
-
458
- .selectric-wrapper{
459
- width: 300px;
460
- }
461
-
462
- div.selectric {
463
- padding: 0 2px 4px;
464
- line-height: 28px;
465
- height: 34px;
466
- vertical-align: middle;
467
- background-color: #fff;
468
- }
469
-
470
- .selectric .label {
471
- line-height: 28px;
472
- height: 28px;
473
- margin: 0px 0px 0px 4px;
474
- font-size: 14px;
475
- }
476
-
477
- .selectric .button {
478
- width: 22px;
479
- height: 32px;
480
- border: none;
481
- }
482
-
483
- .selectric .button:after {
484
- border-top-color: #000;
485
- }
486
-
487
- .selectric-hover .selectric {
488
- border-color: #DDD;
489
- cursor: default;
490
- }
491
-
492
- .selectric-hover .selectric .button {
493
- cursor: default;
494
- }
495
-
496
- .selectric-hover .selectric .button:after {
497
- border-top-color: #000;
498
- }
499
-
500
  #updraft_backup_started {
501
  max-width: 800px;
502
  font-size: 140%;
@@ -1338,4 +1318,69 @@ input #backupnow_includefiles_moreoptions {
1338
 
1339
  /* End of forgotton something */
1340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1341
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  top: -20px;
250
  }
251
 
252
+ #updraft_report_cell .updraft_reportbox {
253
+ padding:8px;
254
+ margin: 8px 0;
255
+ border: 1px dotted;
256
+ clear:left;
257
+ float:left;
258
+ }
259
+
260
+ #updraft_report_cell button.updraft_reportbox_delete {
261
+ font-size: 50%;
262
+ float:right;
263
+ padding:0 3px;
264
+ position: relative;
265
+ top: -4px;
266
+ left: 4px;
267
+ }
268
+
269
+ #updraft-navtab-settings-content .updraft-test-button {
270
+ font-size:18px !important;
271
+ }
272
+
273
+ #updraft_report_cell .updraft_report_checkbox {
274
+ margin-top: 4px;
275
+ }
276
+
277
+ #updraft_report_cell .updraft_report_email {
278
+ width: 300px;
279
+ }
280
+
281
+ #updraft_report_cell .updraft_report_another_p {
282
+ clear:left;
283
+ }
284
+
285
  /* Taken straight from admin.php */
286
 
287
  #updraft-navtab-settings-content table.form-table p {
477
  background: red;
478
  }
479
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  #updraft_backup_started {
481
  max-width: 800px;
482
  font-size: 140%;
1318
 
1319
  /* End of forgotton something */
1320
 
1321
+ .updraftplusmethod.updraftvault #vaultlogo { padding-left: 40px; }
1322
+
1323
+ .updraftplusmethod.updraftvault .vault_primary_option {
1324
+ float: left;
1325
+ width:50%;
1326
+ text-align:center;
1327
+ padding-bottom:20px;
1328
+ }
1329
+
1330
+ .updraftplusmethod.updraftvault .vault_primary_option div {
1331
+ clear:right;
1332
+ padding-top: 20px;
1333
+ }
1334
+
1335
+ .updraftplusmethod.updraftvault .clear-left {
1336
+ clear: left;
1337
+ }
1338
+
1339
+ .updraftplusmethod.updraftvault .padding-top-20px { padding-top: 20px; }
1340
 
1341
+ .updraftplusmethod.updraftvault .padding-top-14px { padding-top: 14px; }
1342
+
1343
+ .updraftplusmethod.updraftvault #updraftvault_settings_default .button-primary, .updraftplusmethod.updraftvault #updraftvault_settings_showoptions .button-primary {
1344
+ font-size: 18px !important;
1345
+ padding-bottom: 20px;
1346
+ }
1347
+
1348
+ .updraftplusmethod.updraftvault #updraftvault_showoptions, .updraftplusmethod.updraftvault #updraftvault_connect {
1349
+ margin-top:8px;
1350
+ }
1351
+
1352
+ .updraftplusmethod.updraftvault #updraftvault_settings_connect input {
1353
+ margin-right:10px;
1354
+ }
1355
+
1356
+ .updraftplusmethod.updraftvault #updraftvault_email { width: 280px; }
1357
+ .updraftplusmethod.updraftvault #updraftvault_pass { width: 200px; }
1358
+
1359
+ .updraftplusmethod.updraftvault #vault-is-connected { margin: 0; padding: 0; }
1360
+
1361
+ .updraftplusmethod.updraftvault #updraftvault_settings_default p {
1362
+ clear:left;
1363
+ }
1364
+
1365
+ .updraftplusmethod.updraftvault .vault-purchase-option {
1366
+ float: left;
1367
+ width:33%;
1368
+ text-align:center;
1369
+ padding-top: 20px;
1370
+ }
1371
+
1372
+ .updraftplusmethod.updraftvault .vault-purchase-option-size {
1373
+ font-size: 200%;
1374
+ font-weight:bold;
1375
+ }
1376
+
1377
+ .updraftplusmethod.updraftvault .vault-purchase-option-link {
1378
+ clear:both;
1379
+ font-size: 150%
1380
+ }
1381
+
1382
+ .updraftplusmethod.updraftvault .vault-purchase-option-or {
1383
+ clear: both;
1384
+ font-size: 115%;
1385
+ font-style: italic;
1386
+ }
includes/class-partialfileservlet.php CHANGED
@@ -48,11 +48,9 @@ class UpdraftPlus_RangeHeader
48
  if ($header === null) {
49
  return null;
50
  }
51
- error_log("header=$header");
52
  if (!preg_match('/^\s*([A-Za-z]+)\s*=\s*(\d*)\s*-\s*(\d*)\s*(?:,|$)/', $header, $info)) {
53
  throw new UpdraftPlus_InvalidRangeHeaderException('Invalid header format');
54
  } else if (strtolower($info[1]) !== 'bytes') {
55
- error_log_v($info);
56
  throw new UpdraftPlus_InvalidRangeHeaderException('Unknown range unit: ' . $info[1]);
57
  }
58
 
48
  if ($header === null) {
49
  return null;
50
  }
 
51
  if (!preg_match('/^\s*([A-Za-z]+)\s*=\s*(\d*)\s*-\s*(\d*)\s*(?:,|$)/', $header, $info)) {
52
  throw new UpdraftPlus_InvalidRangeHeaderException('Invalid header format');
53
  } else if (strtolower($info[1]) !== 'bytes') {
 
54
  throw new UpdraftPlus_InvalidRangeHeaderException('Unknown range unit: ' . $info[1]);
55
  }
56
 
includes/class-udrpc.php CHANGED
@@ -59,7 +59,7 @@ if (!class_exists('UpdraftPlus_Remote_Communications')):
59
  class UpdraftPlus_Remote_Communications {
60
 
61
  // Version numbers relate to versions of this PHP library only (i.e. it's not a protocol support number, and version numbers of other compatible libraries (e.g. JavaScript) are not comparable)
62
- public $version = '1.2';
63
 
64
  private $key_name_indicator;
65
 
@@ -608,53 +608,54 @@ class UpdraftPlus_Remote_Communications {
608
  // Check this now, rather than allow the decrypt method to thrown an Exception
609
 
610
  if (empty($this->key_local)) {
611
- $this->log("no local key (format 1): cannot decrypt");
612
  die;
613
  }
614
 
615
  if ($format >= 2) {
616
  if (empty($_POST['signature'])) {
617
- $this->log("No message signature found");
618
  die;
619
  }
620
  if (!$this->key_remote) {
621
- $this->log('No signature verification key has been set');
622
  die;
623
  }
624
  if (!$this->verify_signature($udrpc_message, $_POST['signature'], $this->key_remote)) {
625
- $this->log('Signature verification failed; discarding');
 
626
  }
627
  }
628
 
629
  try {
630
  $udrpc_message = $this->decrypt_message($udrpc_message);
631
  } catch (Exception $e) {
632
- $this->log("Exception (".get_class($e)."): ".$e->getMessage());
633
  die;
634
  }
635
 
636
  $udrpc_message = json_decode($udrpc_message, true);
637
 
638
  if (empty($udrpc_message) || !is_array($udrpc_message) || empty($udrpc_message['command']) || !is_string($udrpc_message['command'])) {
639
- $this->log("Could not decode JSON on incoming message");
640
  die;
641
  }
642
 
643
  if (empty($udrpc_message['time'])) {
644
- $this->log("No time set in incoming message");
645
  die;
646
  }
647
 
648
  // Mismatch indicating a replay of the message with a different key name in the unencrypted portion?
649
  if (empty($udrpc_message['key_name']) || $_POST['key_name'] != $udrpc_message['key_name']) {
650
- $this->log("key_name mismatch between encrypted and unencrypted portions");
651
  die;
652
  }
653
 
654
  if ($this->extra_replay_protection) {
655
  $message_hash = $this->calculate_message_hash((string)$_POST['udrpc_message']);
656
  if ($this->message_hash_seen($message_hash)) {
657
- $this->log("Message dropped: apparently a replay (hash: $message_hash)");
658
  die;
659
  }
660
  }
@@ -662,7 +663,7 @@ class UpdraftPlus_Remote_Communications {
662
  // Do this after the extra replay protection, as that checks hashes within the maximum time window - so don't check the maximum time window until afterwards, to avoid a tiny window (race) in between.
663
  $time_difference = absint($udrpc_message['time'] - time());
664
  if ($time_difference > $this->maximum_replay_time_difference) {
665
- $this->log("Time in incoming message is outside of allowed window ($time_difference > ".$this->maximum_replay_time_difference.")");
666
  die;
667
  }
668
 
@@ -674,7 +675,7 @@ class UpdraftPlus_Remote_Communications {
674
  global $wpdb;
675
 
676
  if (!isset($udrpc_message['sequence_id']) || !is_numeric($udrpc_message['sequence_id'])) {
677
- $this->log("a numerical sequence number is required, but none was included in the message - dropping");
678
  die;
679
  }
680
 
@@ -702,7 +703,7 @@ class UpdraftPlus_Remote_Communications {
702
  if ($this->debug) $this->log("Sequence id ($message_sequence_id) is within tolerance range of previous maximum (".max($recently_seen_sequences_ids).") - message is thus OK");
703
  $recently_seen_sequences_ids_as_array[] = $message_sequence_id;
704
  } else {
705
- $this->log("message received outside of allowed sequence window - dropping (received=$message_sequence_id, seen=$recently_seen_sequences_ids, tolerance=".$this->sequence_protection_tolerance.")");
706
  die;
707
  }
708
 
59
  class UpdraftPlus_Remote_Communications {
60
 
61
  // Version numbers relate to versions of this PHP library only (i.e. it's not a protocol support number, and version numbers of other compatible libraries (e.g. JavaScript) are not comparable)
62
+ public $version = '1.3';
63
 
64
  private $key_name_indicator;
65
 
608
  // Check this now, rather than allow the decrypt method to thrown an Exception
609
 
610
  if (empty($this->key_local)) {
611
+ $this->log("no local key (format 1): cannot decrypt", 'error');
612
  die;
613
  }
614
 
615
  if ($format >= 2) {
616
  if (empty($_POST['signature'])) {
617
+ $this->log("No message signature found", 'error');
618
  die;
619
  }
620
  if (!$this->key_remote) {
621
+ $this->log('No signature verification key has been set', 'error');
622
  die;
623
  }
624
  if (!$this->verify_signature($udrpc_message, $_POST['signature'], $this->key_remote)) {
625
+ $this->log('Signature verification failed; discarding', 'error');
626
+ die;
627
  }
628
  }
629
 
630
  try {
631
  $udrpc_message = $this->decrypt_message($udrpc_message);
632
  } catch (Exception $e) {
633
+ $this->log("Exception (".get_class($e)."): ".$e->getMessage(), 'error');
634
  die;
635
  }
636
 
637
  $udrpc_message = json_decode($udrpc_message, true);
638
 
639
  if (empty($udrpc_message) || !is_array($udrpc_message) || empty($udrpc_message['command']) || !is_string($udrpc_message['command'])) {
640
+ $this->log("Could not decode JSON on incoming message", 'error');
641
  die;
642
  }
643
 
644
  if (empty($udrpc_message['time'])) {
645
+ $this->log("No time set in incoming message", 'error');
646
  die;
647
  }
648
 
649
  // Mismatch indicating a replay of the message with a different key name in the unencrypted portion?
650
  if (empty($udrpc_message['key_name']) || $_POST['key_name'] != $udrpc_message['key_name']) {
651
+ $this->log("key_name mismatch between encrypted and unencrypted portions", 'error');
652
  die;
653
  }
654
 
655
  if ($this->extra_replay_protection) {
656
  $message_hash = $this->calculate_message_hash((string)$_POST['udrpc_message']);
657
  if ($this->message_hash_seen($message_hash)) {
658
+ $this->log("Message dropped: apparently a replay (hash: $message_hash)", 'error');
659
  die;
660
  }
661
  }
663
  // Do this after the extra replay protection, as that checks hashes within the maximum time window - so don't check the maximum time window until afterwards, to avoid a tiny window (race) in between.
664
  $time_difference = absint($udrpc_message['time'] - time());
665
  if ($time_difference > $this->maximum_replay_time_difference) {
666
+ $this->log("Time in incoming message is outside of allowed window ($time_difference > ".$this->maximum_replay_time_difference.")", 'error');
667
  die;
668
  }
669
 
675
  global $wpdb;
676
 
677
  if (!isset($udrpc_message['sequence_id']) || !is_numeric($udrpc_message['sequence_id'])) {
678
+ $this->log("a numerical sequence number is required, but none was included in the message - dropping", 'error');
679
  die;
680
  }
681
 
703
  if ($this->debug) $this->log("Sequence id ($message_sequence_id) is within tolerance range of previous maximum (".max($recently_seen_sequences_ids).") - message is thus OK");
704
  $recently_seen_sequences_ids_as_array[] = $message_sequence_id;
705
  } else {
706
+ $this->log("message received outside of allowed sequence window - dropping (received=$message_sequence_id, seen=$recently_seen_sequences_ids, tolerance=".$this->sequence_protection_tolerance.")", 'error');
707
  die;
708
  }
709
 
includes/selectric/jquery.selectric.js DELETED
@@ -1,555 +0,0 @@
1
- /*!
2
- * ,/
3
- * ,'/
4
- * ,' /
5
- * ,' /_____,
6
- * .'____ ,'
7
- * / ,'
8
- * / ,'
9
- * /,'
10
- * /'
11
- *
12
- * Selectric Ϟ v1.9.3 (Jul 08 2015) - http://lcdsantos.github.io/jQuery-Selectric/
13
- *
14
- * Copyright (c) 2015 Leonardo Santos; Dual licensed: MIT/GPL
15
- *
16
- */
17
-
18
- ;(function($) {
19
- 'use strict';
20
-
21
- var pluginName = 'selectric',
22
- classList = 'Input Items Open Disabled TempShow HideSelect Wrapper Hover Responsive Above Scroll Group GroupLabel',
23
- bindSufix = '.sl',
24
- defaults = {
25
- onChange: function(elm) { $(elm).change(); },
26
- maxHeight: 300,
27
- keySearchTimeout: 500,
28
- arrowButtonMarkup: '<b class="button">&#x25be;</b>',
29
- disableOnMobile: true,
30
- openOnHover: false,
31
- hoverIntentTimeout: 500,
32
- expandToItemText: false,
33
- responsive: false,
34
- preventWindowScroll: true,
35
- inheritOriginalWidth: false,
36
- allowWrap: true,
37
- customClass: {
38
- prefix: pluginName,
39
- camelCase: false,
40
- overwrite: true
41
- },
42
- optionsItemBuilder: '{text}', // function(itemData, element, index)
43
- labelBuilder: '{text}' // function(currItem)
44
- },
45
- hooks = {
46
- add: function(callbackName, hookName, fn) {
47
- if ( !this[callbackName] )
48
- this[callbackName] = {};
49
-
50
- this[callbackName][hookName] = fn;
51
- },
52
- remove: function(callbackName, hookName) {
53
- delete this[callbackName][hookName];
54
- }
55
- },
56
- _utils = {
57
- // Replace diacritics
58
- replaceDiacritics: function(s) {
59
- // /[\340-\346]/g, // a
60
- // /[\350-\353]/g, // e
61
- // /[\354-\357]/g, // i
62
- // /[\362-\370]/g, // o
63
- // /[\371-\374]/g, // u
64
- // /[\361]/g, // n
65
- // /[\347]/g, // c
66
- // /[\377]/g // y
67
- var d = '40-46 50-53 54-57 62-70 71-74 61 47 77'.replace(/\d+/g, '\\3$&').split(' '),
68
- k = d.length;
69
-
70
- while (k--)
71
- s = s.toLowerCase().replace(RegExp('[' + d[k] + ']', 'g'), 'aeiouncy'.charAt(k));
72
-
73
- return s;
74
- },
75
- // https://gist.github.com/atesgoral/984375
76
- format: function(f) {var a=arguments;return(""+f).replace(/{(\d+|(\w+))}/g,function(s,i,p) {return p&&a[1]?a[1][p]:a[i]})},
77
- nextEnabledItem: function(selectItems, selected) {
78
- while ( selectItems[ selected = (selected + 1) % selectItems.length ].disabled ) {}
79
- return selected;
80
- },
81
- previousEnabledItem: function(selectItems, selected) {
82
- while ( selectItems[ selected = (selected > 0 ? selected : selectItems.length) - 1 ].disabled ) {}
83
- return selected;
84
- },
85
- toDash: function(str) {
86
- return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
87
- },
88
- triggerCallback: function(fn, scope) {
89
- var elm = scope.element,
90
- func = scope.options['on' + fn];
91
-
92
- if ( $.isFunction(func) )
93
- func.call(elm, elm, scope);
94
-
95
- if ( hooks[fn] ) {
96
- $.each(hooks[fn], function() {
97
- this.call(elm, elm, scope);
98
- });
99
- }
100
-
101
- $(elm).trigger(pluginName + '-' + _utils.toDash(fn), scope);
102
- }
103
- },
104
- $doc = $(document),
105
- $win = $(window),
106
- Selectric = function(element, opts) {
107
- var _this = this,
108
- $original = $(element),
109
- $input, $items, $itemsScroll, $wrapper, $label, $outerWrapper, $li,
110
- isOpen = false,
111
- isEnabled = false,
112
- selected,
113
- currValue,
114
- itemsHeight,
115
- itemsInnerHeight,
116
- finalWidth,
117
- optionsLength,
118
- eventTriggers,
119
- isMobile = /android|ip(hone|od|ad)/i.test(navigator.userAgent),
120
- tabindex = $original.prop('tabindex'),
121
- labelBuilder;
122
-
123
- function _init(opts) {
124
- _this.options = $.extend(true, {}, defaults, _this.options, opts);
125
- _this.classes = {};
126
- _this.element = element;
127
-
128
- _utils.triggerCallback('BeforeInit', _this);
129
-
130
- // Disable on mobile browsers
131
- if ( _this.options.disableOnMobile && isMobile ) {
132
- _this.disableOnMobile = true;
133
- return;
134
- }
135
-
136
- // Preserve data
137
- _destroy(true);
138
-
139
- // Generate classNames for elements
140
- var customClass = _this.options.customClass,
141
- postfixes = classList.split(' '),
142
- originalWidth = $original.width();
143
-
144
- $.each(postfixes, function(i, currClass) {
145
- var c = customClass.prefix + currClass;
146
- _this.classes[currClass.toLowerCase()] = customClass.camelCase ? c : _utils.toDash(c);
147
- });
148
-
149
- $input = $('<input/>', { 'class': _this.classes.input, 'readonly': isMobile });
150
- $items = $('<div/>', { 'class': _this.classes.items, 'tabindex': -1 });
151
- $itemsScroll = $('<div/>', { 'class': _this.classes.scroll });
152
- $wrapper = $('<div/>', { 'class': customClass.prefix, 'html': _this.options.arrowButtonMarkup });
153
- $label = $('<p class="label"/>');
154
- $outerWrapper = $original.wrap('<div>').parent().append($wrapper.prepend($label), $items, $input);
155
-
156
- eventTriggers = {
157
- open : _open,
158
- close : _close,
159
- destroy : _destroy,
160
- refresh : _refresh,
161
- init : _init
162
- };
163
-
164
- $original.on(eventTriggers).wrap('<div class="' + _this.classes.hideselect + '">');
165
- $.extend(_this, eventTriggers);
166
-
167
- labelBuilder = _this.options.labelBuilder;
168
-
169
- if ( _this.options.inheritOriginalWidth && originalWidth > 0 )
170
- $outerWrapper.width(originalWidth);
171
-
172
- _populate();
173
- }
174
-
175
- // Generate options markup and event binds
176
- function _populate() {
177
- _this.items = [];
178
-
179
- var $options = $original.children(),
180
- _$li = '<ul>',
181
- $justOptions = $original.find('option'),
182
- selectedIndex = $justOptions.index($justOptions.filter(':selected')),
183
- currIndex = 0;
184
-
185
- currValue = (selected = ~selectedIndex ? selectedIndex : 0);
186
-
187
- if ( optionsLength = $options.length ) {
188
- // Build options markup
189
- $options.each(function() {
190
- var $elm = $(this);
191
-
192
- if ( $elm.is('optgroup') ) {
193
- var groupDisabled = $elm.prop('disabled'),
194
- $children = $elm.children();
195
-
196
- _$li += _utils.format('<ul class="{1}"><li class="{2}">{3}</li>',
197
- $.trim([_this.classes.group, groupDisabled ? 'disabled' : '', $elm.prop('class')].join(' ')),
198
- _this.classes.grouplabel,
199
- $elm.prop('label')
200
- );
201
-
202
- if ( groupDisabled ) {
203
- $children.prop('disabled', true);
204
- }
205
-
206
- $children.each(buildOption);
207
-
208
- _$li += '</ul>';
209
- } else {
210
- buildOption.call($elm);
211
- }
212
-
213
- function buildOption() {
214
- var $elm = $(this),
215
- optionText = $elm.html(),
216
- selectDisabled = $elm.prop('disabled'),
217
- itemBuilder = _this.options.optionsItemBuilder;
218
-
219
- _this.items[currIndex] = {
220
- element : $elm,
221
- value : $elm.val(),
222
- text : optionText,
223
- slug : _utils.replaceDiacritics(optionText),
224
- disabled : selectDisabled
225
- };
226
-
227
- _$li += _utils.format('<li data-index="{1}" class="{2}">{3}</li>',
228
- currIndex,
229
- $.trim([currIndex == currValue ? 'selected' : '', currIndex == optionsLength - 1 ? 'last' : '', selectDisabled ? 'disabled' : ''].join(' ')),
230
- $.isFunction(itemBuilder) ? itemBuilder(_this.items[currIndex], $elm, currIndex) : _utils.format(itemBuilder, _this.items[currIndex])
231
- );
232
-
233
- currIndex++;
234
- }
235
- });
236
-
237
- $items.append( $itemsScroll.html(_$li + '</ul>') );
238
-
239
- $label.html(
240
- $.isFunction(labelBuilder) ? labelBuilder(_this.items[currValue]) : _utils.format(labelBuilder, _this.items[currValue])
241
- )
242
- }
243
-
244
- $wrapper.add($original).add($outerWrapper).add($input).off(bindSufix);
245
-
246
- $outerWrapper.prop('class', [
247
- _this.classes.wrapper,
248
- _this.options.customClass.overwrite ?
249
- $original.prop('class').replace(/\S+/g, _this.options.customClass.prefix + '-$&') :
250
- $original.prop('class'),
251
- _this.options.responsive ? _this.classes.responsive : ''
252
- ].join(' '));
253
-
254
- if ( !$original.prop('disabled') ) {
255
- isEnabled = true;
256
-
257
- // Not disabled, so... Removing disabled class and bind hover
258
- $outerWrapper.removeClass(_this.classes.disabled).on('mouseenter' + bindSufix + ' mouseleave' + bindSufix, function(e) {
259
- $(this).toggleClass(_this.classes.hover);
260
-
261
- // Delay close effect when openOnHover is true
262
- if ( _this.options.openOnHover ) {
263
- clearTimeout(_this.closeTimer);
264
- e.type == 'mouseleave' ? _this.closeTimer = setTimeout(_close, _this.options.hoverIntentTimeout) : _open();
265
- }
266
- });
267
-
268
- // Toggle open/close
269
- $wrapper.on('click' + bindSufix, function(e) {
270
- isOpen ? _close() : _open(e);
271
- });
272
-
273
- $input
274
- .prop({
275
- tabindex: tabindex,
276
- disabled: false
277
- })
278
- .on('keypress' + bindSufix, _handleSystemKeys)
279
- .on('keydown' + bindSufix, function(e) {
280
- _handleSystemKeys(e);
281
-
282
- // Clear search
283
- clearTimeout(_this.resetStr);
284
- _this.resetStr = setTimeout(function() {
285
- $input.val('');
286
- }, _this.options.keySearchTimeout);
287
-
288
- var key = e.keyCode || e.which;
289
-
290
- // If it's a directional key
291
- // 37 => Left
292
- // 38 => Up
293
- // 39 => Right
294
- // 40 => Down
295
- if ( key > 36 && key < 41 ) {
296
- if ( !_this.options.allowWrap ) {
297
- if ( (key < 39 && selected == 0) || (key > 38 && (selected + 1) == _this.items.length) ) {
298
- return;
299
- }
300
- }
301
-
302
- _select(_utils[(key < 39 ? 'previous' : 'next') + 'EnabledItem'](_this.items, selected));
303
- }
304
- })
305
- .on('focusin' + bindSufix, function(e) {
306
- // Stupid, but necessary... Prevent the flicker when
307
- // focusing out and back again in the browser window
308
- $input.one('blur', function() {
309
- $input.blur();
310
- });
311
-
312
- isOpen || _open(e);
313
- })
314
- .on('oninput' in $input[0] ? 'input' : 'keyup', function() {
315
- if ( $input.val().length ) {
316
- // Search in select options
317
- $.each(_this.items, function(i, elm) {
318
- if ( RegExp('^' + $input.val(), 'i').test(elm.slug) && !elm.disabled ) {
319
- _select(i);
320
- return false;
321
- }
322
- });
323
- }
324
- });
325
-
326
- $original.prop('tabindex', false);
327
-
328
- // Remove styles from items box
329
- // Fix incorrect height when refreshed is triggered with fewer options
330
- $li = $('li', $items.removeAttr('style')).on({
331
- // Prevent <input> blur on Chrome
332
- mousedown: function(e) {
333
- e.preventDefault();
334
- e.stopPropagation();
335
- },
336
- click: function() {
337
- // The second parameter is to close the box after click
338
- _select($(this).data('index'), true);
339
-
340
- // Chrome doesn't close options box if select is wrapped with a label
341
- // We need to 'return false' to avoid that
342
- return false;
343
- }
344
- }).filter('[data-index]');
345
- } else {
346
- $outerWrapper.addClass(_this.classes.disabled);
347
- $input.prop('disabled', true);
348
- }
349
-
350
- _utils.triggerCallback('Init', _this);
351
- }
352
-
353
- function _refresh() {
354
- _utils.triggerCallback('Refresh', _this);
355
- _populate();
356
- }
357
-
358
- // Behavior when system keys is pressed
359
- function _handleSystemKeys(e) {
360
- var key = e.keyCode || e.which;
361
-
362
- if ( key == 13 ) {
363
- e.preventDefault();
364
- }
365
-
366
- // Tab / Enter / ESC
367
- if ( /^(9|13|27)$/.test(key) ) {
368
- e.stopPropagation();
369
- _select(selected, true);
370
- }
371
- }
372
-
373
- // Set options box width/height
374
- function _calculateOptionsDimensions() {
375
- // Calculate options box height
376
- // Set a temporary class on the hidden parent of the element
377
- var hiddenChildren = $items.closest(':visible').children(':hidden').addClass(_this.classes.tempshow),
378
- maxHeight = _this.options.maxHeight,
379
- itemsWidth = $items.outerWidth(),
380
- wrapperWidth = $wrapper.outerWidth() - (itemsWidth - $items.width());
381
-
382
- // Set the dimensions, minimum is wrapper width, expand for long items if option is true
383
- if ( !_this.options.expandToItemText || wrapperWidth > itemsWidth )
384
- finalWidth = wrapperWidth;
385
- else {
386
- // Make sure the scrollbar width is included
387
- $items.css('overflow', 'scroll');
388
-
389
- // Set a really long width for $outerWrapper
390
- $outerWrapper.width(9e4);
391
- finalWidth = $items.width();
392
- // Set scroll bar to auto
393
- $items.css('overflow', '');
394
- $outerWrapper.width('');
395
- }
396
-
397
- $items.width(finalWidth).height() > maxHeight && $items.height(maxHeight);
398
-
399
- // Remove the temporary class
400
- hiddenChildren.removeClass(_this.classes.tempshow);
401
- }
402
-
403
- // Open the select options box
404
- function _open(e) {
405
- _utils.triggerCallback('BeforeOpen', _this);
406
-
407
- if ( e ) {
408
- e.preventDefault();
409
- e.stopPropagation();
410
- }
411
-
412
- if ( isEnabled ) {
413
- _calculateOptionsDimensions();
414
-
415
- // Find any other opened instances of select and close it
416
- $('.' + _this.classes.hideselect, '.' + _this.classes.open).children()[pluginName]('close');
417
-
418
- isOpen = true;
419
- itemsHeight = $items.outerHeight();
420
- itemsInnerHeight = $items.height();
421
-
422
- // Toggle options box visibility
423
- $outerWrapper.addClass(_this.classes.open);
424
-
425
- // Give dummy input focus
426
- $input.val('').is(':focus') || $input.focus();
427
-
428
- $doc.on('click' + bindSufix, _close).on('scroll' + bindSufix, _isInViewport);
429
- _isInViewport();
430
-
431
- // Prevent window scroll when using mouse wheel inside items box
432
- if ( _this.options.preventWindowScroll ) {
433
- $doc.on('mousewheel' + bindSufix + ' DOMMouseScroll' + bindSufix, '.' + _this.classes.scroll, function(e) {
434
- var orgEvent = e.originalEvent,
435
- scrollTop = $(this).scrollTop(),
436
- deltaY = 0;
437
-
438
- if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
439
- if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
440
- if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
441
- if ( 'deltaY' in orgEvent ) { deltaY = orgEvent.deltaY * -1; }
442
-
443
- if ( scrollTop == (this.scrollHeight - itemsInnerHeight) && deltaY < 0 || scrollTop == 0 && deltaY > 0 ) {
444
- e.preventDefault();
445
- }
446
- });
447
- }
448
-
449
- _detectItemVisibility(selected);
450
-
451
- _utils.triggerCallback('Open', _this);
452
- }
453
- }
454
-
455
- // Detect is the options box is inside the window
456
- function _isInViewport() {
457
- $outerWrapper.toggleClass(_this.classes.above, $outerWrapper.offset().top + $outerWrapper.outerHeight() + itemsHeight > $win.scrollTop() + $win.height());
458
- }
459
-
460
- // Close the select options box
461
- function _close() {
462
- _utils.triggerCallback('BeforeClose', _this);
463
-
464
- if ( currValue != selected ) {
465
- _utils.triggerCallback('BeforeChange', _this);
466
-
467
- var text = _this.items[selected].text;
468
-
469
- // Apply changed value to original select
470
- $original
471
- .prop('selectedIndex', currValue = selected)
472
- .data('value', text);
473
-
474
- // Change label text
475
- $label.html(
476
- $.isFunction(labelBuilder) ? labelBuilder(_this.items[selected]) : _utils.format(labelBuilder, _this.items[selected])
477
- )
478
-
479
- _utils.triggerCallback('Change', _this);
480
- }
481
-
482
- // Remove custom events on document
483
- $doc.off(bindSufix);
484
-
485
- // Remove visible class to hide options box
486
- $outerWrapper.removeClass(_this.classes.open);
487
-
488
- isOpen = false;
489
-
490
- _utils.triggerCallback('Close', _this);
491
- }
492
-
493
- // Select option
494
- function _select(index, close) {
495
- // Parameter index is required
496
- if ( index == undefined ) {
497
- return;
498
- }
499
-
500
- // If element is disabled, can't select it
501
- if ( !_this.items[index].disabled ) {
502
- // If 'close' is false (default), the options box won't close after
503
- // each selected item, this is necessary for keyboard navigation
504
- $li
505
- .removeClass('selected')
506
- .eq(selected = index)
507
- .addClass('selected');
508
-
509
- _detectItemVisibility(index);
510
- close && _close();
511
- }
512
- }
513
-
514
- // Detect if currently selected option is visible and scroll the options box to show it
515
- function _detectItemVisibility(index) {
516
- var liHeight = $li.eq(index).outerHeight(),
517
- liTop = $li[index].offsetTop,
518
- itemsScrollTop = $itemsScroll.scrollTop(),
519
- scrollT = liTop + liHeight * 2;
520
-
521
- $itemsScroll.scrollTop(
522
- scrollT > itemsScrollTop + itemsHeight ? scrollT - itemsHeight :
523
- liTop - liHeight < itemsScrollTop ? liTop - liHeight :
524
- itemsScrollTop
525
- );
526
- }
527
-
528
- // Unbind and remove
529
- function _destroy(preserveData) {
530
- if ( isEnabled ) {
531
- $items.add($wrapper).add($input).remove();
532
- !preserveData && $original.removeData(pluginName).removeData('value');
533
- $original.prop('tabindex', tabindex).off(bindSufix).off(eventTriggers).unwrap().unwrap();
534
- isEnabled = false;
535
- }
536
- }
537
-
538
- _init(opts);
539
- };
540
-
541
- // A really lightweight plugin wrapper around the constructor,
542
- // preventing against multiple instantiations
543
- $.fn[pluginName] = function(args) {
544
- return this.each(function() {
545
- var data = $.data(this, pluginName);
546
-
547
- if ( data && !data.disableOnMobile )
548
- (''+args === args && data[args]) ? data[args]() : data.init(args);
549
- else
550
- $.data(this, pluginName, new Selectric(this, args));
551
- });
552
- };
553
-
554
- $.fn[pluginName].hooks = hooks;
555
- }(jQuery));