UpdraftPlus WordPress Backup Plugin - Version 1.12.15

Version Description

  • 06/Jul/2016 =

  • TWEAK: S3 now supports the new Mumbai region

  • TWEAK: If the user enters an AWS/S3 access key that looks prima facie invalid, then mention this in the error output

  • TWEAK: Make the message that the user is shown in the case of no network connectivity to updraftplus.com when connecting for updates (paid versions) clearer

  • TWEAK: Extend cacheing of enumeration of uploads that was introduced in 1.11.1 to other data in wp-content also

  • TWEAK: Avoid fatal error in Migrator if running via WP-CLI with the USER environment variable unset

  • TWEAK: When DB_CHARSET is defined but empty, treat it the same as if undefined

  • TWEAK: Add updraftplus_remotesend_udrpc_object_obtained action hook, allowing customisation of HTTP transport options for remote sending

  • TWEAK: Introduced new UPDRAFTPLUS_RESTORE_ALL_SETTINGS constant to assist in complicated load-balancing setups with duplicate install on the same URL

  • TWEAK: Update bundled tripleclick script to fix bug in teardown handler

  • TWEAK: Update bundled UDRPC library to version 1.4.8

  • TWEAK: Patch Labelauty to be friendly to screen-readers

  • TWEAK: Suppress the UD updates check on paid versions that immediately follows a WP automatic core security update

  • TWEAK: Handle missing UpdraftCentral command classes more elegantly

  • FEATURE: Endpoint handlers for forthcoming updates and user mangement features in UpdraftCentral

  • TRANSLATIONS: Remove bundled German (de_DE) translation, since this is now retrieved from wordpress.org

  • FIX: Fix inaccurate reporting of the current Vault quota usage in the report email

  • FIX: Fix logic errors in processing return codes when no direct MySQL/MySQLi connection was possible in restoring that could cause UpdraftPlus to wrongly conclude that restoring was not possible

Download this release

Release Info

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

Code changes from version 1.12.13 to 1.12.15

admin.php CHANGED
@@ -441,7 +441,7 @@ class UpdraftPlus_Admin {
441
 
442
  wp_enqueue_script('jquery-blockui', UPDRAFTPLUS_URL.'/includes/jquery.blockUI.js', array('jquery'), '2.70.0');
443
 
444
- wp_enqueue_script('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.js', array('jquery'), '20150925');
445
  wp_enqueue_style('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.css', array(), '20150925');
446
 
447
  do_action('updraftplus_admin_enqueue_scripts');
@@ -3790,7 +3790,9 @@ class UpdraftPlus_Admin {
3790
  $multi = apply_filters('updraftplus_storage_printoptions_multi', '');
3791
 
3792
  foreach($updraftplus->backup_methods as $method => $description) {
3793
- echo "<input name=\"updraft_service[]\" class=\"updraft_servicecheckbox $method $multi\" id=\"updraft_servicecheckbox_$method\" type=\"checkbox\" value=\"$method\"";
 
 
3794
  if ($active_service === $method || (is_array($active_service) && in_array($method, $active_service))) echo ' checked="checked"';
3795
  echo " data-labelauty=\"".esc_attr($description)."\">";
3796
  }
441
 
442
  wp_enqueue_script('jquery-blockui', UPDRAFTPLUS_URL.'/includes/jquery.blockUI.js', array('jquery'), '2.70.0');
443
 
444
+ wp_enqueue_script('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.js', array('jquery'), '20160622-ud');
445
  wp_enqueue_style('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.css', array(), '20150925');
446
 
447
  do_action('updraftplus_admin_enqueue_scripts');
3790
  $multi = apply_filters('updraftplus_storage_printoptions_multi', '');
3791
 
3792
  foreach($updraftplus->backup_methods as $method => $description) {
3793
+ $backup_using = esc_attr(sprintf(__("Backup using %s?", 'updraftplus'), $description));
3794
+
3795
+ echo "<input aria-label=\"$backup_using\" name=\"updraft_service[]\" class=\"updraft_servicecheckbox $method $multi\" id=\"updraft_servicecheckbox_$method\" type=\"checkbox\" value=\"$method\"";
3796
  if ($active_service === $method || (is_array($active_service) && in_array($method, $active_service))) echo ' checked="checked"';
3797
  echo " data-labelauty=\"".esc_attr($description)."\">";
3798
  }
backup.php CHANGED
@@ -1575,7 +1575,7 @@ class UpdraftPlus_Backup {
1575
  if ($sind % 100 == 0) $updraftplus->something_useful_happened();
1576
  }
1577
 
1578
- if (defined("DB_CHARSET")) {
1579
  $this->stow("/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
1580
  }
1581
 
@@ -1909,7 +1909,7 @@ class UpdraftPlus_Backup {
1909
  $this->stow("# Database: ".$updraftplus->backquote($this->dbinfo['name'])."\n");
1910
  $this->stow("# --------------------------------------------------------\n");
1911
 
1912
- if (defined("DB_CHARSET")) {
1913
  $this->stow("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n");
1914
  $this->stow("/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n");
1915
  $this->stow("/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n");
@@ -2291,7 +2291,7 @@ class UpdraftPlus_Backup {
2291
 
2292
  // Uploads: can/should we get it back from the cache?
2293
  // || 'others' == $whichone
2294
- if (('uploads' == $whichone ) && function_exists('gzopen') && function_exists('gzread')) {
2295
  $use_cache_files = false;
2296
  $cache_file_base = $this->zip_basename.'-cachelist-'.$this->makezip_if_altered_since;
2297
  // Cache file suffixes: -zfd.gz.tmp, -zfb.gz.tmp, -info.tmp, (possible)-zfs.gz.tmp
@@ -2377,7 +2377,7 @@ class UpdraftPlus_Backup {
2377
  // Cache the file scan, if it looks like it'll be useful
2378
  // We use gzip to reduce the size as on hosts which limit disk I/O, the cacheing may make things worse
2379
  // || 'others' == $whichone
2380
- if (('uploads' == $whichone) && !$error_occurred && function_exists('gzopen') && function_exists('gzwrite')) {
2381
  $cache_file_base = $this->zip_basename.'-cachelist-'.$this->makezip_if_altered_since;
2382
 
2383
  // Just approximate - we're trying to avoid an otherwise-unpredictable PHP fatal error. Cacheing only happens if file enumeration took a long time - so presumably there are very many.
@@ -2386,9 +2386,32 @@ class UpdraftPlus_Backup {
2386
 
2387
  // We haven't bothered to check if we just fetched the files from cache, as that shouldn't take a long time and so shouldn't trigger this
2388
  // Let us suppose we need 15% overhead for gzipping
 
 
 
 
 
2389
  if ($time_counting_ended-$time_counting_began > 20 && $updraftplus->verify_free_memory($memory_needed_estimate*0.15) && $whandle = gzopen($cache_file_base.'-zfb.gz.tmp', 'w')) {
2390
- $updraftplus->log("File counting took a long time (".($time_counting_ended - $time_counting_began)."s); will attempt to cache results (estimated uncompressed bytes: ".round($memory_needed_estimate/1024, 1)." Kb)");
2391
- if (!gzwrite($whandle, serialize($this->zipfiles_batched))) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2392
  @unlink($cache_file_base.'-zfb.gz.tmp');
2393
  @gzclose($whandle);
2394
  } else {
1575
  if ($sind % 100 == 0) $updraftplus->something_useful_happened();
1576
  }
1577
 
1578
+ if (@constant("DB_CHARSET")) {
1579
  $this->stow("/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
1580
  }
1581
 
1909
  $this->stow("# Database: ".$updraftplus->backquote($this->dbinfo['name'])."\n");
1910
  $this->stow("# --------------------------------------------------------\n");
1911
 
1912
+ if (@constant("DB_CHARSET")) {
1913
  $this->stow("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n");
1914
  $this->stow("/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n");
1915
  $this->stow("/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n");
2291
 
2292
  // Uploads: can/should we get it back from the cache?
2293
  // || 'others' == $whichone
2294
+ if (('uploads' == $whichone || 'others' == $whichone) && function_exists('gzopen') && function_exists('gzread')) {
2295
  $use_cache_files = false;
2296
  $cache_file_base = $this->zip_basename.'-cachelist-'.$this->makezip_if_altered_since;
2297
  // Cache file suffixes: -zfd.gz.tmp, -zfb.gz.tmp, -info.tmp, (possible)-zfs.gz.tmp
2377
  // Cache the file scan, if it looks like it'll be useful
2378
  // We use gzip to reduce the size as on hosts which limit disk I/O, the cacheing may make things worse
2379
  // || 'others' == $whichone
2380
+ if (('uploads' == $whichone|| 'others' == $whichone) && !$error_occurred && function_exists('gzopen') && function_exists('gzwrite')) {
2381
  $cache_file_base = $this->zip_basename.'-cachelist-'.$this->makezip_if_altered_since;
2382
 
2383
  // Just approximate - we're trying to avoid an otherwise-unpredictable PHP fatal error. Cacheing only happens if file enumeration took a long time - so presumably there are very many.
2386
 
2387
  // We haven't bothered to check if we just fetched the files from cache, as that shouldn't take a long time and so shouldn't trigger this
2388
  // Let us suppose we need 15% overhead for gzipping
2389
+
2390
+ $memory_limit = ini_get('memory_limit');
2391
+ $memory_usage = round(@memory_get_usage(false)/1048576, 1);
2392
+ $memory_usage2 = round(@memory_get_usage(true)/1048576, 1);
2393
+
2394
  if ($time_counting_ended-$time_counting_began > 20 && $updraftplus->verify_free_memory($memory_needed_estimate*0.15) && $whandle = gzopen($cache_file_base.'-zfb.gz.tmp', 'w')) {
2395
+ $updraftplus->log("File counting took a long time (".($time_counting_ended - $time_counting_began)."s); will attempt to cache results (memory_limit: $memory_limit (used: ${memory_usage}M | ${memory_usage2}M), estimated uncompressed bytes: ".round($memory_needed_estimate/1024, 1)." Kb)");
2396
+
2397
+ $buf = 'a:'.count($this->zipfiles_batched).':{';
2398
+ foreach ($this->zipfiles_batched as $file => $add_as) {
2399
+ $k = addslashes($file);
2400
+ $v = addslashes($add_as);
2401
+ $buf .= 's:'.strlen($k).':"'.$k.'";s:'.strlen($v).':"'.$v.'";';
2402
+ if (strlen($buf) > 1048576) {
2403
+ gzwrite($whandle, $buf, strlen($buf));
2404
+ $buf = '';
2405
+ }
2406
+ }
2407
+ $buf .= '}';
2408
+ $final = gzwrite($whandle, $buf);
2409
+ unset($buf);
2410
+
2411
+ // $serialised = serialize($this->zipfiles_batched);
2412
+ // $updraftplus->log("Actual uncompressed bytes: ".round(strlen($serialised)/1024, 1)." Kb");
2413
+ // if (!gzwrite($whandle, $serialised)) {
2414
+ if (!$final) {
2415
  @unlink($cache_file_base.'-zfb.gz.tmp');
2416
  @gzclose($whandle);
2417
  } else {
central/bootstrap.php CHANGED
@@ -22,6 +22,7 @@ class UpdraftPlus_UpdraftCentral_Main {
22
  'core' => 'UpdraftCentral_Core_Commands',
23
  'updraftplus' => 'UpdraftPlus_RemoteControl_Commands',
24
  'updates' => 'UpdraftCentral_Updates_Commands',
 
25
  ));
26
 
27
  // Remote control keys
22
  'core' => 'UpdraftCentral_Core_Commands',
23
  'updraftplus' => 'UpdraftPlus_RemoteControl_Commands',
24
  'updates' => 'UpdraftCentral_Updates_Commands',
25
+ 'users' => 'UpdraftCentral_Users_Commands',
26
  ));
27
 
28
  // Remote control keys
central/classes/class-automatic-upgrader-skin.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Extracted from 4.5.2/wordpress/wp-admin/includes/class-wp-upgrader-skins.php
4
+ // Needed only on WP < 3.7
5
+
6
+ /**
7
+ * Upgrader Skin for Automatic WordPress Upgrades
8
+ *
9
+ * This skin is designed to be used when no output is intended, all output
10
+ * is captured and stored for the caller to process and log/email/discard.
11
+ *
12
+ * @package WordPress
13
+ * @subpackage Upgrader
14
+ * @since 3.7.0
15
+ */
16
+ class Automatic_Upgrader_Skin extends WP_Upgrader_Skin {
17
+ protected $messages = array();
18
+
19
+ /**
20
+ *
21
+ * @param bool $error
22
+ * @param string $context
23
+ * @param bool $allow_relaxed_file_ownership
24
+ * @return bool
25
+ */
26
+ public function request_filesystem_credentials( $error = false, $context = '', $allow_relaxed_file_ownership = false ) {
27
+ if ( $context ) {
28
+ $this->options['context'] = $context;
29
+ }
30
+ // TODO: fix up request_filesystem_credentials(), or split it, to allow us to request a no-output version
31
+ // This will output a credentials form in event of failure, We don't want that, so just hide with a buffer
32
+ ob_start();
33
+ $result = parent::request_filesystem_credentials( $error, $context, $allow_relaxed_file_ownership );
34
+ ob_end_clean();
35
+ return $result;
36
+ }
37
+
38
+ /**
39
+ * @access public
40
+ *
41
+ * @return array
42
+ */
43
+ public function get_upgrade_messages() {
44
+ return $this->messages;
45
+ }
46
+
47
+ /**
48
+ * @param string|array|WP_Error $data
49
+ */
50
+ public function feedback( $data ) {
51
+ if ( is_wp_error( $data ) ) {
52
+ $string = $data->get_error_message();
53
+ } elseif ( is_array( $data ) ) {
54
+ return;
55
+ } else {
56
+ $string = $data;
57
+ }
58
+ if ( ! empty( $this->upgrader->strings[ $string ] ) )
59
+ $string = $this->upgrader->strings[ $string ];
60
+
61
+ if ( strpos( $string, '%' ) !== false ) {
62
+ $args = func_get_args();
63
+ $args = array_splice( $args, 1 );
64
+ if ( ! empty( $args ) )
65
+ $string = vsprintf( $string, $args );
66
+ }
67
+
68
+ $string = trim( $string );
69
+
70
+ // Only allow basic HTML in the messages, as it'll be used in emails/logs rather than direct browser output.
71
+ $string = wp_kses( $string, array(
72
+ 'a' => array(
73
+ 'href' => true
74
+ ),
75
+ 'br' => true,
76
+ 'em' => true,
77
+ 'strong' => true,
78
+ ) );
79
+
80
+ if ( empty( $string ) )
81
+ return;
82
+
83
+ $this->messages[] = $string;
84
+ }
85
+
86
+ /**
87
+ * @access public
88
+ */
89
+ public function header() {
90
+ ob_start();
91
+ }
92
+
93
+ /**
94
+ * @access public
95
+ */
96
+ public function footer() {
97
+ $output = ob_get_clean();
98
+ if ( ! empty( $output ) )
99
+ $this->feedback( $output );
100
+ }
101
+ }
central/listener.php CHANGED
@@ -109,15 +109,19 @@ class UpdraftPlus_UpdraftCentral_Listener {
109
 
110
  $command_php_class = $this->command_classes[$class_prefix];
111
 
112
- if (!class_exists($command_php_class)) require_once(UPDRAFTPLUS_DIR.'/central/'.$class_prefix.'-commands.php');
113
 
114
- if (empty($this->commands[$class_prefix])) $this->commands[$class_prefix] = new $command_php_class($this);
 
 
 
 
115
 
116
- $command_class = $this->commands[$class_prefix];
117
 
118
- if ('_' == substr($command, 0, 1) || !method_exists($command_class, $command)) {
119
  if (defined('UPDRAFTPLUS_UDRPC_FORCE_DEBUG') && UPDRAFTPLUS_UDRPC_FORCE_DEBUG) error_log("Unknown RPC command received: ".$command);
120
- return $this->return_rpc_message(array('response' => 'rpcerror', 'data' => array('code' => 'unknown_rpc_command', 'data' => $command)));
121
  }
122
 
123
  $extra_info = isset($this->extra_info[$key_name_indicator]) ? $this->extra_info[$key_name_indicator] : null;
109
 
110
  $command_php_class = $this->command_classes[$class_prefix];
111
 
112
+ if (!class_exists($command_php_class) && file_exists(UPDRAFTPLUS_DIR.'/central/'.$class_prefix.'-commands.php')) require_once(UPDRAFTPLUS_DIR.'/central/'.$class_prefix.'-commands.php');
113
 
114
+ if (empty($this->commands[$class_prefix])) {
115
+ if (class_exists($command_php_class)) {
116
+ $this->commands[$class_prefix] = new $command_php_class($this);
117
+ }
118
+ }
119
 
120
+ $command_class = isset($this->commands[$class_prefix]) ? $this->commands[$class_prefix] : new stdClass;
121
 
122
+ if ('_' == substr($command, 0, 1) || !is_a($command_class, $command_php_class) || !method_exists($command_class, $command)) {
123
  if (defined('UPDRAFTPLUS_UDRPC_FORCE_DEBUG') && UPDRAFTPLUS_UDRPC_FORCE_DEBUG) error_log("Unknown RPC command received: ".$command);
124
+ return $this->return_rpc_message(array('response' => 'rpcerror', 'data' => array('code' => 'unknown_rpc_command', 'data' => array('prefix' => $class_prefix, 'command' => $command, 'class' => $command_php_class))));
125
  }
126
 
127
  $extra_info = isset($this->extra_info[$key_name_indicator]) ? $this->extra_info[$key_name_indicator] : null;
central/updates-commands.php ADDED
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
+
5
+ if (!class_exists('UpdraftCentral_Commands')) require_once('commands.php');
6
+
7
+ class UpdraftCentral_Updates_Commands extends UpdraftCentral_Commands {
8
+
9
+ public function do_updates($updates) {
10
+
11
+ if (!is_array($updates)) $this->_generic_error_response('invalid_data');
12
+
13
+ if (!empty($updates['plugins']) && !current_user_can('update_plugins')) return $this->_generic_error_response('updates_permission_denied', 'update_plugins');
14
+
15
+ if (!empty($updates['themes']) && !current_user_can('update_themes')) return $this->_generic_error_response('updates_permission_denied', 'update_themes');
16
+
17
+ if (!empty($updates['core']) && !current_user_can('update_core')) return $this->_generic_error_response('updates_permission_denied', 'update_core');
18
+
19
+ $this->_admin_include('plugin.php', 'update.php', 'file.php', 'template.php');
20
+ $this->_frontend_include('update.php');
21
+
22
+ if (!empty($updates['meta']) && isset($updates['meta']['filesystem_credentials'])) {
23
+ parse_str($updates['meta']['filesystem_credentials'], $filesystem_credentials);
24
+ if (is_array($filesystem_credentials)) {
25
+ foreach ($filesystem_credentials as $key => $value) {
26
+ // Put them into $_POST, which is where request_filesystem_credentials() checks for them.
27
+ $_POST[$key] = $value;
28
+ }
29
+ }
30
+ }
31
+
32
+ $plugins = empty($updates['plugins']) ? array() : $updates['plugins'];
33
+ $plugin_updates = array();
34
+ foreach ($plugins as $plugin_info) {
35
+ $plugin_file = $plugin_info['plugin'];
36
+ $plugin_updates[] = $this->_update_plugin($plugin_info['plugin'], $plugin_info['slug']);
37
+ }
38
+
39
+ $themes = empty($updates['themes']) ? array() : $updates['themes'];
40
+ $theme_updates = array();
41
+ foreach ($themes as $theme_info) {
42
+ $theme = $theme_info['theme'];
43
+ $theme_updates[] = $this->_update_theme($theme);
44
+ }
45
+
46
+ $cores = empty($updates['core']) ? array() : $updates['core'];
47
+ $core_updates = array();
48
+ foreach ($cores as $core) {
49
+ $core_updates[] = $this->_update_core(null);
50
+ // Only one (and always we go to the latest version) - i.e. we ignore the passed parameters
51
+ break;
52
+ }
53
+
54
+ return $this->_response(array(
55
+ 'plugins' => $plugin_updates,
56
+ 'themes' => $theme_updates,
57
+ 'core' => $core_updates,
58
+ ));
59
+
60
+ }
61
+
62
+ // Mostly from wp_ajax_update_plugin() in wp-admin/includes/ajax-actions.php (WP 4.5.2)
63
+ // Code-formatting style has been retained from the original, for ease of comparison/updating
64
+ private function _update_plugin($plugin, $slug) {
65
+
66
+ $status = array(
67
+ 'update' => 'plugin',
68
+ 'plugin' => $plugin,
69
+ 'slug' => sanitize_key( $slug ),
70
+ 'oldVersion' => '',
71
+ 'newVersion' => '',
72
+ );
73
+
74
+ if (false !== strpos($plugin, '..') || false !== strpos($plugin, ':') || !preg_match('#^[^\/]#i', $plugin)) {
75
+ $status['error'] = 'not_found';
76
+ return $status;
77
+ }
78
+
79
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
80
+ if (!isset($plugin_data['Name']) || !isset($plugin_data['Author']) || ('' == $plugin_data['Name'] && '' == $plugin_data['Author'])) {
81
+ $status['error'] = 'not_found';
82
+ return $status;
83
+ }
84
+
85
+ if ( $plugin_data['Version'] ) {
86
+ $status['oldVersion'] = $plugin_data['Version'];
87
+ }
88
+
89
+ if ( ! current_user_can( 'update_plugins' ) ) {
90
+ $status['error'] = 'updates_permission_denied';
91
+ return $status;
92
+ }
93
+
94
+ include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
95
+
96
+ wp_update_plugins();
97
+
98
+ // WP < 3.7
99
+ if (!class_exists('Automatic_Upgrader_Skin')) require_once(UPDRAFTPLUS_DIR.'/central/classes/class-automatic-upgrader-skin.php');
100
+
101
+ $skin = new Automatic_Upgrader_Skin();
102
+ $upgrader = new Plugin_Upgrader( $skin );
103
+ $result = $upgrader->bulk_upgrade( array( $plugin ) );
104
+
105
+ if ( is_array( $result ) && empty( $result[$plugin] ) && is_wp_error( $skin->result ) ) {
106
+ $result = $skin->result;
107
+ }
108
+
109
+ $status['messages'] = $upgrader->skin->get_upgrade_messages();
110
+
111
+ if ( is_array( $result ) && !empty( $result[ $plugin ] ) ) {
112
+ $plugin_update_data = current( $result );
113
+
114
+ /*
115
+ * If the `update_plugins` site transient is empty (e.g. when you update
116
+ * two plugins in quick succession before the transient repopulates),
117
+ * this may be the return.
118
+ *
119
+ * Preferably something can be done to ensure `update_plugins` isn't empty.
120
+ * For now, surface some sort of error here.
121
+ */
122
+ if ( $plugin_update_data === true ) {
123
+ $status['error'] = 'update_failed';
124
+ return $status;
125
+ }
126
+
127
+ $plugin_data = get_plugins( '/' . $result[ $plugin ]['destination_name'] );
128
+ $plugin_data = reset( $plugin_data );
129
+
130
+ if ( $plugin_data['Version'] ) {
131
+ $status['newVersion'] = $plugin_data['Version'];
132
+ }
133
+ return $status;
134
+
135
+ } else if ( is_wp_error( $result ) ) {
136
+ $status['error'] = $result->get_error_code();
137
+ $status['error_message'] = $result->get_error_message();
138
+ return $status;
139
+
140
+ } else if ( is_bool( $result ) && ! $result ) {
141
+ $status['error'] = 'unable_to_connect_to_filesystem';
142
+
143
+ global $wp_filesystem;
144
+
145
+ // Pass through the error from WP_Filesystem if one was raised
146
+ if ( isset($wp_filesystem->errors) && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
147
+ $status['error'] = $wp_filesystem->errors->get_error_code();
148
+ $status['error_message'] = $wp_filesystem->errors->get_error_message();
149
+ }
150
+
151
+ return $status;
152
+
153
+ } else {
154
+ // An unhandled error occured
155
+ $status['error'] = 'update_failed';
156
+ return $status;
157
+ }
158
+ }
159
+
160
+ // Adapted from _update_theme (above)
161
+ private function _update_core($core) {
162
+
163
+ global $wp_filesystem;
164
+
165
+ $status = array(
166
+ 'update' => 'core',
167
+ 'core' => $core,
168
+ 'oldVersion' => '',
169
+ 'newVersion' => '',
170
+ );
171
+
172
+ include(ABSPATH.WPINC.'/version.php');
173
+
174
+ $status['oldVersion'] = $wp_version;
175
+
176
+ if ( ! current_user_can( 'update_core' ) ) {
177
+ $status['error'] = 'updates_permission_denied';
178
+ return $status;
179
+ }
180
+
181
+ include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
182
+
183
+ wp_version_check();
184
+
185
+ $locale = get_locale();
186
+
187
+ $core_update_key = false;
188
+ $core_update_latest_version = false;
189
+
190
+ $get_core_updates = get_core_updates();
191
+
192
+ @include(ABSPATH.WPINC.'/version.php');
193
+
194
+ foreach ($get_core_updates as $k => $core_update) {
195
+ if (isset($core_update->version) && version_compare($core_update->version, $wp_version, '>') && version_compare($core_update->version, $core_update_latest_version, '>')) {
196
+ $core_update_latest_version = $core_update->version;
197
+ $core_update_key = $k;
198
+ }
199
+ }
200
+
201
+ if ( $core_update_key === false ) {
202
+ $status['error'] = 'no_update_found';
203
+ return $status;
204
+ }
205
+
206
+ $update = $get_core_updates[$core_update_key];
207
+
208
+ // WP < 3.7
209
+ if (!class_exists('Automatic_Upgrader_Skin')) require_once(UPDRAFTPLUS_DIR.'/central/classes/class-automatic-upgrader-skin.php');
210
+
211
+ $skin = new Automatic_Upgrader_Skin();
212
+ $upgrader = new Core_Upgrader( $skin );
213
+
214
+ $result = $upgrader->upgrade($update);
215
+
216
+ $status['messages'] = $upgrader->skin->get_upgrade_messages();
217
+
218
+ if ( is_wp_error( $result ) ) {
219
+ $status['error'] = $result->get_error_code();
220
+ $status['error_message'] = $result->get_error_message();
221
+ return $status;
222
+
223
+ } else if ( is_bool( $result ) && ! $result ) {
224
+ $status['error'] = 'unable_to_connect_to_filesystem';
225
+
226
+ // Pass through the error from WP_Filesystem if one was raised
227
+ if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
228
+ $status['error'] = $wp_filesystem->errors->get_error_code();
229
+ $status['error_message'] = $wp_filesystem->errors->get_error_message();
230
+ }
231
+
232
+ return $status;
233
+
234
+
235
+ } elseif ( preg_match('/^[0-9]/', $result) ) {
236
+
237
+ $status['newVersion'] = $result;
238
+
239
+ return $status;
240
+
241
+ } else {
242
+ // An unhandled error occured
243
+ $status['error'] = 'update_failed';
244
+ return $status;
245
+ }
246
+
247
+ }
248
+
249
+ private function _update_theme($theme) {
250
+
251
+ global $wp_filesystem;
252
+
253
+ $status = array(
254
+ 'update' => 'theme',
255
+ 'theme' => $theme,
256
+ 'oldVersion' => '',
257
+ 'newVersion' => '',
258
+ );
259
+
260
+ if (false !== strpos($theme, '/') || false !== strpos($theme, '\\')) {
261
+ $status['error'] = 'not_found';
262
+ return $status;
263
+ }
264
+
265
+ $theme_version = $this->get_theme_version($theme);
266
+ if (false === $theme_version) {
267
+ $status['error'] = 'not_found';
268
+ return $status;
269
+ }
270
+ $status['oldVersion'] = $theme_version;
271
+
272
+ if ( ! current_user_can( 'update_themes' ) ) {
273
+ $status['error'] = 'updates_permission_denied';
274
+ return $status;
275
+ }
276
+
277
+ include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
278
+
279
+ wp_update_themes();
280
+
281
+ // WP < 3.7
282
+ if (!class_exists('Automatic_Upgrader_Skin')) require_once(UPDRAFTPLUS_DIR.'/central/classes/class-automatic-upgrader-skin.php');
283
+
284
+ $skin = new Automatic_Upgrader_Skin();
285
+ $upgrader = new Theme_Upgrader( $skin );
286
+ $upgrader->init();
287
+ $result = $upgrader->bulk_upgrade( array($theme) );
288
+
289
+ if ( is_array( $result ) && empty( $result[$theme] ) && is_wp_error( $skin->result ) ) {
290
+ $result = $skin->result;
291
+ }
292
+
293
+ $status['messages'] = $upgrader->skin->get_upgrade_messages();
294
+
295
+ if ( is_array( $result ) && !empty( $result[ $theme ] ) ) {
296
+ $theme_update_data = current( $result );
297
+
298
+ /*
299
+ * If the `update_themes` site transient is empty (e.g. when you update
300
+ * two plugins in quick succession before the transient repopulates),
301
+ * this may be the return.
302
+ *
303
+ * Preferably something can be done to ensure `update_themes` isn't empty.
304
+ * For now, surface some sort of error here.
305
+ */
306
+ if ( $theme_update_data === true ) {
307
+ $status['error'] = 'update_failed';
308
+ return $status;
309
+ }
310
+
311
+ $new_theme_version = $this->get_theme_version($theme);
312
+ if (false === $new_theme_version) {
313
+ $status['error'] = 'update_failed';
314
+ return $status;
315
+ }
316
+
317
+ $status['newVersion'] = $new_theme_version;
318
+
319
+ return $status;
320
+
321
+ } else if ( is_wp_error( $result ) ) {
322
+ $status['error'] = $result->get_error_code();
323
+ $status['error_message'] = $result->get_error_message();
324
+ return $status;
325
+
326
+ } else if ( is_bool( $result ) && ! $result ) {
327
+ $status['error'] = 'unable_to_connect_to_filesystem';
328
+
329
+ // Pass through the error from WP_Filesystem if one was raised
330
+ if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
331
+ $status['error'] = $wp_filesystem->errors->get_error_code();
332
+ $status['error_message'] = $wp_filesystem->errors->get_error_message();
333
+ }
334
+
335
+ return $status;
336
+
337
+ } else {
338
+ // An unhandled error occured
339
+ $status['error'] = 'update_failed';
340
+ return $status;
341
+ }
342
+
343
+ }
344
+
345
+ private function get_theme_version($theme) {
346
+
347
+ if (function_exists('wp_get_theme')) {
348
+ // Since WP 3.4.0
349
+ $theme = wp_get_theme($theme);
350
+
351
+ if (is_a($theme, 'WP_Theme')) {
352
+ return $theme->Version;
353
+ } else {
354
+ return false;
355
+ }
356
+
357
+ } else {
358
+ $theme_data = get_theme_data(WP_CONTENT_DIR . '/themes/'.$theme.'/style.css');
359
+
360
+ if (isset($theme_data['Version'])) {
361
+ return $theme_data['Version'];
362
+ } else {
363
+ return false;
364
+ }
365
+ }
366
+ }
367
+
368
+ public function get_updates($options) {
369
+
370
+ if (!current_user_can('update_plugins') && !current_user_can('update_themes') && !current_user_can('update_core')) return $this->_generic_error_response('updates_permission_denied');
371
+
372
+ $this->_admin_include('plugin.php', 'update.php', 'file.php', 'template.php');
373
+ $this->_frontend_include('update.php');
374
+
375
+ if (!is_array($options)) $options = array();
376
+
377
+ // Normalise it
378
+ $plugin_updates = array();
379
+ if (current_user_can('update_plugins')) {
380
+
381
+ // Detect if refresh needed
382
+ $transient = get_site_transient('update_plugins');
383
+ if (!empty($options['force_refresh']) || false === $transient) {
384
+ delete_site_transient('update_plugins');
385
+ wp_update_plugins();
386
+ }
387
+
388
+ $get_plugin_updates = get_plugin_updates();
389
+ if (is_array($get_plugin_updates)) {
390
+ foreach ($get_plugin_updates as $update) {
391
+ $plugin_updates[] = array(
392
+ 'name' => $update->Name,
393
+ 'plugin_uri' => $update->PluginURI,
394
+ 'version' => $update->Version,
395
+ 'description' => $update->Description,
396
+ 'author' => $update->Author,
397
+ 'author_uri' => $update->AuthorURI,
398
+ 'title' => $update->Title,
399
+ 'author_name' => $update->AuthorName,
400
+ 'update' => array(
401
+ 'plugin' => $update->update->plugin,
402
+ 'slug' => $update->update->slug,
403
+ 'new_version' => $update->update->new_version,
404
+ 'package' => $update->update->package,
405
+ 'tested' => isset($update->update->tested) ? $update->update->tested : null,
406
+ 'compatibility' => isset($update->update->compatibility) ? (array)$update->update->compatibility : null,
407
+ 'sections' => isset($update->update->sections) ? (array)$update->update->sections : null,
408
+ ),
409
+ );
410
+ }
411
+ }
412
+ }
413
+
414
+ $theme_updates = array();
415
+ if (current_user_can('update_themes')) {
416
+
417
+ // Detect if refresh needed
418
+ $transient = get_site_transient('update_themes');
419
+ if (!empty($options['force_refresh']) || false === $transient) {
420
+ delete_site_transient('update_themes');
421
+ wp_update_themes();
422
+ }
423
+ $get_theme_updates = get_theme_updates();
424
+ if (is_array($get_theme_updates)) {
425
+ foreach ($get_theme_updates as $update) {
426
+ $theme_updates[] = array(
427
+ 'name' => $update->get('Name'),
428
+ 'theme_uri' => $update->get('ThemeURI'),
429
+ 'version' => $update->get('Version'),
430
+ 'description' => $update->get('Description'),
431
+ 'author' => $update->get('Author'),
432
+ 'author_uri' => $update->get('AuthorURI'),
433
+ 'update' => array(
434
+ 'theme' => $update->update['theme'],
435
+ 'new_version' => $update->update['new_version'],
436
+ 'package' => $update->update['package'],
437
+ 'url' => $update->update['url'],
438
+ ),
439
+ );
440
+ }
441
+ }
442
+ }
443
+
444
+ $core_updates = array();
445
+ if (current_user_can('update_core')) {
446
+
447
+ // Detect if refresh needed
448
+ $transient = get_site_transient('update_core');
449
+ if (!empty($options['force_refresh']) || false === $transient) {
450
+ // The next line is only needed for older WP versions - otherwise, the parameter to wp_version_check forces a check.
451
+ delete_site_transient('update_core');
452
+ wp_version_check(array(), true);
453
+ }
454
+
455
+ $get_core_updates = get_core_updates();
456
+
457
+ if (is_array($get_core_updates)) {
458
+
459
+ $core_update_key = false;
460
+ $core_update_latest_version = false;
461
+
462
+ @include(ABSPATH.WPINC.'/version.php');
463
+
464
+ foreach ($get_core_updates as $k => $core_update) {
465
+ if (isset($core_update->version) && version_compare($core_update->version, $wp_version, '>') && version_compare($core_update->version, $core_update_latest_version, '>')) {
466
+ $core_update_latest_version = $core_update->version;
467
+ $core_update_key = $k;
468
+ }
469
+ }
470
+
471
+ if ($core_update_key !== false) {
472
+
473
+ $update = $get_core_updates[$core_update_key];
474
+
475
+ global $wpdb;
476
+
477
+ $mysql_version = $wpdb->db_version();
478
+
479
+ $is_mysql = (file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql )) ? false : true;
480
+
481
+ $core_updates[] = array(
482
+ 'download' => $update->download,
483
+ 'version' => $update->version,
484
+ 'php_version' => $update->php_version,
485
+ 'mysql_version' => $update->mysql_version,
486
+ 'installed' => array(
487
+ 'version' => $wp_version,
488
+ 'mysql' => $mysql_version,
489
+ 'php' => PHP_VERSION,
490
+ 'is_mysql' => $is_mysql,
491
+ ),
492
+ 'sufficient' => array(
493
+ 'mysql' => version_compare($mysql_version, $update->mysql_version, '>='),
494
+ 'php' => version_compare(PHP_VERSION, $update->php_version, '>='),
495
+ ),
496
+ );
497
+
498
+ }
499
+ }
500
+
501
+ }
502
+
503
+
504
+ // Do we need to ask the user for filesystem credentials?
505
+ $request_filesystem_credentials = array();
506
+ $check_fs = array(
507
+ 'plugins' => WP_PLUGIN_DIR,
508
+ 'themes' => WP_CONTENT_DIR.'/themes',
509
+ 'core' => untrailingslashit(ABSPATH)
510
+ );
511
+
512
+ foreach ($check_fs as $entity => $dir) {
513
+ $filesystem_method = get_filesystem_method(array(), $dir);
514
+ ob_start();
515
+ $filesystem_credentials_are_stored = request_filesystem_credentials(site_url());
516
+ $filesystem_form = strip_tags(ob_get_contents(), '<div><h2><p><input><label><fieldset><legend><span><em>');
517
+ ob_end_clean();
518
+ $request_filesystem_credentials[$entity] = ($filesystem_method != 'direct' && ! $filesystem_credentials_are_stored);
519
+ }
520
+
521
+ $automatic_backups = (class_exists('UpdraftPlus_Options') && class_exists('UpdraftPlus_Addon_Autobackup') && UpdraftPlus_Options::get_updraft_option('updraft_autobackup_default', true)) ? true : false;
522
+
523
+ return $this->_response(array(
524
+ 'plugins' => $plugin_updates,
525
+ 'themes' => $theme_updates,
526
+ 'core' => $core_updates,
527
+ 'meta' => array(
528
+ 'request_filesystem_credentials' => $request_filesystem_credentials,
529
+ 'filesystem_form' => $filesystem_form,
530
+ 'automatic_backups' => $automatic_backups
531
+ ),
532
+ ));
533
+ }
534
+
535
+ }
central/users-commands.php ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
+
5
+ if (!class_exists('UpdraftCentral_Commands')) require_once('commands.php');
6
+
7
+ class UpdraftCentral_Users_Commands extends UpdraftCentral_Commands {
8
+
9
+ private function _search_users($query){
10
+ $this->_admin_include('user.php');
11
+ $query1 = new WP_User_Query( array (
12
+ 'orderby' => 'ID',
13
+ 'order' => 'ASC',
14
+ 'role'=> $query["role"],
15
+ 'search' => '*' . esc_attr( $query["search"] ) . '*',
16
+ ));
17
+ $query2 = new WP_User_Query( array (
18
+ 'orderby' => 'ID',
19
+ 'order' => 'ASC',
20
+ 'role'=> $query["role"],
21
+ 'meta_query'=>array(
22
+ 'relation' => 'OR',
23
+ array(
24
+ 'key' => 'first_name',
25
+ 'value' => $query["search"],
26
+ 'compare' => 'LIKE'
27
+ ),
28
+ array(
29
+ 'key' => 'last_name',
30
+ 'value' => $query["search"],
31
+ 'compare' => 'LIKE'
32
+ ),
33
+ )
34
+ ));
35
+
36
+ if(empty( $query1->results)){
37
+ $query1->results = array();
38
+ }
39
+ if(empty( $query2->results)){
40
+ $query2->results = array();
41
+ }
42
+ if(empty($query1->results) && empty($query2->results)){
43
+ return array("message" => "users_not_found");
44
+ }
45
+
46
+ $found_users = array_merge($query1->results, $query2->results);
47
+ $users = array();
48
+ foreach ($found_users as $new_user) {
49
+ $new = true;
50
+ foreach ($users as $user) {
51
+ if($new_user == $user){
52
+ $new = false;
53
+ }
54
+ };
55
+ if($new){
56
+ array_push($users, $new_user);
57
+ }
58
+ };
59
+ return array("users" => $users, "count"=>count($users));
60
+ }
61
+
62
+ private function _calculate_pages($query){
63
+ $per_page_options = array();
64
+ for($i = 1; $i < 6; $i++){
65
+ $value = $i * 10;
66
+ array_push($per_page_options, $value );
67
+ };
68
+
69
+ if(!empty($query)){
70
+ $pages = array();
71
+ $page_query = new WP_User_Query(array('role'=> $query["role"]));
72
+ $page_count = ceil($page_query->total_users / $query["per_page"]);
73
+ if($page_count > 1){
74
+
75
+ for($i = 0; $i < $page_count; $i++){
76
+ if( $i + 1 == $query["page_no"]){
77
+ $paginator_item = array(
78
+ "value"=>$i+1,
79
+ "setting"=>"disabled"
80
+ );
81
+ }else{
82
+ $paginator_item = array(
83
+ "value"=>$i+1
84
+ );
85
+ }
86
+ array_push($pages, $paginator_item);
87
+ };
88
+
89
+ if($query["page_no"] >= $page_count){
90
+ $page_next = array(
91
+ "value"=>$page_count,
92
+ "setting"=>"disabled"
93
+ );
94
+ }else{
95
+ $page_next = array(
96
+ "value"=>$query["page_no"] + 1
97
+ );
98
+ };
99
+ if($query["page_no"] === 1){
100
+ $page_prev = array(
101
+ "value"=>1,
102
+ "setting"=>"disabled"
103
+ );
104
+ }else{
105
+ $page_prev = array(
106
+ "value"=>$query["page_no"] - 1
107
+ );
108
+ };
109
+
110
+ return array(
111
+ "page_no" => $query["page_no"],
112
+ "per_page" => $query["per_page"],
113
+ "page_count" => $page_count,
114
+ "pages" => $pages,
115
+ "page_next" => $page_next,
116
+ "page_prev" => $page_prev,
117
+ "total_results" => $page_query->total_users,
118
+ "per_page_options" => $per_page_options
119
+ );
120
+
121
+ }
122
+ else{
123
+ return array(
124
+ "page_no" => $query["page_no"],
125
+ "per_page" => $query["per_page"],
126
+ "page_count" => $page_count,
127
+ "total_results" => $page_query->total_users,
128
+ "per_page_options" => $per_page_options
129
+ );
130
+ }
131
+ }
132
+ else{
133
+ return array(
134
+ "per_page_options" => $per_page_options
135
+ );
136
+ }
137
+ }
138
+
139
+ public function check_username($username){
140
+ $this->_admin_include('user.php');
141
+ if(username_exists($username)){
142
+ $result = array("valid"=>false, "message"=>'username_exists');
143
+ return $this->_response($result);
144
+ }
145
+
146
+ $result = array("valid"=>true, "message"=>'username_valid');
147
+ return $this->_response($result);
148
+ }
149
+
150
+ public function check_email($email){
151
+ $this->_admin_include('user.php');
152
+
153
+ if (is_email($email) === false){
154
+ $result = array("valid"=> false, "message"=>'email_invalid');
155
+ return $this->_response($result);
156
+ }
157
+
158
+ if (email_exists($email)){
159
+ $result = array("valid"=> false, "message"=>'email_exists');
160
+ return $this->_response($result);
161
+ }
162
+
163
+ $result = array("valid"=> true, "message"=>'email_valid');
164
+ return $this->_response($result);
165
+ }
166
+
167
+ public function get_users($query) {
168
+ $this->_admin_include('user.php');
169
+
170
+ if(!empty($query["search"])){
171
+ return $this->_response($this->_search_users($query));
172
+ }
173
+
174
+ if(empty($query["per_page"])){ $query["per_page"] = 10; }
175
+ if(empty($query["page_no"])){ $query["page_no"] = 1; }
176
+ if(empty($query["role"])){ $query["role"] = ""; }
177
+
178
+ $user_query = new WP_User_Query(array(
179
+ 'orderby' => 'ID',
180
+ 'order' => 'ASC',
181
+ 'number' => $query["per_page"],
182
+ 'paged'=> $query["page_no"],
183
+ 'role'=> $query["role"]
184
+ ));
185
+
186
+ if(empty( $user_query->results)){
187
+ $result = array("message"=>'users_not_found');
188
+ return $this->_response($result);
189
+ }
190
+
191
+ $users = $user_query->results;
192
+ foreach ( $users as $key => $user) {
193
+ $user->first_name = get_user_meta($user->ID, 'first_name' , true);
194
+ $user->last_name = get_user_meta($user->ID, 'last_name' , true);
195
+ $user->description = get_user_meta($user->ID, 'description' , true);
196
+ }
197
+ $result = array(
198
+ "users"=>$users,
199
+ "paging" => $this->_calculate_pages($query)
200
+ );
201
+
202
+
203
+ return $this->_response($result);
204
+ }
205
+
206
+ public function add_user($user){
207
+ $this->_admin_include('user.php');
208
+
209
+ if(!current_user_can('create_users') && !is_super_admin()){
210
+ $result = array("error" => true, "message" => "user_create_no_premission");
211
+ return $this->_response($result);
212
+ }
213
+ if ( is_email($user["user_email"]) === false){
214
+ $result = array("error" => true, "message" => "email_invalid");
215
+ return $this->_response($result);
216
+ }
217
+ if (email_exists( $user["user_email"] )){
218
+ $result = array("error" => true, "message" => "email_exsists");
219
+ return $this->_response($result);
220
+ }
221
+ if(username_exists($user["user_login"])){
222
+ $result = array("error" => true, "message" => "username_exsists");
223
+ return $this->_response($result);
224
+ }
225
+
226
+ $user_id = wp_insert_user( $user ) ;
227
+ if($user_id > 0){
228
+ $result = array("error" => false, "message"=>"user_created_with_user_name", "values" => array($user['user_login']));
229
+ return $this->_response($result);
230
+ }else{
231
+ $result = array("error" => true, "message"=>"user_create_failed", "values" => array($user));
232
+ }
233
+ return $this->_response($result);
234
+ }
235
+
236
+ public function delete_user($user_id){
237
+ $this->_admin_include('user.php');
238
+
239
+ if(!current_user_can('delete_users') && !is_super_admin()){
240
+ $result = array("error" => true, "message" => "user_delete_no_premission");
241
+ return $this->_response($result);
242
+ }
243
+ if ( get_userdata( $user_id ) === false ) {
244
+ $result = array("error" => true, "message"=>"user_not_found");
245
+ return $this->_response($result);
246
+ }
247
+
248
+ if(wp_delete_user($user_id)){
249
+ $result = array("error" => false, "message"=>"user_deleted");
250
+ }else{
251
+ $result = array("error" => true, "message"=>"user_delete_failed");
252
+ }
253
+ return $this->_response($result);
254
+ }
255
+
256
+ public function edit_user($user){
257
+ $this->_admin_include('user.php');
258
+
259
+ if(!current_user_can('edit_users') && !is_super_admin() && $user["ID"] !== get_current_user_id()){
260
+ $result = array("error" => true, "message" => "user_edit_no_premission");
261
+ return $this->_response($result);
262
+ }
263
+ if ( get_userdata( $user["ID"] ) === false ) {
264
+ $result = array("error" => true, "message"=>"user_not_found");
265
+ return $this->_response($result);
266
+ }
267
+ if($user["ID"] == get_current_user_id()){
268
+ unset($user["role"]);
269
+ }
270
+
271
+ $user_id = wp_update_user( $user );
272
+ if ( is_wp_error( $user_id ) ) {
273
+ $result = array("error" => true, "message" => "user_edit_failed_with_error", "values" => array($user_id));
274
+ } else {
275
+ $result = array("error" => false, "message" => "user_edited_with_user_name", "values" => array($user["user_login"]));
276
+ }
277
+ return $this->_response($result);
278
+ }
279
+
280
+ public function get_roles(){
281
+ $this->_admin_include('user.php');
282
+ $roles = array_reverse( get_editable_roles() );
283
+ return $this->_response($roles);
284
+ }
285
+
286
+ public function get_user_filters(){
287
+ $this->_admin_include('user.php');
288
+ $result = array(
289
+ "roles" => array_reverse(get_editable_roles()),
290
+ "paging" => $this->_calculate_pages(null),
291
+ );
292
+ return $this->_response($result);
293
+ }
294
+ }
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.4.7';
63
 
64
  private $key_name_indicator;
65
 
@@ -680,26 +680,12 @@ class UpdraftPlus_Remote_Communications {
680
  }
681
 
682
  $time_difference = absint(time() - $json_decoded['time']);
683
- if ($time_difference > $this->maximum_replay_time_difference) return array(
684
- 'response' => 'rpcerror',
685
- 'data' => array(
686
- 'code' => 'window_error',
687
- 'difference' => $time_difference,
688
- 'maximum_difference' => $this->maximum_replay_time_difference
689
- )
690
- );
691
 
692
  if (isset($json_decoded['incoming_rand']) && !empty($this->message_random_number) && $json_decoded['incoming_rand'] != $this->message_random_number) {
693
  $this->log("UDRPC: Message mismatch (possibly MITM) (sent_rand="+$this->message_random_number+", returned_rand=".$json_decoded['incoming_rand']."): dropping", 'error');
694
 
695
- return array(
696
- 'response' => 'rpcerror',
697
- 'data' => array(
698
- 'code' => 'message_mismatch_error',
699
- 'ours' => $this->message_random_number,
700
- 'returned' => $json_decoded['incoming_rand']
701
- )
702
- );
703
 
704
  }
705
 
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.4.8';
63
 
64
  private $key_name_indicator;
65
 
680
  }
681
 
682
  $time_difference = absint(time() - $json_decoded['time']);
683
+ if ($time_difference > $this->maximum_replay_time_difference) return new WP_Error('window_error', 'Message refused: maxium replay time difference exceeded', $time_difference);
 
 
 
 
 
 
 
684
 
685
  if (isset($json_decoded['incoming_rand']) && !empty($this->message_random_number) && $json_decoded['incoming_rand'] != $this->message_random_number) {
686
  $this->log("UDRPC: Message mismatch (possibly MITM) (sent_rand="+$this->message_random_number+", returned_rand=".$json_decoded['incoming_rand']."): dropping", 'error');
687
 
688
+ return new WP_Error('message_mismatch_error', 'Message refused: message mismatch (possible MITM)');
 
 
 
 
 
 
 
689
 
690
  }
691
 
includes/labelauty/jquery-labelauty.js CHANGED
@@ -61,11 +61,19 @@
61
  return this.each(function()
62
  {
63
  var $object = $( this );
 
 
64
  var use_labels = true;
65
  var labels;
66
  var labels_object;
67
  var input_id;
68
-
 
 
 
 
 
 
69
  // Test if object is a check input
70
  // Don't mess me up, come on
71
  if( $object.is( ":checkbox" ) === false && $object.is( ":radio" ) === false )
@@ -74,11 +82,11 @@
74
  // Add "labelauty" class to all checkboxes
75
  // So you can apply some custom styles
76
  $object.addClass( settings.class );
77
-
78
  // Get the value of "data-labelauty" attribute
79
  // Then, we have the labels for each case (or not, as we will see)
80
  labels = $object.attr( "data-labelauty" );
81
-
82
  use_labels = settings.label;
83
 
84
  // It's time to check if it's going to the right way
@@ -123,11 +131,11 @@
123
  // Start hiding ugly checkboxes
124
  // Obviously, we don't need native checkboxes :O
125
  $object.css({ display : "none" });
126
-
127
  // We don't need more data-labelauty attributes!
128
  // Ok, ok, it's just for beauty improvement
129
  $object.removeAttr( "data-labelauty" );
130
-
131
  // Now, grab checkbox ID Attribute for "label" tag use
132
  // If there's no ID Attribute, then generate a new one
133
  input_id = $object.attr( "id" );
@@ -151,8 +159,32 @@
151
 
152
  // Now, add necessary tags to make this work
153
  // Here, we're going to test some control variables and act properly
154
- $object.after( create( input_id, labels_object, use_labels ) );
155
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  // Now, add "min-width" to label
157
  // Let's say the truth, a fixed width is more beautiful than a variable width
158
  if( settings.minimum_width !== false )
@@ -198,12 +230,13 @@
198
  window.console.log( "jQuery-LABELAUTY: " + message );
199
  };
200
 
201
- function create( input_id, messages_object, label )
202
- {
203
  var block;
204
  var unchecked_message;
205
  var checked_message;
206
-
 
207
  if( messages_object == null )
208
  unchecked_message = checked_message = "";
209
  else
@@ -216,10 +249,15 @@
216
  else
217
  checked_message = messages_object[1];
218
  }
219
-
 
 
 
 
 
220
  if( label == true )
221
  {
222
- block = '<label for="' + input_id + '">' +
223
  '<span class="labelauty-unchecked-image"></span>' +
224
  '<span class="labelauty-unchecked">' + unchecked_message + '</span>' +
225
  '<span class="labelauty-checked-image"></span>' +
@@ -228,13 +266,13 @@
228
  }
229
  else
230
  {
231
- block = '<label for="' + input_id + '">' +
232
  '<span class="labelauty-unchecked-image"></span>' +
233
  '<span class="labelauty-checked-image"></span>' +
234
  '</label>';
235
  }
236
-
237
  return block;
238
  };
239
 
240
- }( jQuery ));
61
  return this.each(function()
62
  {
63
  var $object = $( this );
64
+ var selected = $object.is(':checked');
65
+ var type = $object.attr('type');
66
  var use_labels = true;
67
  var labels;
68
  var labels_object;
69
  var input_id;
70
+
71
+ //Get the aria label from the input element
72
+ var aria_label = $object.attr( "aria-label" );
73
+
74
+ // Hide the object form screen readers
75
+ $object.attr( "aria-hidden", true );
76
+
77
  // Test if object is a check input
78
  // Don't mess me up, come on
79
  if( $object.is( ":checkbox" ) === false && $object.is( ":radio" ) === false )
82
  // Add "labelauty" class to all checkboxes
83
  // So you can apply some custom styles
84
  $object.addClass( settings.class );
85
+
86
  // Get the value of "data-labelauty" attribute
87
  // Then, we have the labels for each case (or not, as we will see)
88
  labels = $object.attr( "data-labelauty" );
89
+
90
  use_labels = settings.label;
91
 
92
  // It's time to check if it's going to the right way
131
  // Start hiding ugly checkboxes
132
  // Obviously, we don't need native checkboxes :O
133
  $object.css({ display : "none" });
134
+
135
  // We don't need more data-labelauty attributes!
136
  // Ok, ok, it's just for beauty improvement
137
  $object.removeAttr( "data-labelauty" );
138
+
139
  // Now, grab checkbox ID Attribute for "label" tag use
140
  // If there's no ID Attribute, then generate a new one
141
  input_id = $object.attr( "id" );
159
 
160
  // Now, add necessary tags to make this work
161
  // Here, we're going to test some control variables and act properly
162
+
163
+ var element = jQuery(create( input_id, aria_label, selected, type, labels_object, use_labels ))
164
+
165
+ element.click(function(){
166
+ if($object.is(':checked')){
167
+ $(element).attr('aria-checked', false);
168
+ }else{
169
+ $(element).attr('aria-checked', true);
170
+ }
171
+ });
172
+
173
+ element.keypress(function(event){
174
+ event.preventDefault();
175
+ if(event.keyCode === 32 || event.keyCode === 13){
176
+ if($object.is(':checked')){
177
+ $object.prop('checked', false);
178
+ $(element).attr('aria-checked',false);
179
+ }else{
180
+ $object.prop('checked', true);
181
+ $(element).attr('aria-checked', true);
182
+ }
183
+ }
184
+ })
185
+
186
+ $object.after(element);
187
+
188
  // Now, add "min-width" to label
189
  // Let's say the truth, a fixed width is more beautiful than a variable width
190
  if( settings.minimum_width !== false )
230
  window.console.log( "jQuery-LABELAUTY: " + message );
231
  };
232
 
233
+ function create( input_id, aria_label, selected, type, messages_object, label )
234
+ {
235
  var block;
236
  var unchecked_message;
237
  var checked_message;
238
+ var aria = "";
239
+
240
  if( messages_object == null )
241
  unchecked_message = checked_message = "";
242
  else
249
  else
250
  checked_message = messages_object[1];
251
  }
252
+
253
+ if(aria_label == null)
254
+ aria = "";
255
+ else
256
+ aria = 'tabindex="0" role="' + type + '" aria-checked="' + selected + '" aria-label="' + aria_label + '"';
257
+
258
  if( label == true )
259
  {
260
+ block = '<label for="' + input_id + '" ' + aria + '>' +
261
  '<span class="labelauty-unchecked-image"></span>' +
262
  '<span class="labelauty-unchecked">' + unchecked_message + '</span>' +
263
  '<span class="labelauty-checked-image"></span>' +
266
  }
267
  else
268
  {
269
+ block = '<label for="' + input_id + '" ' + aria + '>' +
270
  '<span class="labelauty-unchecked-image"></span>' +
271
  '<span class="labelauty-checked-image"></span>' +
272
  '</label>';
273
  }
274
+
275
  return block;
276
  };
277
 
278
+ }( jQuery ));
includes/updraft-admin-ui.js CHANGED
@@ -2389,7 +2389,7 @@ jQuery(document).ready(function($){
2389
  },
2390
  teardown: function(namespaces)
2391
  {
2392
- $(this).unbind("touchstart click.triple", data, tripleHandler);
2393
  }
2394
  };
2395
  })(jQuery);
2389
  },
2390
  teardown: function(namespaces)
2391
  {
2392
+ $(this).unbind("touchstart click.triple", tripleHandler);
2393
  }
2394
  };
2395
  })(jQuery);
languages/updraftplus-ar.mo CHANGED
Binary file
languages/updraftplus-ar.po CHANGED
@@ -1,5948 +0,0 @@
1
- # Translation of UpdraftPlus in Arabic
2
- # This file is distributed under the same license as the UpdraftPlus package.
3
- msgid ""
4
- msgstr ""
5
- "PO-Revision-Date: 2015-10-27 10:37:08+0000\n"
6
- "MIME-Version: 1.0\n"
7
- "Content-Type: text/plain; charset=UTF-8\n"
8
- "Content-Transfer-Encoding: 8bit\n"
9
- "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
10
- "X-Generator: GlotPress/2.0.1\n"
11
- "Project-Id-Version: UpdraftPlus\n"
12
-
13
- #: admin.php:2162
14
- msgid "FAQs"
15
- msgstr ""
16
-
17
- #: udaddons/plugin-updates/github-checker.php:120
18
- msgid "There is no changelog available."
19
- msgstr ""
20
-
21
- #: udaddons/plugin-updates/plugin-update-checker.php:648
22
- msgid "Check for updates"
23
- msgstr ""
24
-
25
- #: udaddons/plugin-updates/plugin-update-checker.php:692
26
- msgid "This plugin is up to date."
27
- msgstr ""
28
-
29
- #: udaddons/plugin-updates/plugin-update-checker.php:694
30
- msgid "A new version of this plugin is available."
31
- msgstr ""
32
-
33
- #: udaddons/plugin-updates/plugin-update-checker.php:696
34
- msgid "Unknown update checker status \"%s\""
35
- msgstr ""
36
-
37
- #: backup.php:1973
38
- msgid "%s: unreadable file - could not be backed up (check the file permissions and ownership)"
39
- msgstr ""
40
-
41
- #: backup.php:1987
42
- msgid "Failed to open directory (check the file permissions and ownership): %s"
43
- msgstr ""
44
-
45
- #: central/bootstrap.php:419
46
- msgid "Public key was sent to:"
47
- msgstr ""
48
-
49
- #: central/bootstrap.php:424
50
- msgid "Key size: %d bits"
51
- msgstr ""
52
-
53
- #: central/bootstrap.php:439
54
- msgid "Dashboard at"
55
- msgstr ""
56
-
57
- #: central/bootstrap.php:439
58
- msgid "Use the alternative method for making a connection with the dashboard."
59
- msgstr ""
60
-
61
- #: central/bootstrap.php:439
62
- msgid "More information..."
63
- msgstr ""
64
-
65
- #: central/bootstrap.php:439
66
- msgid "This is useful if the dashboard webserver cannot be contacted with incoming traffic by this website (for example, this is the case if this website is hosted on the public Internet, but the UpdraftCentral dashboard is on localhost, or on an Intranet, or if this website has an outgoing firewall), or if the dashboard website does not have a SSL certificate."
67
- msgstr ""
68
-
69
- #: addons/migrator.php:2158
70
- msgid "Create a key: give this key a unique name (e.g. indicate the site it is for), then press \"Create Key\":"
71
- msgstr ""
72
-
73
- #: addons/migrator.php:2159
74
- msgid "Enter your chosen name"
75
- msgstr ""
76
-
77
- #: addons/migrator.php:2161 central/bootstrap.php:441
78
- msgid "Encryption key size:"
79
- msgstr ""
80
-
81
- #: addons/migrator.php:2163 addons/migrator.php:2164 addons/migrator.php:2166
82
- #: central/bootstrap.php:442 central/bootstrap.php:443
83
- #: central/bootstrap.php:445
84
- msgid "%s bits"
85
- msgstr ""
86
-
87
- #: addons/migrator.php:2163 central/bootstrap.php:442
88
- msgid "easy to break, fastest"
89
- msgstr ""
90
-
91
- #: addons/migrator.php:2164 central/bootstrap.php:443
92
- msgid "faster (possibility for slow PHP installs)"
93
- msgstr ""
94
-
95
- #: addons/migrator.php:2165 central/bootstrap.php:444
96
- msgid "%s bytes"
97
- msgstr ""
98
-
99
- #: addons/migrator.php:2165 central/bootstrap.php:444
100
- msgid "recommended"
101
- msgstr ""
102
-
103
- #: addons/migrator.php:2166 central/bootstrap.php:445
104
- msgid "slower, strongest"
105
- msgstr ""
106
-
107
- #: addons/migrator.php:2169
108
- msgid "Create key"
109
- msgstr ""
110
-
111
- #: central/bootstrap.php:439
112
- msgid "i.e. you have an account there"
113
- msgstr ""
114
-
115
- #: central/bootstrap.php:439
116
- msgid "Other (please specify - i.e. the site where you have installed an UpdraftCentral dashboard)"
117
- msgstr ""
118
-
119
- #: class-updraftplus.php:1240
120
- msgid "Size: %s MB"
121
- msgstr ""
122
-
123
- #: methods/email.php:28
124
- msgid "This backup archive is %s MB in size - the attempt to send this via email is likely to fail (few email servers allow attachments of this size). If so, you should switch to using a different remote storage method."
125
- msgstr ""
126
-
127
- #: methods/email.php:77
128
- msgid "Be aware that mail servers tend to have size limits; typically around %s MB; backups larger than any limits will likely not arrive."
129
- msgstr ""
130
-
131
- #: methods/ftp.php:355
132
- msgid "login"
133
- msgstr ""
134
-
135
- #: methods/ftp.php:383
136
- msgid "This is sometimes caused by a firewall - try turning off SSL in the expert settings, and testing again."
137
- msgstr ""
138
-
139
- #: methods/googledrive.php:417
140
- msgid "Upload expected to fail: the %s limit for any single file is %s, whereas this file is %s GB (%d bytes)"
141
- msgstr ""
142
-
143
- #: admin.php:2453
144
- msgid "Now"
145
- msgstr ""
146
-
147
- #: admin.php:2604
148
- msgid "Free 1GB for UpdraftPlus Vault"
149
- msgstr ""
150
-
151
- #: admin.php:3959
152
- msgid "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)."
153
- msgstr ""
154
-
155
- #: class-updraftplus.php:3529 restorer.php:926
156
- msgid "You should enable %s to make any pretty permalinks (e.g. %s) work"
157
- msgstr ""
158
-
159
- #: admin.php:3770
160
- msgid "(tap on an icon to select or unselect)"
161
- msgstr ""
162
-
163
- #: backup.php:833 class-updraftplus.php:2411
164
- msgid "The backup was aborted by the user"
165
- msgstr ""
166
-
167
- #: central/bootstrap.php:50
168
- msgid "UpdraftCentral Connection"
169
- msgstr ""
170
-
171
- #: central/bootstrap.php:53
172
- msgid "An UpdraftCentral connection has been made successfully."
173
- msgstr ""
174
-
175
- #: central/bootstrap.php:55
176
- msgid "A new UpdraftCentral connection has not been made."
177
- msgstr ""
178
-
179
- #: central/bootstrap.php:58
180
- msgid "The key referred to was unknown."
181
- msgstr ""
182
-
183
- #: central/bootstrap.php:64
184
- msgid "You are not logged into this WordPress site in your web browser."
185
- msgstr ""
186
-
187
- #: central/bootstrap.php:64
188
- msgid "You must visit this URL in the same browser and login session as you created the key in."
189
- msgstr ""
190
-
191
- #: central/bootstrap.php:71
192
- msgid "You must visit this link in the same browser and login session as you created the key in."
193
- msgstr ""
194
-
195
- #: central/bootstrap.php:75
196
- msgid "This connection appears to already have been made."
197
- msgstr ""
198
-
199
- #: central/bootstrap.php:83
200
- msgid "Close..."
201
- msgstr ""
202
-
203
- #: central/bootstrap.php:196
204
- msgid "An invalid URL was entered"
205
- msgstr ""
206
-
207
- #: central/bootstrap.php:313 central/bootstrap.php:324
208
- msgid "A key was created, but the attempt to register it with %s was unsuccessful - please try again later."
209
- msgstr ""
210
-
211
- #: central/bootstrap.php:381
212
- msgid "Key description"
213
- msgstr ""
214
-
215
- #: central/bootstrap.php:381
216
- msgid "Details"
217
- msgstr ""
218
-
219
- #: central/bootstrap.php:387
220
- msgid "No keys have yet been created."
221
- msgstr ""
222
-
223
- #: central/bootstrap.php:419
224
- msgid "Access this site as user:"
225
- msgstr ""
226
-
227
- #: central/bootstrap.php:422
228
- msgid "Created:"
229
- msgstr ""
230
-
231
- #: central/bootstrap.php:429
232
- msgid "Delete..."
233
- msgstr ""
234
-
235
- #: central/bootstrap.php:435
236
- msgid "Create new key"
237
- msgstr ""
238
-
239
- #: central/bootstrap.php:437
240
- msgid "Description"
241
- msgstr ""
242
-
243
- #: central/bootstrap.php:437
244
- msgid "Enter any description"
245
- msgstr ""
246
-
247
- #: central/bootstrap.php:439
248
- msgid "URL of mothership"
249
- msgstr ""
250
-
251
- #: central/bootstrap.php:452
252
- msgid "View recent UpdraftCentral log events"
253
- msgstr ""
254
-
255
- #: central/bootstrap.php:452
256
- msgid "fetch..."
257
- msgstr ""
258
-
259
- #: central/bootstrap.php:463
260
- msgid "UpdraftCentral (Remote Control)"
261
- msgstr ""
262
-
263
- #: class-updraftplus.php:356 class-updraftplus.php:401
264
- msgid "The given file was not found, or could not be read."
265
- msgstr ""
266
-
267
- #: methods/updraftvault.php:214
268
- msgid "No Vault connection was found for this site (has it moved?); please disconnect and re-connect."
269
- msgstr ""
270
-
271
- #: methods/updraftvault.php:269 methods/updraftvault.php:275
272
- #: methods/updraftvault.php:281
273
- msgid "or (annual discount)"
274
- msgstr ""
275
-
276
- #: methods/updraftvault.php:270 methods/updraftvault.php:276
277
- #: methods/updraftvault.php:282
278
- msgid "%s per year"
279
- msgstr ""
280
-
281
- #: addons/copycom.php:60 addons/copycom.php:526
282
- msgid "Barracuda are closing down Copy.Com on May 1st, 2016. See:"
283
- msgstr ""
284
-
285
- #: addons/s3-enhanced.php:305
286
- msgid "Asia Pacific (Seoul)"
287
- msgstr ""
288
-
289
- #: admin.php:477
290
- msgid "Fetching..."
291
- msgstr ""
292
-
293
- #: admin.php:485
294
- msgid "Error: the server sent us a response which we did not understand."
295
- msgstr ""
296
-
297
- #: admin.php:521
298
- msgid "Saving..."
299
- msgstr ""
300
-
301
- #: admin.php:538
302
- msgid "Please enter a valid URL"
303
- msgstr ""
304
-
305
- #: admin.php:539
306
- msgid "We requested to delete the file, but could not understand the server's response"
307
- msgstr ""
308
-
309
- #: admin.php:545
310
- msgid "You should save your changes to ensure that they are used for making your backup."
311
- msgstr ""
312
-
313
- #: admin.php:2599
314
- msgid "Microsoft OneDrive, Microsoft Azure, Google Cloud Storage"
315
- msgstr ""
316
-
317
- #: admin.php:2863
318
- msgid "calculate"
319
- msgstr ""
320
-
321
- #: admin.php:2934
322
- msgid "this backup set"
323
- msgstr ""