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
Release Info
Developer | DavidAnderson |
Plugin | 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 +166 -138
- backup.php +1 -1
- class-updraftplus.php +32 -4
- css/admin.css +98 -53
- includes/class-partialfileservlet.php +0 -2
- includes/class-udrpc.php +14 -13
- includes/selectric/jquery.selectric.js +0 -555
- includes/selectric/jquery.selectric.min.js +0 -2
- includes/selectric/selectric.css +0 -191
- includes/updraft-admin-ui.js +358 -188
- languages/updraftplus-ar.mo +0 -0
- languages/updraftplus-ar.po +1330 -1185
- languages/updraftplus-bn_BD.mo +0 -0
- languages/updraftplus-bn_BD.po +1330 -1185
- languages/updraftplus-ca_ES.po +1330 -1185
- languages/updraftplus-cs_CZ.mo +0 -0
- languages/updraftplus-cs_CZ.po +1330 -1185
- languages/updraftplus-da_DK.mo +0 -0
- languages/updraftplus-da_DK.po +615 -430
@@ -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(
|
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 |
-
|
1488 |
-
|
1489 |
-
|
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(
|
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 .= '
|
3678 |
}
|
3679 |
return $dir_info;
|
3680 |
}
|
3681 |
|
3682 |
-
|
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
|
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
|
3705 |
|
3706 |
|
3707 |
<?php
|
@@ -3720,7 +3717,7 @@ class UpdraftPlus_Admin {
|
|
3720 |
</tr>
|
3721 |
|
3722 |
<?php if (defined('UPDRAFTPLUS_EXPERIMENTAL') && UPDRAFTPLUS_EXPERIMENTAL) { ?>
|
3723 |
-
<tr
|
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
|
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
|
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
|
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 =
|
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
|
3781 |
-
|
3782 |
-
|
3783 |
-
|
|
|
|
|
3784 |
if (is_array($active_service)) $active_service = $updraftplus->just_one($active_service);
|
3785 |
-
|
3786 |
-
|
3787 |
-
|
3788 |
-
|
3789 |
-
|
3790 |
-
|
3791 |
-
|
3792 |
-
echo "
|
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 |
-
|
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="#"
|
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
|
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"
|
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
|
|
|
4003 |
<span id="updraft_writable_mess">
|
4004 |
<?php
|
4005 |
-
|
4006 |
-
|
4007 |
-
|
4008 |
-
|
|
|
|
|
|
|
|
|
4009 |
</tr>
|
4010 |
|
4011 |
<tr class="expertmode updraft-hidden" style="display:none;">
|
4012 |
-
<th><?php _e(
|
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 |
-
|
4036 |
-
|
4037 |
-
|
4038 |
-
|
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 |
-
$
|
|
|
|
|
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 |
-
|
|
|
|
|
|
|
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 {
|
@@ -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,
|
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 |
}
|
@@ -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
|
2366 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 (
|
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 |
}
|
@@ -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 |
+
}
|
@@ -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 |
|
@@ -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.
|
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 |
|
@@ -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">▾</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));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|