UpdraftPlus WordPress Backup Plugin - Version 1.13.5

Version Description

  • 08/Aug/2017 =

  • TWEAK: Manage phpseclib through composer

  • TWEAK: Do less logging to database when resuming and noticing already-processed tables (saves resources)

  • TWEAK: Returns comment status when updating comments from UpdraftCentral

  • TWEAK: Update plugin-updates-checker library to current (4.2), and manage via composer, replacing bundled copy in the build source

  • TWEAK: Replace uses of create_function(), which is deprecated on PHP 7.2

  • TWEAK: Replace deprecated constructors (PHP 7+) in webdav module

  • TWEAK: Documentation showing plugin developers how easy it is to add in-page backups to their plugin: https://updraftplus.com/add-take-backup-functionality-plugin/

  • TWEAK: Make the UpdraftCentral updates checking able to cope with a wider range of third-party schemes

  • TWEAK: General code tidy-up, making older code conform to our current standards

  • TWEAK: Minor version updates of some bundled libraries

  • TWEAK: Produce and use minified resources (CSS/JS) where available

  • TWEAK: Update class-udrpc to latest (1.4.14) which removes a conflict with other code that may interact with CORS OPTIONS requests

  • TWEAK: Escape log lines when sending for display (theoretically an XSS security issue, but to achieve a successful attack, someone would have to first get something malicious into the log file, which is difficult as there are not many places where foreign input can end up in the log file - e.g. hack into Dropbox and cause Dropbox to send you back malicious HTML in an error message - and then be able to persuade you to both take a backup triggering the problem and then view the log file in your WP dashboard)

  • TWEAK: Update Google Cloud bucket locations

Download this release

Release Info

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

Code changes from version 1.13.4 to 1.13.5

Files changed (41) hide show
  1. admin.php +38 -21
  2. backup.php +39 -4
  3. central/bootstrap.php +58 -61
  4. central/classes/class-automatic-upgrader-skin.php +3 -1
  5. central/commands.php +9 -10
  6. central/listener.php +24 -14
  7. central/modules/comments.php +285 -231
  8. central/modules/core.php +75 -65
  9. central/modules/updates.php +234 -65
  10. central/modules/updraftvault.php +0 -14
  11. central/modules/users.php +141 -134
  12. class-updraftplus.php +43 -9
  13. clean-composer.sh +0 -32
  14. composer.json +0 -10
  15. composer.lock +0 -373
  16. css/admin.css +720 -671
  17. css/admin.min.css +2 -0
  18. css/admin.min.css.map +1 -0
  19. css/updraftplus-notices.css +14 -12
  20. css/updraftplus-notices.min.css +2 -0
  21. css/updraftplus-notices.min.css.map +1 -0
  22. example-decrypt.php +1 -1
  23. includes/Dropbox/OAuth/Storage/Encrypter.php +1 -1
  24. includes/Dropbox2/OAuth/Storage/Encrypter.php +1 -1
  25. includes/class-udrpc.php +192 -77
  26. includes/jquery-ui.custom.min.css +2 -0
  27. includes/jquery-ui.custom.min.css.map +1 -0
  28. includes/jquery.blockUI.min.js +1 -0
  29. includes/jquery.serializeJSON/LICENSE.txt +0 -21
  30. includes/jstree/jstree.js +188 -70
  31. includes/jstree/jstree.min.js +6 -6
  32. includes/jstree/themes/default-dark/style.css +6 -0
  33. includes/jstree/themes/default-dark/style.min.css +1 -1
  34. includes/jstree/themes/default/style.css +6 -0
  35. includes/jstree/themes/default/style.min.css +1 -1
  36. includes/labelauty/jquery-labelauty.min.css +2 -0
  37. includes/labelauty/jquery-labelauty.min.css.map +1 -0
  38. includes/labelauty/jquery-labelauty.min.js +1 -0
  39. includes/updraft-admin.min.js +3 -0
  40. includes/updraftplus-notices.php +20 -29
  41. languages/updraftplus-af.po +1318 -1348
admin.php CHANGED
@@ -570,17 +570,19 @@ class UpdraftPlus_Admin {
570
  private function ensure_sufficient_jquery_and_enqueue() {
571
  global $updraftplus, $wp_version;
572
 
573
- $enqueue_version = @constant('WP_DEBUG') ? $updraftplus->version.'-'.time() : $updraftplus->version;
 
574
 
575
  if (version_compare($wp_version, '3.3', '<')) {
576
  // Require a newer jQuery (3.2.1 has 1.6.1, so we go for something not too much newer). We use .on() in a way that is incompatible with < 1.7
577
  wp_deregister_script('jquery');
578
- wp_register_script('jquery', 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', false, '1.7.2', false);
 
579
  wp_enqueue_script('jquery');
580
  // No plupload until 3.3
581
- wp_enqueue_script('updraftplus-admin', UPDRAFTPLUS_URL.'/includes/updraft-admin.js', array('jquery', 'jquery-ui-dialog'), $enqueue_version, true);
582
  } else {
583
- wp_enqueue_script('updraftplus-admin', UPDRAFTPLUS_URL.'/includes/updraft-admin.js', array('jquery', 'jquery-ui-dialog', 'plupload-all'), $enqueue_version);
584
  }
585
 
586
  }
@@ -589,24 +591,26 @@ class UpdraftPlus_Admin {
589
  public function admin_enqueue_scripts() {
590
 
591
  global $updraftplus, $wp_locale;
 
 
 
592
 
593
  // Defeat other plugins/themes which dump their jQuery UI CSS onto our settings page
594
  wp_deregister_style('jquery-ui');
595
- wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui.custom.css', array(), '1.11.4');
596
-
597
- $our_version = @constant('SCRIPT_DEBUG') ? $updraftplus->version.'.'.time() : $updraftplus->version;
598
 
599
- wp_enqueue_style('updraft-admin-css', UPDRAFTPLUS_URL.'/css/admin.css', array(), $our_version);
600
  // add_filter('style_loader_tag', array($this, 'style_loader_tag'), 10, 2);
601
 
602
  $this->ensure_sufficient_jquery_and_enqueue();
603
-
604
- wp_enqueue_script('jquery-blockui', UPDRAFTPLUS_URL.'/includes/jquery.blockUI.js', array('jquery'), '2.70.0');
605
 
606
- wp_enqueue_script('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.js', array('jquery'), '20160622-ud');
607
- wp_enqueue_style('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.css', array(), '20150925');
608
-
609
- wp_enqueue_script('jquery.serializeJSON', UPDRAFTPLUS_URL.'/includes/jquery.serializeJSON/jquery.serializejson.min.js', array('jquery'), '2.8.1');
610
 
611
  $this->enqueue_jstree();
612
 
@@ -748,7 +752,7 @@ class UpdraftPlus_Admin {
748
  'updraftplus_version' => $updraftplus->version
749
  ) );
750
  }
751
-
752
  // Despite the name, this fires irrespective of what capabilities the user has (even none - so be careful)
753
  public function core_upgrade_preamble() {
754
  // They need to be able to perform backups, and to perform updates
@@ -1692,7 +1696,16 @@ class UpdraftPlus_Admin {
1692
  do_action($event, apply_filters('updraft_backupnow_options', $options, $request));
1693
  }
1694
 
1695
- public function fetch_log($backup_nonce, $log_pointer = 0) {
 
 
 
 
 
 
 
 
 
1696
  global $updraftplus;
1697
 
1698
  if (empty($backup_nonce)) {
@@ -1736,6 +1749,8 @@ class UpdraftPlus_Admin {
1736
  $log_content .= __('The log file could not be read.', 'updraftplus');
1737
  }
1738
 
 
 
1739
  $ret_array = array(
1740
  'log' => $log_content,
1741
  'nonce' => $nonce,
@@ -4089,7 +4104,7 @@ ENDHERE;
4089
  }
4090
  }
4091
  } else {
4092
- $return_array = array('saved' => false, 'error_message' => sprintf(__('UpdraftPlus seems to have been updated to version (%s) different to the version running when this settings page was loaded. Please reload the settings page before trying to save settings.', 'updraftplus'), $updraftplus->version));
4093
  }
4094
 
4095
  // Checking for various possible messages
@@ -4120,11 +4135,11 @@ ENDHERE;
4120
 
4121
  do_action('all_admin_notices');
4122
 
4123
- if (!$really_is_writable){ //Check if writable
4124
  $this->show_admin_warning_unwritable();
4125
  }
4126
 
4127
- if ($return_array['saved']){ //
4128
  $this->show_admin_warning(__('Your settings have been saved.', 'updraftplus'), 'updated fade');
4129
  } else {
4130
  if (isset($return_array['error_message'])) {
@@ -4366,8 +4381,10 @@ ENDHERE;
4366
  if ($already_enqueued) return;
4367
 
4368
  $already_enqueued = true;
 
 
4369
  // Include jstree components
4370
- wp_enqueue_script('jstree', UPDRAFTPLUS_URL.'/includes/jstree/jstree.min.js', array('jquery'), '3.3');
4371
- wp_enqueue_style('jstree', UPDRAFTPLUS_URL.'/includes/jstree/themes/default/style.min.css', array(), '3.3');
4372
  }
4373
  }
570
  private function ensure_sufficient_jquery_and_enqueue() {
571
  global $updraftplus, $wp_version;
572
 
573
+ $enqueue_version = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? $updraftplus->version.'.'.time() : $updraftplus->version;
574
+ $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
575
 
576
  if (version_compare($wp_version, '3.3', '<')) {
577
  // Require a newer jQuery (3.2.1 has 1.6.1, so we go for something not too much newer). We use .on() in a way that is incompatible with < 1.7
578
  wp_deregister_script('jquery');
579
+ $jquery_enqueue_version = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '1.7.2'.'.'.time() : '1.7.2';
580
+ wp_register_script('jquery', 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery'.$min_or_not.'.js', false, $jquery_enqueue_version, false);
581
  wp_enqueue_script('jquery');
582
  // No plupload until 3.3
583
+ wp_enqueue_script('updraftplus-admin', UPDRAFTPLUS_URL.'/includes/updraft-admin'.$min_or_not.'.js', array('jquery', 'jquery-ui-dialog'), $enqueue_version, true);
584
  } else {
585
+ wp_enqueue_script('updraftplus-admin', UPDRAFTPLUS_URL.'/includes/updraft-admin'.$min_or_not.'.js', array('jquery', 'jquery-ui-dialog', 'plupload-all'), $enqueue_version);
586
  }
587
 
588
  }
591
  public function admin_enqueue_scripts() {
592
 
593
  global $updraftplus, $wp_locale;
594
+
595
+ $enqueue_version = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? $updraftplus->version.'.'.time() : $updraftplus->version;
596
+ $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
597
 
598
  // Defeat other plugins/themes which dump their jQuery UI CSS onto our settings page
599
  wp_deregister_style('jquery-ui');
600
+ $jquery_ui_css_enqueue_version = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '1.11.4'.'.'.time() : '1.11.4';
601
+ wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui.custom'.$min_or_not.'.css', array(), $jquery_ui_css_enqueue_version);
 
602
 
603
+ wp_enqueue_style('updraft-admin-css', UPDRAFTPLUS_URL.'/css/admin'.$min_or_not.'.css', array(), $enqueue_version);
604
  // add_filter('style_loader_tag', array($this, 'style_loader_tag'), 10, 2);
605
 
606
  $this->ensure_sufficient_jquery_and_enqueue();
607
+ $jquery_blockui_enqueue_version = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '2.70.0'.'.'.time() : '2.70.0';
608
+ wp_enqueue_script('jquery-blockui', UPDRAFTPLUS_URL.'/includes/jquery.blockUI'.$min_or_not.'.js', array('jquery'), $jquery_blockui_enqueue_version);
609
 
610
+ wp_enqueue_script('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty'.$min_or_not.'.js', array('jquery'), $enqueue_version);
611
+ wp_enqueue_style('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty'.$min_or_not.'.css', array(), $enqueue_version);
612
+ $serialize_js_enqueue_version = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '2.8.1'.'.'.time() : '2.8.1';
613
+ wp_enqueue_script('jquery.serializeJSON', UPDRAFTPLUS_URL.'/includes/jquery.serializeJSON/jquery.serializejson'.$min_or_not.'.js', array('jquery'), $serialize_js_enqueue_version);
614
 
615
  $this->enqueue_jstree();
616
 
752
  'updraftplus_version' => $updraftplus->version
753
  ) );
754
  }
755
+
756
  // Despite the name, this fires irrespective of what capabilities the user has (even none - so be careful)
757
  public function core_upgrade_preamble() {
758
  // They need to be able to perform backups, and to perform updates
1696
  do_action($event, apply_filters('updraft_backupnow_options', $options, $request));
1697
  }
1698
 
1699
+ /**
1700
+ * Get the contents of a log file
1701
+ *
1702
+ * @param String $backup_nonce - the backup id; or empty, for the most recently modified
1703
+ * @param Integer $log_pointer - the byte count to fetch from
1704
+ * @param String $output_format - the format to return in; allowed as 'html' (which will escape HTML entities in what is returned) and 'raw'
1705
+ *
1706
+ * @return String
1707
+ */
1708
+ public function fetch_log($backup_nonce = '', $log_pointer = 0, $output_format = 'html') {
1709
  global $updraftplus;
1710
 
1711
  if (empty($backup_nonce)) {
1749
  $log_content .= __('The log file could not be read.', 'updraftplus');
1750
  }
1751
 
1752
+ if ('html' == $output_format) $log_content = htmlspecialchars($log_content);
1753
+
1754
  $ret_array = array(
1755
  'log' => $log_content,
1756
  'nonce' => $nonce,
4104
  }
4105
  }
4106
  } else {
4107
+ $return_array = array('saved' => false, 'error_message' => sprintf(__('UpdraftPlus seems to have been updated to version (%s), which is different to the version running when this settings page was loaded. Please reload the settings page before trying to save settings.', 'updraftplus'), $updraftplus->version));
4108
  }
4109
 
4110
  // Checking for various possible messages
4135
 
4136
  do_action('all_admin_notices');
4137
 
4138
+ if (!$really_is_writable) { //Check if writable
4139
  $this->show_admin_warning_unwritable();
4140
  }
4141
 
4142
+ if ($return_array['saved']) { //
4143
  $this->show_admin_warning(__('Your settings have been saved.', 'updraftplus'), 'updated fade');
4144
  } else {
4145
  if (isset($return_array['error_message'])) {
4381
  if ($already_enqueued) return;
4382
 
4383
  $already_enqueued = true;
4384
+ $jstree_enqueue_version = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '3.3'.'.'.time() : '3.3';
4385
+ $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
4386
  // Include jstree components
4387
+ wp_enqueue_script('jstree', UPDRAFTPLUS_URL.'/includes/jstree/jstree'.$min_or_not.'.js', array('jquery'), $jstree_enqueue_version);
4388
+ wp_enqueue_style('jstree', UPDRAFTPLUS_URL.'/includes/jstree/themes/default/style'.$min_or_not.'.css', array(), $jstree_enqueue_version);
4389
  }
4390
  }
backup.php CHANGED
@@ -1408,9 +1408,9 @@ class UpdraftPlus_Backup {
1408
 
1409
  if (empty($all_tables) && !empty($this->wpdb_obj->last_error)) {
1410
  $all_tables = $this->wpdb_obj->get_results("SHOW TABLES", ARRAY_N);
1411
- $all_tables = array_map(create_function('$a', 'return array("name" => $a[0], "type" => "BASE TABLE");'), $all_tables);
1412
  } else {
1413
- $all_tables = array_map(create_function('$a', 'return array("name" => $a[0], "type" => $a[1]);'), $all_tables);
1414
  }
1415
 
1416
  # If this is not the WP database, then we do not consider it a fatal error if there are no tables
@@ -1424,7 +1424,7 @@ class UpdraftPlus_Backup {
1424
  // Put the options table first
1425
  usort($all_tables, array($this, 'backup_db_sorttables'));
1426
 
1427
- $all_table_names = array_map(create_function('$a', 'return $a["name"];'), $all_tables);
1428
 
1429
  if (!$updraftplus->really_is_writable($this->updraft_dir)) {
1430
  $updraftplus->log("The backup directory (".$this->updraft_dir.") could not be written to (could be account/disk space full, or wrong permissions).");
@@ -1462,7 +1462,9 @@ class UpdraftPlus_Backup {
1462
  if ('wp' == $whichdb && (strtolower($this->table_prefix_raw.'options') == strtolower($table) || ($is_multisite && (strtolower($this->table_prefix_raw.'sitemeta') == strtolower($table) || strtolower($this->table_prefix_raw.'1_options') == strtolower($table))))) $found_options_table = true;
1463
 
1464
  if (file_exists($this->updraft_dir.'/'.$table_file_prefix.'.gz')) {
1465
- $updraftplus->log("Table $table: corresponding file already exists; moving on");
 
 
1466
  $stitch_files[] = $table_file_prefix;
1467
  } else {
1468
  # === is needed, otherwise 'false' matches (i.e. prefix does not match)
@@ -3081,6 +3083,39 @@ class UpdraftPlus_Backup {
3081
  $updraftplus->jobdata_set('job_file_entities', $this->job_file_entities);
3082
  }
3083
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3084
  }
3085
 
3086
  class UpdraftPlus_WPDB_OtherDB extends wpdb {
1408
 
1409
  if (empty($all_tables) && !empty($this->wpdb_obj->last_error)) {
1410
  $all_tables = $this->wpdb_obj->get_results("SHOW TABLES", ARRAY_N);
1411
+ $all_tables = array_map(array($this, 'cb_get_name_base_type'), $all_tables);
1412
  } else {
1413
+ $all_tables = array_map(array($this, 'cb_get_name_type'), $all_tables);
1414
  }
1415
 
1416
  # If this is not the WP database, then we do not consider it a fatal error if there are no tables
1424
  // Put the options table first
1425
  usort($all_tables, array($this, 'backup_db_sorttables'));
1426
 
1427
+ $all_table_names = array_map(array($this, 'cb_get_name'), $all_tables);
1428
 
1429
  if (!$updraftplus->really_is_writable($this->updraft_dir)) {
1430
  $updraftplus->log("The backup directory (".$this->updraft_dir.") could not be written to (could be account/disk space full, or wrong permissions).");
1462
  if ('wp' == $whichdb && (strtolower($this->table_prefix_raw.'options') == strtolower($table) || ($is_multisite && (strtolower($this->table_prefix_raw.'sitemeta') == strtolower($table) || strtolower($this->table_prefix_raw.'1_options') == strtolower($table))))) $found_options_table = true;
1463
 
1464
  if (file_exists($this->updraft_dir.'/'.$table_file_prefix.'.gz')) {
1465
+ $stitched = count($stitch_files);
1466
+ $skip_dblog = (($stitched > 10 && 0 != $stitched % 20) || ($stitched > 100 && 0 != $stitched % 100));
1467
+ $updraftplus->log("Table $table: corresponding file already exists; moving on", 'notice', false, $skip_dblog);
1468
  $stitch_files[] = $table_file_prefix;
1469
  } else {
1470
  # === is needed, otherwise 'false' matches (i.e. prefix does not match)
3083
  $updraftplus->jobdata_set('job_file_entities', $this->job_file_entities);
3084
  }
3085
 
3086
+ /**
3087
+ * Returns the member of the array with key (int)0, as a new array. This function is used as a callback for array_map().
3088
+ *
3089
+ * @param Array $a - the array
3090
+ *
3091
+ * @return Array - with keys 'name' and 'type'
3092
+ */
3093
+ private function cb_get_name_base_type($a) {
3094
+ return array('name' => $a[0], 'type' => 'BASE TABLE');
3095
+ }
3096
+
3097
+ /**
3098
+ * Returns the members of the array with keys (int)0 and (int)1, as part of a new array.
3099
+ *
3100
+ * @param Array $a - the array
3101
+ *
3102
+ * @return Array - keys are 'name' and 'type'
3103
+ */
3104
+ private function cb_get_name_type($a) {
3105
+ return array('name' => $a[0], 'type' => $a[1]);
3106
+ }
3107
+
3108
+ /**
3109
+ * Returns the member of the array with key (string)'name'. This function is used as a callback for array_map().
3110
+ *
3111
+ * @param Array $a - the array
3112
+ *
3113
+ * @return Mixed - the value with key (string)'name'
3114
+ */
3115
+ private function cb_get_name($a) {
3116
+ return $a['name'];
3117
+ }
3118
+
3119
  }
3120
 
3121
  class UpdraftPlus_WPDB_OtherDB extends wpdb {
central/bootstrap.php CHANGED
@@ -15,8 +15,8 @@ class UpdraftPlus_UpdraftCentral_Main {
15
  add_action('updraftplus_debugtools_dashboard', array($this, 'debugtools_dashboard'), 20);
16
  add_action('udrpc_log', array($this, 'udrpc_log'), 10, 3);
17
 
18
- add_action('wp_ajax_updraftcentral_receivepublickey', array($this, 'wp_ajax_updraftcentral_receivepublickey'));
19
- add_action('wp_ajax_nopriv_updraftcentral_receivepublickey', array($this, 'wp_ajax_updraftcentral_receivepublickey'));
20
 
21
  // The 'updraftplus' commands are registered in UpdraftPlus::plugins_loaded()
22
  $command_classes = apply_filters('updraftplus_remotecontrol_command_classes', array(
@@ -30,7 +30,7 @@ class UpdraftPlus_UpdraftCentral_Main {
30
  // Remote control keys
31
  // These are different from the remote send keys, which are set up in the Migrator add-on
32
  $our_keys = UpdraftPlus_Options::get_updraft_option('updraft_central_localkeys');
33
- if (is_array($our_keys) && !empty($our_keys)) {
34
  $remote_control = new UpdraftPlus_UpdraftCentral_Listener($our_keys, $command_classes);
35
  }
36
 
@@ -50,30 +50,23 @@ class UpdraftPlus_UpdraftCentral_Main {
50
  echo __('An UpdraftCentral connection has been made successfully.', 'updraftplus');
51
  } else {
52
  echo '<strong>'.__('A new UpdraftCentral connection has not been made.', 'updraftplus').'</strong><br>';
53
- switch($result['code']) {
54
  case 'unknown_key':
55
- echo __('The key referred to was unknown.', 'updraftplus');
56
- break;
57
- case 'not_logged_in';
58
-
59
- // $the_url = admin_url('admin-ajax.php').'?action=updraftcentral_receivepublickey&_wpnonce='.urlencode($_GET['_wpnonce']).'&updraft_key_index='.urlencode($_GET['updraft_key_index']).'&public_key='.urlencode($_GET['public_key']);
60
-
61
- echo __('You are not logged into this WordPress site in your web browser.', 'updraftplus').' '.__('You must visit this URL in the same browser and login session as you created the key in.', 'updraftplus');
62
-
63
- break;
64
- case 'nonce_failure';
65
-
66
- echo 'Security check. ';
67
-
68
- _e('You must visit this link in the same browser and login session as you created the key in.', 'updraftplus');
69
-
70
- break;
71
- case 'already_have';
72
- echo __('This connection appears to already have been made.', 'updraftplus');
73
- break;
74
  default:
75
- echo htmlspecialchars(print_r($result, true));
76
- break;
77
  }
78
  }
79
 
@@ -108,7 +101,13 @@ class UpdraftPlus_UpdraftCentral_Main {
108
  return array('responsetype' => 'ok', 'code' => 'ok');
109
  }
110
 
111
- // Action parameters, from udrpc: $message, $level, $this->key_name_indicator, $this->debug, $this
 
 
 
 
 
 
112
  public function udrpc_log($message, $level, $key_name_indicator) {
113
  $udrpc_log = get_site_option('updraftcentral_client_log');
114
  if (!is_array($udrpc_log)) $udrpc_log = array();
@@ -186,9 +185,9 @@ class UpdraftPlus_UpdraftCentral_Main {
186
  // Use the site URL - this means that if the site URL changes, communication ends; which is the case anyway
187
  $user = wp_get_current_user();
188
 
189
- $where_send = empty($params['where_send']) ? '' : (string)$params['where_send'];
190
 
191
- if ($where_send != '__updraftpluscom') {
192
  $purl = parse_url($where_send);
193
  if (empty($purl) || !array($purl) || empty($purl['scheme']) || empty($purl['host'])) return array('error' => __('An invalid URL was entered', 'updraftplus'));
194
  }
@@ -210,10 +209,10 @@ class UpdraftPlus_UpdraftCentral_Main {
210
  }
211
 
212
  if (!empty($params['key_description'])) {
213
- $extra_info['name'] = (string)$params['key_description'];
214
  }
215
 
216
- $key_size = (empty($params['key_size']) || !is_numeric($params['key_size']) || $params['key_size'] < 512) ? 2048 : (int)$params['key_size'];
217
 
218
  $extra_info['key_size'] = $key_size;
219
 
@@ -224,7 +223,6 @@ class UpdraftPlus_UpdraftCentral_Main {
224
  }
225
 
226
  return $created;
227
- die;
228
  }
229
 
230
  private function indicator_name_from_index($index) {
@@ -269,8 +267,7 @@ class UpdraftPlus_UpdraftCentral_Main {
269
 
270
  @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
271
 
272
- $key_size = (empty($extra_info['key_size']) || !is_numeric($extra_info['key_size']) || $extra_info['key_size'] < 512) ? 2048 : (int)$extra_info['key_size'];
273
- // unset($extra_info['key_size']);
274
 
275
  if (is_object($ud_rpc) && $ud_rpc->generate_new_keypair($key_size)) {
276
 
@@ -307,7 +304,7 @@ class UpdraftPlus_UpdraftCentral_Main {
307
  );
308
 
309
  if (is_wp_error($sent_key) || empty($sent_key)) {
310
- $err_msg = sprintf(__('A key was created, but the attempt to register it with %s was unsuccessful - please try again later.', 'updraftplus'), (string)$post_it_description);
311
  if (is_wp_error($sent_key)) $err_msg .= ' '.$sent_key->get_error_message().' ('.$sent_key->get_error_code().')';
312
  return array(
313
  'r' => $err_msg
@@ -318,7 +315,7 @@ class UpdraftPlus_UpdraftCentral_Main {
318
 
319
  if (!is_array($response) || !isset($response['key_id']) || !isset($response['key_public'])) {
320
  return array(
321
- 'r' => sprintf(__('A key was created, but the attempt to register it with %s was unsuccessful - please try again later.', 'updraftplus'), (string)$post_it_description),
322
  'raw' => wp_remote_retrieve_body($sent_key)
323
  );
324
  }
@@ -341,7 +338,7 @@ class UpdraftPlus_UpdraftCentral_Main {
341
 
342
 
343
  if (isset($extra_info['name'])) {
344
- $name = (string)$extra_info['name'];
345
  unset($extra_info['name']);
346
  } else {
347
  $name = 'UpdraftCentral Remote Control';
@@ -362,8 +359,8 @@ class UpdraftPlus_UpdraftCentral_Main {
362
  return array(
363
  'bundle' => $local_bundle,
364
  'r' => __('Key created successfully.', 'updraftplus').' '.__('You must copy and paste this key now - it cannot be shown again.', 'updraftplus'),
365
- // 'selector' => $this->get_remotesites_selector(array()),
366
- // 'ourkeys' => $this->list_our_keys($our_keys),
367
  );
368
  }
369
 
@@ -432,8 +429,8 @@ class UpdraftPlus_UpdraftCentral_Main {
432
  <table>
433
  <thead>
434
  <tr>
435
- <th style="text-align:left;"><?php _e('Key description', 'updraftplus') ?></th>
436
- <th style="text-align:left;"><?php _e('Details', 'updraftplus') ?></th>
437
  </tr>
438
  </thead>
439
  <tbody>
@@ -450,16 +447,17 @@ class UpdraftPlus_UpdraftCentral_Main {
450
  return ob_get_clean();
451
  }
452
 
453
- private function create_key_markup(){
454
- ob_start(); ?>
 
455
  <div class="create_key_container">
456
- <h4> <?php _e('Create new key', 'updraftplus') ?></h4>
457
  <table style="width: auto; table-layout:fixed;">
458
  <thead></thead>
459
  <tbody>
460
  <tr class="updraft_debugrow">
461
  <th style="width: 20%;">
462
- <?php _e('Description', 'updraftplus') ?>:
463
  </th>
464
  <td style="width:80%;">
465
  <input id="updraftcentral_keycreate_description" type="text" size="20" placeholder="<?php _e('Enter any description', 'updraftplus'); ?>" value="" >
@@ -467,26 +465,26 @@ class UpdraftPlus_UpdraftCentral_Main {
467
  </tr>
468
 
469
  <tr class="updraft_debugrow">
470
- <th style=""> <?php _e('Dashboard at', 'updraftplus') ?>:</th>
471
  <td style="width:80%;">
472
  <label>
473
  <input checked="checked" type="radio" name="updraftcentral_mothership" id="updraftcentral_mothership_updraftpluscom">
474
- UpdraftPlus.Com (<?php _e('i.e. you have an account there', 'updraftplus') ?>)
475
  </label>
476
  <br>
477
  <label>
478
  <input type="radio" name="updraftcentral_mothership" id="updraftcentral_mothership_other">
479
- <?php _e('Other (please specify - i.e. the site where you have installed an UpdraftCentral dashboard)', 'updraftplus') ?>:
480
  </label>
481
  <br>
482
- <input disabled="disabled" id="updraftcentral_keycreate_mothership" type="text" size="40" placeholder="<?php _e('URL of mothership', 'updraftplus') ?>" value="">
483
  <br>
484
  <div id="updraftcentral_keycreate_mothership_firewalled_container">
485
  <label>
486
  <input id="updraftcentral_keycreate_mothership_firewalled" type="checkbox">
487
- <?php _e('Use the alternative method for making a connection with the dashboard.', 'updraftplus') ?>
488
  <a href="#" id="updraftcentral_keycreate_altmethod_moreinfo_get">
489
- <?php _e('More information...', 'updraftplus') ?>
490
  </a>
491
  <p id="updraftcentral_keycreate_altmethod_moreinfo" style="display:none;">
492
  <?php _e('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.');?>
@@ -500,32 +498,32 @@ class UpdraftPlus_UpdraftCentral_Main {
500
  <td style="width:80%;">
501
  <?php _e('Encryption key size:', 'updraftplus'); ?>
502
  <select style="" id="updraftcentral_keycreate_keysize">
503
- <option value="512"><?php echo sprintf(__('%s bits', 'updraftplus').' - '.__('easy to break, fastest', 'updraftplus'), '512') ?></option>
504
- <option value="1024"><?php echo sprintf(__('%s bits', 'updraftplus').' - '.__('faster (possibility for slow PHP installs)', 'updraftplus'), '1024') ?></option>
505
- <option value="2048" selected="selected"><?php echo sprintf(__('%s bytes', 'updraftplus').' - '.__('recommended', 'updraftplus'), '2048') ?></option>
506
- <option value="4096"><?php echo sprintf(__('%s bits', 'updraftplus').' - '.__('slower, strongest', 'updraftplus'), '4096') ?></option>
507
  </select>
508
  </td>
509
  </tr>
510
  <tr class="updraft_debugrow">
511
  <th style=""></th>
512
  <td style="width:80%;">
513
- <button type="button" class="button button-primary" id="updraftcentral_keycreate_go"><?php _e('Create', 'updraftplus') ?></button>
514
  </td>
515
  </tr>
516
  </tbody>
517
  </table>
518
  </div>
519
- <?php
520
- return ob_get_clean();
521
- }
522
 
523
  private function create_log_markup(){
524
  ob_start();
525
  ?>
526
  <div id="updraftcentral_view_log_container">
527
- <h4><?php _e('View recent UpdraftCentral log events', 'updraftplus') ?> -
528
- <a href="#" id="updraftcentral_view_log"><?php _e('fetch...', 'updraftplus') ?></a>
529
  </h4>
530
  <pre id="updraftcentral_view_log_contents" style="padding: 0 4px;">
531
  </pre>
@@ -549,7 +547,6 @@ class UpdraftPlus_UpdraftCentral_Main {
549
  </div>
550
  <?php
551
  }
552
-
553
  }
554
 
555
  global $updraftplus_updraftcentral_main;
15
  add_action('updraftplus_debugtools_dashboard', array($this, 'debugtools_dashboard'), 20);
16
  add_action('udrpc_log', array($this, 'udrpc_log'), 10, 3);
17
 
18
+ add_action('wp_ajax_updraftcentral_receivepublickey', array($this, 'wp_ajax_updraftcentral_receivepublickey'));
19
+ add_action('wp_ajax_nopriv_updraftcentral_receivepublickey', array($this, 'wp_ajax_updraftcentral_receivepublickey'));
20
 
21
  // The 'updraftplus' commands are registered in UpdraftPlus::plugins_loaded()
22
  $command_classes = apply_filters('updraftplus_remotecontrol_command_classes', array(
30
  // Remote control keys
31
  // These are different from the remote send keys, which are set up in the Migrator add-on
32
  $our_keys = UpdraftPlus_Options::get_updraft_option('updraft_central_localkeys');
33
+ if (is_array($our_keys) && !empty($our_keys)) {
34
  $remote_control = new UpdraftPlus_UpdraftCentral_Listener($our_keys, $command_classes);
35
  }
36
 
50
  echo __('An UpdraftCentral connection has been made successfully.', 'updraftplus');
51
  } else {
52
  echo '<strong>'.__('A new UpdraftCentral connection has not been made.', 'updraftplus').'</strong><br>';
53
+ switch ($result['code']) {
54
  case 'unknown_key':
55
+ echo __('The key referred to was unknown.', 'updraftplus');
56
+ break;
57
+ case 'not_logged_in':
58
+ echo __('You are not logged into this WordPress site in your web browser.', 'updraftplus').' '.__('You must visit this URL in the same browser and login session as you created the key in.', 'updraftplus');
59
+ break;
60
+ case 'nonce_failure':
61
+ echo 'Security check. ';
62
+ _e('You must visit this link in the same browser and login session as you created the key in.', 'updraftplus');
63
+ break;
64
+ case 'already_have':
65
+ echo __('This connection appears to already have been made.', 'updraftplus');
66
+ break;
 
 
 
 
 
 
 
67
  default:
68
+ echo htmlspecialchars(print_r($result, true));
69
+ break;
70
  }
71
  }
72
 
101
  return array('responsetype' => 'ok', 'code' => 'ok');
102
  }
103
 
104
+ /**
105
+ * Action parameters, from udrpc: $message, $level, $this->key_name_indicator, $this->debug, $this
106
+ *
107
+ * @param string $message The log message
108
+ * @param string $level Log level
109
+ * @param string $key_name_indicator This indicates the key name
110
+ */
111
  public function udrpc_log($message, $level, $key_name_indicator) {
112
  $udrpc_log = get_site_option('updraftcentral_client_log');
113
  if (!is_array($udrpc_log)) $udrpc_log = array();
185
  // Use the site URL - this means that if the site URL changes, communication ends; which is the case anyway
186
  $user = wp_get_current_user();
187
 
188
+ $where_send = empty($params['where_send']) ? '' : (string) $params['where_send'];
189
 
190
+ if ('__updraftpluscom' != $where_send) {
191
  $purl = parse_url($where_send);
192
  if (empty($purl) || !array($purl) || empty($purl['scheme']) || empty($purl['host'])) return array('error' => __('An invalid URL was entered', 'updraftplus'));
193
  }
209
  }
210
 
211
  if (!empty($params['key_description'])) {
212
+ $extra_info['name'] = (string) $params['key_description'];
213
  }
214
 
215
+ $key_size = (empty($params['key_size']) || !is_numeric($params['key_size']) || $params['key_size'] < 512) ? 2048 : (int) $params['key_size'];
216
 
217
  $extra_info['key_size'] = $key_size;
218
 
223
  }
224
 
225
  return $created;
 
226
  }
227
 
228
  private function indicator_name_from_index($index) {
267
 
268
  @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
269
 
270
+ $key_size = (empty($extra_info['key_size']) || !is_numeric($extra_info['key_size']) || $extra_info['key_size'] < 512) ? 2048 : (int) $extra_info['key_size'];
 
271
 
272
  if (is_object($ud_rpc) && $ud_rpc->generate_new_keypair($key_size)) {
273
 
304
  );
305
 
306
  if (is_wp_error($sent_key) || empty($sent_key)) {
307
+ $err_msg = sprintf(__('A key was created, but the attempt to register it with %s was unsuccessful - please try again later.', 'updraftplus'), (string) $post_it_description);
308
  if (is_wp_error($sent_key)) $err_msg .= ' '.$sent_key->get_error_message().' ('.$sent_key->get_error_code().')';
309
  return array(
310
  'r' => $err_msg
315
 
316
  if (!is_array($response) || !isset($response['key_id']) || !isset($response['key_public'])) {
317
  return array(
318
+ 'r' => sprintf(__('A key was created, but the attempt to register it with %s was unsuccessful - please try again later.', 'updraftplus'), (string) $post_it_description),
319
  'raw' => wp_remote_retrieve_body($sent_key)
320
  );
321
  }
338
 
339
 
340
  if (isset($extra_info['name'])) {
341
+ $name = (string) $extra_info['name'];
342
  unset($extra_info['name']);
343
  } else {
344
  $name = 'UpdraftCentral Remote Control';
359
  return array(
360
  'bundle' => $local_bundle,
361
  'r' => __('Key created successfully.', 'updraftplus').' '.__('You must copy and paste this key now - it cannot be shown again.', 'updraftplus'),
362
+ // 'selector' => $this->get_remotesites_selector(array()),
363
+ // 'ourkeys' => $this->list_our_keys($our_keys),
364
  );
365
  }
366
 
429
  <table>
430
  <thead>
431
  <tr>
432
+ <th style="text-align:left;"><?php _e('Key description', 'updraftplus'); ?></th>
433
+ <th style="text-align:left;"><?php _e('Details', 'updraftplus'); ?></th>
434
  </tr>
435
  </thead>
436
  <tbody>
447
  return ob_get_clean();
448
  }
449
 
450
+ private function create_key_markup(){
451
+ ob_start();
452
+ ?>
453
  <div class="create_key_container">
454
+ <h4> <?php _e('Create new key', 'updraftplus'); ?></h4>
455
  <table style="width: auto; table-layout:fixed;">
456
  <thead></thead>
457
  <tbody>
458
  <tr class="updraft_debugrow">
459
  <th style="width: 20%;">
460
+ <?php _e('Description', 'updraftplus'); ?>:
461
  </th>
462
  <td style="width:80%;">
463
  <input id="updraftcentral_keycreate_description" type="text" size="20" placeholder="<?php _e('Enter any description', 'updraftplus'); ?>" value="" >
465
  </tr>
466
 
467
  <tr class="updraft_debugrow">
468
+ <th style=""> <?php _e('Dashboard at', 'updraftplus'); ?>:</th>
469
  <td style="width:80%;">
470
  <label>
471
  <input checked="checked" type="radio" name="updraftcentral_mothership" id="updraftcentral_mothership_updraftpluscom">
472
+ UpdraftPlus.Com (<?php _e('i.e. you have an account there', 'updraftplus'); ?>)
473
  </label>
474
  <br>
475
  <label>
476
  <input type="radio" name="updraftcentral_mothership" id="updraftcentral_mothership_other">
477
+ <?php _e('Other (please specify - i.e. the site where you have installed an UpdraftCentral dashboard)', 'updraftplus'); ?>:
478
  </label>
479
  <br>
480
+ <input disabled="disabled" id="updraftcentral_keycreate_mothership" type="text" size="40" placeholder="<?php _e('URL of mothership', 'updraftplus'); ?>" value="">
481
  <br>
482
  <div id="updraftcentral_keycreate_mothership_firewalled_container">
483
  <label>
484
  <input id="updraftcentral_keycreate_mothership_firewalled" type="checkbox">
485
+ <?php _e('Use the alternative method for making a connection with the dashboard.', 'updraftplus'); ?>
486
  <a href="#" id="updraftcentral_keycreate_altmethod_moreinfo_get">
487
+ <?php _e('More information...', 'updraftplus'); ?>
488
  </a>
489
  <p id="updraftcentral_keycreate_altmethod_moreinfo" style="display:none;">
490
  <?php _e('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.');?>
498
  <td style="width:80%;">
499
  <?php _e('Encryption key size:', 'updraftplus'); ?>
500
  <select style="" id="updraftcentral_keycreate_keysize">
501
+ <option value="512"><?php echo sprintf(__('%s bits', 'updraftplus').' - '.__('easy to break, fastest', 'updraftplus'), '512'); ?></option>
502
+ <option value="1024"><?php echo sprintf(__('%s bits', 'updraftplus').' - '.__('faster (possibility for slow PHP installs)', 'updraftplus'), '1024'); ?></option>
503
+ <option value="2048" selected="selected"><?php echo sprintf(__('%s bytes', 'updraftplus').' - '.__('recommended', 'updraftplus'), '2048'); ?></option>
504
+ <option value="4096"><?php echo sprintf(__('%s bits', 'updraftplus').' - '.__('slower, strongest', 'updraftplus'), '4096'); ?></option>
505
  </select>
506
  </td>
507
  </tr>
508
  <tr class="updraft_debugrow">
509
  <th style=""></th>
510
  <td style="width:80%;">
511
+ <button type="button" class="button button-primary" id="updraftcentral_keycreate_go"><?php _e('Create', 'updraftplus'); ?></button>
512
  </td>
513
  </tr>
514
  </tbody>
515
  </table>
516
  </div>
517
+ <?php
518
+ return ob_get_clean();
519
+ }
520
 
521
  private function create_log_markup(){
522
  ob_start();
523
  ?>
524
  <div id="updraftcentral_view_log_container">
525
+ <h4><?php _e('View recent UpdraftCentral log events', 'updraftplus'); ?> -
526
+ <a href="#" id="updraftcentral_view_log"><?php _e('fetch...', 'updraftplus'); ?></a>
527
  </h4>
528
  <pre id="updraftcentral_view_log_contents" style="padding: 0 4px;">
529
  </pre>
547
  </div>
548
  <?php
549
  }
 
550
  }
551
 
552
  global $updraftplus_updraftcentral_main;
central/classes/class-automatic-upgrader-skin.php CHANGED
@@ -1,4 +1,6 @@
1
  <?php
 
 
2
 
3
  // Extracted from 4.5.2/wordpress/wp-admin/includes/class-wp-upgrader-skins.php; with the bulk_*() methods added since they are not in the base class on all WP versions.
4
  // Needed only on WP < 3.7
@@ -99,7 +101,7 @@ class Automatic_Upgrader_Skin extends WP_Upgrader_Skin {
99
  $this->feedback( $output );
100
  }
101
 
102
- /**
103
  * @access public
104
  */
105
  public function bulk_header() {}
1
  <?php
2
+ // @codingStandardsIgnoreFile
3
+ if (!defined('ABSPATH')) die('No direct access.');
4
 
5
  // Extracted from 4.5.2/wordpress/wp-admin/includes/class-wp-upgrader-skins.php; with the bulk_*() methods added since they are not in the base class on all WP versions.
6
  // Needed only on WP < 3.7
101
  $this->feedback( $output );
102
  }
103
 
104
+ /**
105
  * @access public
106
  */
107
  public function bulk_header() {}
central/commands.php CHANGED
@@ -2,17 +2,16 @@
2
 
3
  if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
 
5
- /*
6
- - A container for all the RPC commands implemented. Commands map exactly onto method names (and hence this class should not implement anything else, beyond the constructor, and private methods)
7
- - Return format is array('response' => (string - a code), 'data' => (mixed));
8
-
9
- RPC commands are not allowed to begin with an underscore. So, any private methods can be prefixed with an underscore.
10
-
11
- */
12
-
13
  abstract class UpdraftCentral_Commands {
14
 
15
  protected $rc;
 
16
  protected $ud;
17
 
18
  public function __construct($rc) {
@@ -24,14 +23,14 @@ abstract class UpdraftCentral_Commands {
24
  final protected function _admin_include() {
25
  $files = func_get_args();
26
  foreach ($files as $file) {
27
- require_once(ABSPATH.'/wp-admin/includes/'.$file);
28
  }
29
  }
30
 
31
  final protected function _frontend_include() {
32
  $files = func_get_args();
33
  foreach ($files as $file) {
34
- require_once(ABSPATH.WPINC.'/'.$file);
35
  }
36
  }
37
 
2
 
3
  if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
 
5
+ /**
6
+ * - A container for all the RPC commands implemented. Commands map exactly onto method names (and hence this class should not implement anything else, beyond the constructor, and private methods)
7
+ * - Return format is array('response' => (string - a code), 'data' => (mixed));
8
+ *
9
+ * RPC commands are not allowed to begin with an underscore. So, any private methods can be prefixed with an underscore.
10
+ */
 
 
11
  abstract class UpdraftCentral_Commands {
12
 
13
  protected $rc;
14
+
15
  protected $ud;
16
 
17
  public function __construct($rc) {
23
  final protected function _admin_include() {
24
  $files = func_get_args();
25
  foreach ($files as $file) {
26
+ include_once(ABSPATH.'/wp-admin/includes/'.$file);
27
  }
28
  }
29
 
30
  final protected function _frontend_include() {
31
  $files = func_get_args();
32
  foreach ($files as $file) {
33
+ include_once(ABSPATH.WPINC.'/'.$file);
34
  }
35
  }
36
 
central/listener.php CHANGED
@@ -2,17 +2,25 @@
2
 
3
  if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
 
5
- // This class is the basic glue between the lower-level UpdraftPlus_Remote_Communications (UDRPC) class, and UpdraftPlus. It does not contain actual commands themselves; the class names to use for actual commands are passed in as a parameter to the constructor.
6
-
 
7
  class UpdraftPlus_UpdraftCentral_Listener {
8
 
9
  public $udrpc_version;
 
10
  private $ud = null;
 
11
  private $receivers = array();
 
12
  private $extra_info = array();
 
13
  private $php_events = array();
 
14
  private $commands = array();
 
15
  private $current_udrpc = null;
 
16
  private $command_classes;
17
 
18
  public function __construct($keys = array(), $command_classes = array()) {
@@ -53,13 +61,13 @@ class UpdraftPlus_UpdraftCentral_Listener {
53
 
54
  // If we ever need to expand beyond a single GET action, this can/should be generalised and put into the commands class
55
  if (!empty($_GET['udcentral_action']) && 'login' == $_GET['udcentral_action']) {
56
- # auth_redirect() does not return, according to the documentation; but the code shows that it can
57
- # auth_redirect();
58
 
59
  if (!empty($_GET['login_id']) && is_numeric($_GET['login_id']) && !empty($_GET['login_key'])) {
60
  $login_user = get_user_by('id', $_GET['login_id']);
61
 
62
- require_once(ABSPATH.WPINC.'/version.php');
63
  if (is_a($login_user, 'WP_User') || (version_compare($wp_version, '3.5', '<') && !empty($login_user->ID))) {
64
  // Allow site implementers to disable this functionality
65
  $allow_autologin = apply_filters('updraftcentral_allow_autologin', true, $login_user);
@@ -82,10 +90,15 @@ class UpdraftPlus_UpdraftCentral_Listener {
82
 
83
  }
84
 
85
- // Do verification before calling this method
 
 
 
 
 
86
  private function autologin_user($user, $redirect_url = false) {
87
  if (!is_user_logged_in()) {
88
- // $user = get_user_by('id', $user_id);
89
  // Don't check that it's a WP_User - that's WP 3.5+ only
90
  if (!is_object($user) || empty($user->ID)) return;
91
  wp_set_current_user($user->ID, $user->user_login);
@@ -114,14 +127,14 @@ class UpdraftPlus_UpdraftCentral_Listener {
114
 
115
  $command_base_class_at = apply_filters('updraftcentral_command_base_class_at', UPDRAFTPLUS_DIR.'/central/commands.php');
116
 
117
- if (!class_exists('UpdraftCentral_Commands')) require_once($command_base_class_at);
118
 
119
- // Second parameter has been passed since
120
  do_action('updraftcentral_command_class_wanted', $command_php_class);
121
 
122
  if (!class_exists($command_php_class)) {
123
  if (file_exists(UPDRAFTPLUS_DIR.'/central/modules/'.$class_prefix.'.php')) {
124
- require_once(UPDRAFTPLUS_DIR.'/central/modules/'.$class_prefix.'.php');
125
  }
126
  }
127
 
@@ -164,8 +177,6 @@ class UpdraftPlus_UpdraftCentral_Listener {
164
  @ob_start();
165
  add_filter('updraftplus_logline', array($this, 'updraftplus_logline'), 10, 4);
166
  if (!UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) return;
167
- // $this->ud->nonce = $hash;
168
- // $this->ud->logfile_open($hash);
169
  }
170
 
171
  public function updraftplus_logline($line, $nonce, $level, $uniq_id) {
@@ -183,7 +194,7 @@ class UpdraftPlus_UpdraftCentral_Listener {
183
  $caught_output = @ob_get_contents();
184
  @ob_end_clean();
185
  // If turning output-catching off, turn this on instead:
186
- // $caught_output = ''; @ob_end_flush();
187
 
188
  // If there's higher-level output buffering going on, then get rid of that
189
  if (ob_get_level()) ob_end_clean();
@@ -209,5 +220,4 @@ class UpdraftPlus_UpdraftCentral_Listener {
209
 
210
  return $msg;
211
  }
212
-
213
  }
2
 
3
  if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
 
5
+ /**
6
+ * This class is the basic glue between the lower-level UpdraftPlus_Remote_Communications (UDRPC) class, and UpdraftPlus. It does not contain actual commands themselves; the class names to use for actual commands are passed in as a parameter to the constructor.
7
+ */
8
  class UpdraftPlus_UpdraftCentral_Listener {
9
 
10
  public $udrpc_version;
11
+
12
  private $ud = null;
13
+
14
  private $receivers = array();
15
+
16
  private $extra_info = array();
17
+
18
  private $php_events = array();
19
+
20
  private $commands = array();
21
+
22
  private $current_udrpc = null;
23
+
24
  private $command_classes;
25
 
26
  public function __construct($keys = array(), $command_classes = array()) {
61
 
62
  // If we ever need to expand beyond a single GET action, this can/should be generalised and put into the commands class
63
  if (!empty($_GET['udcentral_action']) && 'login' == $_GET['udcentral_action']) {
64
+ // auth_redirect() does not return, according to the documentation; but the code shows that it can
65
+ // auth_redirect();
66
 
67
  if (!empty($_GET['login_id']) && is_numeric($_GET['login_id']) && !empty($_GET['login_key'])) {
68
  $login_user = get_user_by('id', $_GET['login_id']);
69
 
70
+ include_once(ABSPATH.WPINC.'/version.php');
71
  if (is_a($login_user, 'WP_User') || (version_compare($wp_version, '3.5', '<') && !empty($login_user->ID))) {
72
  // Allow site implementers to disable this functionality
73
  $allow_autologin = apply_filters('updraftcentral_allow_autologin', true, $login_user);
90
 
91
  }
92
 
93
+ /**
94
+ * Do verification before calling this method
95
+ *
96
+ * @param WP_User|Object $user user object
97
+ * @param boolean $redirect_url Redirect URL
98
+ */
99
  private function autologin_user($user, $redirect_url = false) {
100
  if (!is_user_logged_in()) {
101
+ // $user = get_user_by('id', $user_id);
102
  // Don't check that it's a WP_User - that's WP 3.5+ only
103
  if (!is_object($user) || empty($user->ID)) return;
104
  wp_set_current_user($user->ID, $user->user_login);
127
 
128
  $command_base_class_at = apply_filters('updraftcentral_command_base_class_at', UPDRAFTPLUS_DIR.'/central/commands.php');
129
 
130
+ if (!class_exists('UpdraftCentral_Commands')) include_once($command_base_class_at);
131
 
132
+ // Second parameter has been passed since
133
  do_action('updraftcentral_command_class_wanted', $command_php_class);
134
 
135
  if (!class_exists($command_php_class)) {
136
  if (file_exists(UPDRAFTPLUS_DIR.'/central/modules/'.$class_prefix.'.php')) {
137
+ include_once(UPDRAFTPLUS_DIR.'/central/modules/'.$class_prefix.'.php');
138
  }
139
  }
140
 
177
  @ob_start();
178
  add_filter('updraftplus_logline', array($this, 'updraftplus_logline'), 10, 4);
179
  if (!UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) return;
 
 
180
  }
181
 
182
  public function updraftplus_logline($line, $nonce, $level, $uniq_id) {
194
  $caught_output = @ob_get_contents();
195
  @ob_end_clean();
196
  // If turning output-catching off, turn this on instead:
197
+ // $caught_output = ''; @ob_end_flush();
198
 
199
  // If there's higher-level output buffering going on, then get rid of that
200
  if (ob_get_level()) ob_end_clean();
220
 
221
  return $msg;
222
  }
 
223
  }
central/modules/comments.php CHANGED
@@ -5,19 +5,22 @@ if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
5
  class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
6
 
7
  /**
8
- * The _search_comments function searches all available comments based
9
- * on the following query parameters (type, status, search)
10
- *
11
- * Search Parameters/Filters:
12
- * type - comment types can be 'comment', 'trackback' and 'pingback', defaults to 'comment'
13
- * status - comment status can be 'hold' or unapprove, 'approve', 'spam', 'trash'
14
- * search - user generated content or keyword
15
- */
 
 
 
16
  private function _search_comments($query) {
17
 
18
- //Basic parameters to the query and should display
19
- //the results in descending order (latest comments) first
20
- //based on their generated IDs
21
 
22
  $args = array(
23
  'orderby' => 'ID',
@@ -33,10 +36,10 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
33
  $comments = array();
34
  foreach ($found_comments as $comment) {
35
 
36
- //We're returning a collection of comment in an array,
37
- //in sync with the originator of the request on the ui side
38
- //so, we're pulling it one by one into the array before
39
- //returning it.
40
 
41
  if (!in_array($comment, $comments)) {
42
  array_push($comments, $comment);
@@ -47,38 +50,41 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
47
  }
48
 
49
  /**
50
- * The _calculate_pages function generates and builds the pagination links
51
- * based on the current search parameters/filters. Please see _search_comments
52
- * for the breakdown of these parameters.
53
- */
 
 
 
54
  private function _calculate_pages($query) {
55
  $per_page_options = array(10, 20, 30, 40, 50);
56
 
57
  if (!empty($query)) {
58
  if (!empty($query['search'])) {
59
- return array(
60
- 'page_count' => 1,
61
- 'page_no' => 1
62
- );
63
  }
64
 
65
  $pages = array();
66
  $page_query = new WP_Comment_Query;
67
 
68
- //Here, we're pulling the comments based on the
69
- //two parameters namely type and status.
70
- //
71
- //The number of results/comments found will then
72
- //be use to compute for the number of pages to be
73
- //displayed as navigation links when browsing all
74
- //comments from the frontend.
75
 
76
  $comments = $page_query->query(array(
77
  'type' => $query['type'],
78
  'status' => $query['status']
79
  ));
80
 
81
- $total_comments = count($comments);
82
  $page_count = ceil($total_comments / $query['per_page']);
83
 
84
  if ($page_count > 1) {
@@ -107,7 +113,7 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
107
  );
108
  }
109
 
110
- if ($query['page_no'] === 1) {
111
  $page_prev = array(
112
  'value' => 1,
113
  'setting' => 'disabled'
@@ -146,22 +152,21 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
146
  }
147
 
148
  /**
149
- * The get_blog_sites function pulls blog sites available
150
- * for the current WP instance.
151
- *
152
- * If Multisite is enabled on the server, then sites under the network
153
- * will be pulled, otherwise, it will return an empty array.
154
- */
155
  private function get_blog_sites() {
156
 
157
  if (!is_multisite()) return array();
158
 
159
- //Initialize array container
160
  $sites = $network_sites = array();
161
 
162
- //Check to see if latest get_sites (available on WP version >= 4.6) function is
163
- //available to pull any available sites from the current WP instance. If not, then
164
- //we're going to use the fallback function wp_get_sites (for older version).
165
 
166
  if (function_exists('get_sites') && class_exists('WP_Site_Query')) {
167
  $network_sites = get_sites();
@@ -171,25 +176,24 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
171
  }
172
  }
173
 
174
- //We only process if sites array is not empty, otherwise, bypass
175
- //the next block.
176
 
177
  if (!empty($network_sites)) {
178
  foreach ($network_sites as $site) {
179
 
180
- //Here we're checking if the site type is an array, because
181
- //we're pulling the blog_id property based on the type of
182
- //site returned.
183
- //
184
- //get_sites returns an array of object, whereas the wp_get_sites
185
- //function returns an array of array.
186
 
187
  $blog_id = (is_array($site)) ? $site['blog_id'] : $site->blog_id;
188
 
189
 
190
- //We're saving the blog_id and blog name as an associative item
191
- //into the sites array, that will be used as "Sites" option in
192
- //the frontend.
193
 
194
  $sites[$blog_id] = get_blog_details($blog_id)->blogname;
195
  }
@@ -199,32 +203,39 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
199
  }
200
 
201
  /**
202
- * The get_wp_option function pulls current blog options
203
- * from the database using either following functions:
204
- * - get_blog_option (for multisite)
205
- * - get_option (for ordinary blog)
206
- */
 
 
 
 
207
  private function _get_wp_option($blog_id, $setting) {
208
  return is_multisite() ? get_blog_option($blog_id, $setting) : get_option($setting);
209
  }
210
 
211
  /**
212
- * The get_comments function pull all the comments from the database
213
- * based on the current search parameters/filters. Please see _search_comments
214
- * for the breakdown of these parameters.
215
- */
 
 
 
216
  public function get_comments($query) {
217
 
218
- //Here, we're getting the current blog id. If blog id
219
- //is passed along with the parameters then we override
220
- //that current (default) value with the parameter blog id value.
221
 
222
  $blog_id = get_current_blog_id();
223
  if (isset($query['blog_id'])) $blog_id = $query['blog_id'];
224
 
225
 
226
- //Here, we're switching to the actual blog that we need
227
- //to pull comments from.
228
 
229
  $switched = false;
230
  if (function_exists('switch_to_blog')) {
@@ -232,24 +243,32 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
232
  }
233
 
234
  if (!empty($query['search'])) {
235
- //If a search keyword is present, then we'll call the _search_comments
236
- //function to process the query.
237
 
238
  $comments = $this->_search_comments($query);
239
  } else {
240
- //Set default parameter values if the designated
241
- //parameters are empty.
242
 
243
- if (empty($query['per_page'])) { $query['per_page'] = 10; }
244
- if (empty($query['page_no'])) { $query['page_no'] = 1; }
245
- if (empty($query['type'])) { $query['type'] = ''; }
246
- if (empty($query['status'])) { $query['status'] = ''; }
 
 
 
 
 
 
 
 
247
 
248
- //Since WP_Comment_Query parameters doesn't have a "page" attribute, we
249
- //need to compute for the offset to get the exact content based on the
250
- //current page and the number of items per page.
251
 
252
- $offset = ((int)$query['page_no'] - 1) * (int)$query['per_page'];
253
  $args = array(
254
  'orderby' => 'ID',
255
  'order' => 'DESC',
@@ -260,24 +279,24 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
260
  );
261
 
262
  $comments_query = new WP_Comment_Query;
263
- $comments = $comments_query->query( $args );
264
  }
265
 
266
- //If no comments are found based on the current query then
267
- //we return with error.
268
 
269
  if (empty($comments)) {
270
  $result = array('message' => 'comments_not_found');
271
  return $this->_response($result);
272
  }
273
 
274
- //Otherwise, we're going to process each comment
275
- //before we return it to the one issuing the request.
276
  //
277
- //Process in the sense that we add additional related info
278
- //such as the post tile where the comment belongs to, the
279
- //comment status, a formatted date field, and to which parent comment
280
- //does the comment was intended to be as a reply.
281
 
282
  foreach ($comments as &$comment) {
283
  $comment = get_comment($comment->comment_ID, ARRAY_A);
@@ -290,8 +309,8 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
290
  if ($parent_comment) $comment['in_reply_to'] = $parent_comment['comment_author'];
291
  }
292
 
293
- //We're formatting the comment_date to be exactly the same
294
- //with that of WP Comments table (e.g. 2016/12/21 at 10:30 PM)
295
 
296
  $comment['comment_date'] = date('Y/m/d \a\t g:i a', strtotime($comment['comment_date']));
297
 
@@ -302,8 +321,8 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
302
  }
303
  }
304
 
305
- //We return the following to the one issuing
306
- //the request.
307
 
308
  $result = array(
309
  'comments' => $comments,
@@ -311,8 +330,8 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
311
  );
312
 
313
 
314
- //Here, we're restoring to the current (default) blog before we
315
- //do the switched.
316
 
317
  if (function_exists('restore_current_blog') && $switched) {
318
  restore_current_blog();
@@ -322,17 +341,17 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
322
  }
323
 
324
  /**
325
- * The get_comment_filters function builds a array of options
326
- * to be use as filters for the search function on the frontend.
327
- */
328
  public function get_comment_filters() {
329
- //Options for comment_types field
330
  $comment_types = apply_filters('admin_comment_types_dropdown', array(
331
  'comment' => __('Comments'),
332
  'pings' => __('Pings'),
333
  ));
334
 
335
- //Options for comment_status field
336
  $comment_statuses = array(
337
  'approve' => __('Approve'),
338
  'hold' => __('Hold or Unapprove'),
@@ -340,7 +359,7 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
340
  'spam' => __('Spam'),
341
  );
342
 
343
- //Pull sites options if available.
344
  $sites = $this->get_blog_sites();
345
 
346
  $result = array(
@@ -354,32 +373,35 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
354
  }
355
 
356
  /**
357
- * The get_settings function pulls the current discussion settings
358
- * option values.
359
- */
 
 
 
360
  public function get_settings($params) {
361
 
362
- //Here, we're getting the current blog id. If blog id
363
- //is passed along with the parameters then we override
364
- //that current (default) value with the parameter blog id value.
365
 
366
  $blog_id = get_current_blog_id();
367
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
368
 
369
 
370
- //If user does not have sufficient privileges to manage and edit
371
- //WP options then we return with error.
372
 
373
  if (!current_user_can_for_blog($blog_id, 'manage_options')) {
374
  $result = array('error' => true, 'message' => 'insufficient_permission');
375
  return $this->_response($result);
376
  }
377
 
378
- //Pull sites options if available.
379
  $sites = $this->get_blog_sites();
380
 
381
- //Wrap current discussion settings values into an array item
382
- //named settings.
383
 
384
  $result = array(
385
  'settings' => array(
@@ -411,39 +433,42 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
411
  }
412
 
413
  /**
414
- * The update_settings function updates the discussion settings
415
- * basing on the user generated content/option from the frontend
416
- * form.
417
- */
 
 
 
418
  public function update_settings($params) {
419
 
420
- //Extract settings values from passed parameters.
421
  $settings = $params['settings'];
422
 
423
- //Here, we're getting the current blog id. If blog id
424
- //is passed along with the parameters then we override
425
- //that current (default) value with the parameter blog id value.
426
 
427
  $blog_id = get_current_blog_id();
428
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
429
 
430
 
431
- //If user does not have sufficient privileges to manage and edit
432
- //WP options then we return with error.
433
 
434
  if (!current_user_can_for_blog($blog_id, 'manage_options')) {
435
  $result = array('error' => true, 'message' => 'insufficient_permission');
436
  return $this->_response($result);
437
  }
438
 
439
- //Here, we're sanitizing the input fields before we save them to the database
440
- //for safety and security reason. The "explode" and "implode" functions are meant
441
- //to maintain the line breaks associated with a textarea input/value.
442
 
443
  foreach ($settings as $key => $value) {
444
 
445
- //We're using update_blog_option and update_option altogether to update the current
446
- //discussion settings.
447
 
448
  if (is_multisite()) {
449
  update_blog_option($blog_id, $key, implode("\n", array_map('sanitize_text_field', explode("\n", $value))));
@@ -452,53 +477,56 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
452
  }
453
  }
454
 
455
- //We're not checking for errors here, but instead we're directly returning a success (error = false)
456
- //status always, because WP's update_option will return fail if values were not changed, meaning
457
- //previous values were not changed by the user's current request, not an actual exception thrown.
458
- //Thus, giving a false positive message or report to the frontend.
459
 
460
  $result = array('error' => false, 'message' => 'settings_updated', 'values' => array());
461
  return $this->_response($result);
462
  }
463
 
464
  /**
465
- * The get_comment function pulls a single comment based
466
- * on a comment ID.
467
- */
 
 
 
468
  public function get_comment($params) {
469
 
470
- //Here, we're getting the current blog id. If blog id
471
- //is passed along with the parameters then we override
472
- //that current (default) value with the parameter blog id value.
473
 
474
  $blog_id = get_current_blog_id();
475
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
476
 
477
 
478
- //If user does not have sufficient privileges to moderate or edit
479
- //a comment then we return with error.
480
 
481
  if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
482
  $result = array('error' => true, 'message' => 'insufficient_permission');
483
  return $this->_response($result);
484
  }
485
 
486
- //Here, we're switching to the actual blog that we need
487
- //to pull comments from.
488
 
489
  $switched = false;
490
  if (function_exists('switch_to_blog')) {
491
  $switched = switch_to_blog($blog_id);
492
  }
493
 
494
- //Get comment by comment_ID parameter and return result as an array.
495
  $result = array(
496
  'comment' => get_comment($params['comment_id'], ARRAY_A)
497
  );
498
 
499
 
500
- //Here, we're restoring to the current (default) blog before we
501
- //do the switched.
502
 
503
  if (function_exists('restore_current_blog') && $switched) {
504
  restore_current_blog();
@@ -508,32 +536,35 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
508
  }
509
 
510
  /**
511
- * The reply_comment function creates a new comment as a reply
512
- * to a certain/selected comment.
513
- */
 
 
 
514
  public function reply_comment($params) {
515
 
516
- //Extract reply info from the passed parameters
517
  $reply = $params['comment'];
518
 
519
- //Here, we're getting the current blog id. If blog id
520
- //is passed along with the parameters then we override
521
- //that current (default) value with the parameter blog id value.
522
 
523
  $blog_id = get_current_blog_id();
524
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
525
 
526
 
527
- //If user does not have sufficient privileges to moderate or edit
528
- //a comment then we return with error.
529
 
530
  if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
531
  $result = array('error' => true, 'message' => 'comment_reply_no_permission');
532
  return $this->_response($result);
533
  }
534
 
535
- //Here, we're switching to the actual blog that we need
536
- //to apply our changes.
537
 
538
  $switched = false;
539
  if (function_exists('switch_to_blog')) {
@@ -541,17 +572,17 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
541
  }
542
 
543
 
544
- //Get comment by comment_ID parameter.
545
  $comment = get_comment($reply['comment_id']);
546
  if ($comment) {
547
 
548
- //Get the currently logged in user
549
  $user = wp_get_current_user();
550
 
551
- //If the current comment was not approved yet then
552
- //we need to approve it before we create a reply to
553
- //to the comment, mimicking exactly the WP behaviour
554
- //in terms of creating a reply to a comment.
555
 
556
  if (empty($comment->comment_approved)) {
557
  $update_data = array(
@@ -561,8 +592,8 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
561
  wp_update_comment($update_data);
562
  }
563
 
564
- //Build new comment parameters based on current user info and
565
- //the target comment for the reply.
566
  $data = array(
567
  'comment_post_ID' => $comment->comment_post_ID,
568
  'comment_author' => $user->display_name,
@@ -575,8 +606,8 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
575
  'comment_approved' => 1
576
  );
577
 
578
- //Create new comment based on the parameters above, and return
579
- //the status accordingly.
580
 
581
  if (wp_insert_comment($data)) {
582
  $result = array('error' => false, 'message' => 'comment_replied_with_comment_author', 'values' => array($comment->comment_author));
@@ -588,8 +619,8 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
588
  }
589
 
590
 
591
- //Here, we're restoring to the current (default) blog before we
592
- //do the switched.
593
 
594
  if (function_exists('restore_current_blog') && $switched) {
595
  restore_current_blog();
@@ -599,32 +630,35 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
599
  }
600
 
601
  /**
602
- * The edit_comment function saves new information for the
603
- * currently selected comment.
604
- */
 
 
 
605
  public function edit_comment($params) {
606
 
607
- //Extract new comment info from the passed parameters
608
  $comment = $params['comment'];
609
 
610
- //Here, we're getting the current blog id. If blog id
611
- //is passed along with the parameters then we override
612
- //that current (default) value with the parameter blog id value.
613
 
614
  $blog_id = get_current_blog_id();
615
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
616
 
617
 
618
- //If user does not have sufficient privileges to moderate or edit
619
- //a comment then we return with error.
620
 
621
  if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
622
  $result = array('error' => true, 'message' => 'comment_edit_no_permission');
623
  return $this->_response($result);
624
  }
625
 
626
- //Here, we're switching to the actual blog that we need
627
- //to apply our changes.
628
 
629
  $switched = false;
630
  if (function_exists('switch_to_blog')) {
@@ -632,26 +666,26 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
632
  }
633
 
634
 
635
- //Get current comment details
636
  $original_comment = get_comment($comment['comment_id']);
637
  if ($original_comment) {
638
  $data = array();
639
 
640
- //Replace "comment_id" with "comment_ID" since WP does not recognize
641
- //the small case "id".
642
  $comment['comment_ID'] = $original_comment->comment_ID;
643
  unset($comment['comment_id']);
644
 
645
- //Here, we're sanitizing the input fields before we save them to the database
646
- //for safety and security reason. The "explode" and "implode" functions are meant
647
- //to maintain the line breaks associated with a textarea input/value.
648
 
649
  foreach ($comment as $key => $value) {
650
  $data[$key] = implode("\n", array_map('sanitize_text_field', explode("\n", $value)));
651
  }
652
 
653
- //Update existing comment based on the passed parameter fields and
654
- //return the status accordingly.
655
 
656
  if (wp_update_comment($data)) {
657
  $result = array('error' => false, 'message' => 'comment_edited_with_comment_author', 'values' => array($original_comment->comment_author));
@@ -662,8 +696,8 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
662
  $result = array('error' => true, 'message' => 'comment_does_not_exists_error', 'values' => array($comment['comment_id']));
663
  }
664
 
665
- //Here, we're restoring to the current (default) blog before we
666
- //do the switched.
667
 
668
  if (function_exists('restore_current_blog') && $switched) {
669
  restore_current_blog();
@@ -673,37 +707,40 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
673
  }
674
 
675
  /**
676
- * The update_comment_status function is a generic handler for the following
677
- * comment actions:
678
- *
679
- * - approve comment
680
- * - unapprove comment
681
- * - set comment as spam
682
- * - move commment to trash
683
- * - delete comment permanently
684
- * - unset comment as spam
685
- * - restore comment
686
- */
 
 
 
687
  public function update_comment_status($params) {
688
 
689
- //Here, we're getting the current blog id. If blog id
690
- //is passed along with the parameters then we override
691
- //that current (default) value with the parameter blog id value.
692
 
693
  $blog_id = get_current_blog_id();
694
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
695
 
696
 
697
- //If user does not have sufficient privileges to moderate or edit
698
- //a comment then we return with error.
699
 
700
  if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
701
  $result = array('error' => true, 'message' => 'comment_change_status_no_permission');
702
  return $this->_response($result);
703
  }
704
 
705
- //Here, we're switching to the actual blog that we need
706
- //to apply our changes.
707
 
708
  $switched = false;
709
  if (function_exists('switch_to_blog')) {
@@ -711,55 +748,73 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
711
  }
712
 
713
 
714
- //We make sure that we still have a valid comment from the server
715
- //before we apply the currently selected action.
716
 
717
  $comment = get_comment($params['comment_id']);
718
  if ($comment) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
719
  $succeeded = false;
720
  $message = '';
721
 
722
- //Here, we're using WP's wp_set_comment_status function to change the state
723
- //of the selected comment based on the current action, except for the "delete" action
724
- //where we use the wp_delete_comment to delete the comment permanently by passing
725
- //"true" to the second argument.
726
 
727
  switch ($params['action']) {
728
  case 'approve':
729
- $succeeded = wp_set_comment_status($params['comment_id'], 'approve');
730
- $message = 'comment_approve_with_comment_author';
731
  break;
732
  case 'unapprove':
733
- $succeeded = wp_set_comment_status($params['comment_id'], 'hold');
734
- $message = 'comment_unapprove_with_comment_author';
735
  break;
736
  case 'spam':
737
- $succeeded = wp_set_comment_status($params['comment_id'], 'spam');
738
- $message = 'comment_spam_with_comment_author';
739
  break;
740
  case 'trash':
741
- $succeeded = wp_set_comment_status($params['comment_id'], 'trash');
742
- $message = 'comment_trash_with_comment_author';
743
  break;
744
  case 'delete':
745
- $succeeded = wp_delete_comment($params['comment_id'], true);
746
- $message = 'comment_delete_with_comment_author';
747
  break;
748
  case 'notspam':
749
- $succeeded = wp_set_comment_status($params['comment_id'], 'hold');
750
- $message = 'comment_not_spam_with_comment_author';
751
  break;
752
  case 'restore':
753
- $succeeded = wp_set_comment_status($params['comment_id'], 'hold');
754
- $message = 'comment_restore_with_comment_author';
755
  break;
756
  }
757
 
758
- //If the current action succeeded, then we return a success message, otherwise,
759
- //we return an error message to the user issuing the request.
760
 
761
  if ($succeeded) {
762
- $result = array('error' => false, 'message' => $message, 'values' => array($comment->comment_author));
763
  } else {
764
  $result = array('error' => true, 'message' => 'comment_change_status_failed_with_error', 'values' => array($comment->comment_ID));
765
  }
@@ -767,8 +822,8 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
767
  $result = array('error' => true, 'message' => 'comment_does_not_exists_error', 'values' => array($params['comment_id']));
768
  }
769
 
770
- //Here, we're restoring to the current (default) blog before we
771
- //do the switched.
772
 
773
  if (function_exists('restore_current_blog') && $switched) {
774
  restore_current_blog();
@@ -776,5 +831,4 @@ class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
776
 
777
  return $this->_response($result);
778
  }
779
-
780
  }
5
  class UpdraftCentral_Comments_Commands extends UpdraftCentral_Commands {
6
 
7
  /**
8
+ * The _search_comments function searches all available comments based
9
+ * on the following query parameters (type, status, search)
10
+ *
11
+ * Search Parameters/Filters:
12
+ * type - comment types can be 'comment', 'trackback' and 'pingback', defaults to 'comment'
13
+ * status - comment status can be 'hold' or unapprove, 'approve', 'spam', 'trash'
14
+ * search - user generated content or keyword
15
+ *
16
+ * @param array $query The query to search comments
17
+ * @return array
18
+ */
19
  private function _search_comments($query) {
20
 
21
+ // Basic parameters to the query and should display
22
+ // the results in descending order (latest comments) first
23
+ // based on their generated IDs
24
 
25
  $args = array(
26
  'orderby' => 'ID',
36
  $comments = array();
37
  foreach ($found_comments as $comment) {
38
 
39
+ // We're returning a collection of comment in an array,
40
+ // in sync with the originator of the request on the ui side
41
+ // so, we're pulling it one by one into the array before
42
+ // returning it.
43
 
44
  if (!in_array($comment, $comments)) {
45
  array_push($comments, $comment);
50
  }
51
 
52
  /**
53
+ * The _calculate_pages function generates and builds the pagination links
54
+ * based on the current search parameters/filters. Please see _search_comments
55
+ * for the breakdown of these parameters.
56
+ *
57
+ * @param array $query Query to generate pagination links
58
+ * @return array
59
+ */
60
  private function _calculate_pages($query) {
61
  $per_page_options = array(10, 20, 30, 40, 50);
62
 
63
  if (!empty($query)) {
64
  if (!empty($query['search'])) {
65
+ return array(
66
+ 'page_count' => 1,
67
+ 'page_no' => 1
68
+ );
69
  }
70
 
71
  $pages = array();
72
  $page_query = new WP_Comment_Query;
73
 
74
+ // Here, we're pulling the comments based on the
75
+ // two parameters namely type and status.
76
+ //
77
+ // The number of results/comments found will then
78
+ // be use to compute for the number of pages to be
79
+ // displayed as navigation links when browsing all
80
+ // comments from the frontend.
81
 
82
  $comments = $page_query->query(array(
83
  'type' => $query['type'],
84
  'status' => $query['status']
85
  ));
86
 
87
+ $total_comments = count($comments);
88
  $page_count = ceil($total_comments / $query['per_page']);
89
 
90
  if ($page_count > 1) {
113
  );
114
  }
115
 
116
+ if (1 === $query['page_no']) {
117
  $page_prev = array(
118
  'value' => 1,
119
  'setting' => 'disabled'
152
  }
153
 
154
  /**
155
+ * The get_blog_sites function pulls blog sites available for the current WP instance.
156
+ * If Multisite is enabled on the server, then sites under the network will be pulled, otherwise, it will return an empty array.
157
+ *
158
+ * @return array
159
+ */
 
160
  private function get_blog_sites() {
161
 
162
  if (!is_multisite()) return array();
163
 
164
+ // Initialize array container
165
  $sites = $network_sites = array();
166
 
167
+ // Check to see if latest get_sites (available on WP version >= 4.6) function is
168
+ // available to pull any available sites from the current WP instance. If not, then
169
+ // we're going to use the fallback function wp_get_sites (for older version).
170
 
171
  if (function_exists('get_sites') && class_exists('WP_Site_Query')) {
172
  $network_sites = get_sites();
176
  }
177
  }
178
 
179
+ // We only process if sites array is not empty, otherwise, bypass
180
+ // the next block.
181
 
182
  if (!empty($network_sites)) {
183
  foreach ($network_sites as $site) {
184
 
185
+ // Here we're checking if the site type is an array, because
186
+ // we're pulling the blog_id property based on the type of
187
+ // site returned.
188
+ // get_sites returns an array of object, whereas the wp_get_sites
189
+ // function returns an array of array.
 
190
 
191
  $blog_id = (is_array($site)) ? $site['blog_id'] : $site->blog_id;
192
 
193
 
194
+ // We're saving the blog_id and blog name as an associative item
195
+ // into the sites array, that will be used as "Sites" option in
196
+ // the frontend.
197
 
198
  $sites[$blog_id] = get_blog_details($blog_id)->blogname;
199
  }
203
  }
204
 
205
  /**
206
+ * The get_wp_option function pulls current blog options
207
+ * from the database using either following functions:
208
+ * - get_blog_option (for multisite)
209
+ * - get_option (for ordinary blog)
210
+ *
211
+ * @param array $blog_id This is the specific blog ID
212
+ * @param array $setting specifies settings
213
+ * @return array
214
+ */
215
  private function _get_wp_option($blog_id, $setting) {
216
  return is_multisite() ? get_blog_option($blog_id, $setting) : get_option($setting);
217
  }
218
 
219
  /**
220
+ * The get_comments function pull all the comments from the database
221
+ * based on the current search parameters/filters. Please see _search_comments
222
+ * for the breakdown of these parameters.
223
+ *
224
+ * @param array $query Specific query to pull comments
225
+ * @return array
226
+ */
227
  public function get_comments($query) {
228
 
229
+ // Here, we're getting the current blog id. If blog id
230
+ // is passed along with the parameters then we override
231
+ // that current (default) value with the parameter blog id value.
232
 
233
  $blog_id = get_current_blog_id();
234
  if (isset($query['blog_id'])) $blog_id = $query['blog_id'];
235
 
236
 
237
+ // Here, we're switching to the actual blog that we need
238
+ // to pull comments from.
239
 
240
  $switched = false;
241
  if (function_exists('switch_to_blog')) {
243
  }
244
 
245
  if (!empty($query['search'])) {
246
+ // If a search keyword is present, then we'll call the _search_comments
247
+ // function to process the query.
248
 
249
  $comments = $this->_search_comments($query);
250
  } else {
251
+ // Set default parameter values if the designated
252
+ // parameters are empty.
253
 
254
+ if (empty($query['per_page'])) {
255
+ $query['per_page'] = 10;
256
+ }
257
+ if (empty($query['page_no'])) {
258
+ $query['page_no'] = 1;
259
+ }
260
+ if (empty($query['type'])) {
261
+ $query['type'] = '';
262
+ }
263
+ if (empty($query['status'])) {
264
+ $query['status'] = '';
265
+ }
266
 
267
+ // Since WP_Comment_Query parameters doesn't have a "page" attribute, we
268
+ // need to compute for the offset to get the exact content based on the
269
+ // current page and the number of items per page.
270
 
271
+ $offset = ((int) $query['page_no'] - 1) * (int) $query['per_page'];
272
  $args = array(
273
  'orderby' => 'ID',
274
  'order' => 'DESC',
279
  );
280
 
281
  $comments_query = new WP_Comment_Query;
282
+ $comments = $comments_query->query($args);
283
  }
284
 
285
+ // If no comments are found based on the current query then
286
+ // we return with error.
287
 
288
  if (empty($comments)) {
289
  $result = array('message' => 'comments_not_found');
290
  return $this->_response($result);
291
  }
292
 
293
+ // Otherwise, we're going to process each comment
294
+ // before we return it to the one issuing the request.
295
  //
296
+ // Process in the sense that we add additional related info
297
+ // such as the post tile where the comment belongs to, the
298
+ // comment status, a formatted date field, and to which parent comment
299
+ // does the comment was intended to be as a reply.
300
 
301
  foreach ($comments as &$comment) {
302
  $comment = get_comment($comment->comment_ID, ARRAY_A);
309
  if ($parent_comment) $comment['in_reply_to'] = $parent_comment['comment_author'];
310
  }
311
 
312
+ // We're formatting the comment_date to be exactly the same
313
+ // with that of WP Comments table (e.g. 2016/12/21 at 10:30 PM)
314
 
315
  $comment['comment_date'] = date('Y/m/d \a\t g:i a', strtotime($comment['comment_date']));
316
 
321
  }
322
  }
323
 
324
+ // We return the following to the one issuing
325
+ // the request.
326
 
327
  $result = array(
328
  'comments' => $comments,
330
  );
331
 
332
 
333
+ // Here, we're restoring to the current (default) blog before we
334
+ // do the switched.
335
 
336
  if (function_exists('restore_current_blog') && $switched) {
337
  restore_current_blog();
341
  }
342
 
343
  /**
344
+ * The get_comment_filters function builds a array of options
345
+ * to be use as filters for the search function on the frontend.
346
+ */
347
  public function get_comment_filters() {
348
+ // Options for comment_types field
349
  $comment_types = apply_filters('admin_comment_types_dropdown', array(
350
  'comment' => __('Comments'),
351
  'pings' => __('Pings'),
352
  ));
353
 
354
+ // Options for comment_status field
355
  $comment_statuses = array(
356
  'approve' => __('Approve'),
357
  'hold' => __('Hold or Unapprove'),
359
  'spam' => __('Spam'),
360
  );
361
 
362
+ // Pull sites options if available.
363
  $sites = $this->get_blog_sites();
364
 
365
  $result = array(
373
  }
374
 
375
  /**
376
+ * The get_settings function pulls the current discussion settings
377
+ * option values.
378
+ *
379
+ * @param array $params Passing specific params for getting current discussion settings
380
+ * @return array
381
+ */
382
  public function get_settings($params) {
383
 
384
+ // Here, we're getting the current blog id. If blog id
385
+ // is passed along with the parameters then we override
386
+ // that current (default) value with the parameter blog id value.
387
 
388
  $blog_id = get_current_blog_id();
389
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
390
 
391
 
392
+ // If user does not have sufficient privileges to manage and edit
393
+ // WP options then we return with error.
394
 
395
  if (!current_user_can_for_blog($blog_id, 'manage_options')) {
396
  $result = array('error' => true, 'message' => 'insufficient_permission');
397
  return $this->_response($result);
398
  }
399
 
400
+ // Pull sites options if available.
401
  $sites = $this->get_blog_sites();
402
 
403
+ // Wrap current discussion settings values into an array item
404
+ // named settings.
405
 
406
  $result = array(
407
  'settings' => array(
433
  }
434
 
435
  /**
436
+ * The update_settings function updates the discussion settings
437
+ * basing on the user generated content/option from the frontend
438
+ * form.
439
+ *
440
+ * @param array $params Specific params to update settings based on discussion
441
+ * @return array
442
+ */
443
  public function update_settings($params) {
444
 
445
+ // Extract settings values from passed parameters.
446
  $settings = $params['settings'];
447
 
448
+ // Here, we're getting the current blog id. If blog id
449
+ // is passed along with the parameters then we override
450
+ // that current (default) value with the parameter blog id value.
451
 
452
  $blog_id = get_current_blog_id();
453
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
454
 
455
 
456
+ // If user does not have sufficient privileges to manage and edit
457
+ // WP options then we return with error.
458
 
459
  if (!current_user_can_for_blog($blog_id, 'manage_options')) {
460
  $result = array('error' => true, 'message' => 'insufficient_permission');
461
  return $this->_response($result);
462
  }
463
 
464
+ // Here, we're sanitizing the input fields before we save them to the database
465
+ // for safety and security reason. The "explode" and "implode" functions are meant
466
+ // to maintain the line breaks associated with a textarea input/value.
467
 
468
  foreach ($settings as $key => $value) {
469
 
470
+ // We're using update_blog_option and update_option altogether to update the current
471
+ // discussion settings.
472
 
473
  if (is_multisite()) {
474
  update_blog_option($blog_id, $key, implode("\n", array_map('sanitize_text_field', explode("\n", $value))));
477
  }
478
  }
479
 
480
+ // We're not checking for errors here, but instead we're directly returning a success (error = false)
481
+ // status always, because WP's update_option will return fail if values were not changed, meaning
482
+ // previous values were not changed by the user's current request, not an actual exception thrown.
483
+ // Thus, giving a false positive message or report to the frontend.
484
 
485
  $result = array('error' => false, 'message' => 'settings_updated', 'values' => array());
486
  return $this->_response($result);
487
  }
488
 
489
  /**
490
+ * The get_comment function pulls a single comment based
491
+ * on a comment ID.
492
+ *
493
+ * @param array $params Specific params for getting a single comment
494
+ * @return array
495
+ */
496
  public function get_comment($params) {
497
 
498
+ // Here, we're getting the current blog id. If blog id
499
+ // is passed along with the parameters then we override
500
+ // that current (default) value with the parameter blog id value.
501
 
502
  $blog_id = get_current_blog_id();
503
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
504
 
505
 
506
+ // If user does not have sufficient privileges to moderate or edit
507
+ // a comment then we return with error.
508
 
509
  if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
510
  $result = array('error' => true, 'message' => 'insufficient_permission');
511
  return $this->_response($result);
512
  }
513
 
514
+ // Here, we're switching to the actual blog that we need
515
+ // to pull comments from.
516
 
517
  $switched = false;
518
  if (function_exists('switch_to_blog')) {
519
  $switched = switch_to_blog($blog_id);
520
  }
521
 
522
+ // Get comment by comment_ID parameter and return result as an array.
523
  $result = array(
524
  'comment' => get_comment($params['comment_id'], ARRAY_A)
525
  );
526
 
527
 
528
+ // Here, we're restoring to the current (default) blog before we
529
+ // do the switched.
530
 
531
  if (function_exists('restore_current_blog') && $switched) {
532
  restore_current_blog();
536
  }
537
 
538
  /**
539
+ * The reply_comment function creates a new comment as a reply
540
+ * to a certain/selected comment.
541
+ *
542
+ * @param array $params Specific params to create a new comment reply
543
+ * @return array
544
+ */
545
  public function reply_comment($params) {
546
 
547
+ // Extract reply info from the passed parameters
548
  $reply = $params['comment'];
549
 
550
+ // Here, we're getting the current blog id. If blog id
551
+ // is passed along with the parameters then we override
552
+ // that current (default) value with the parameter blog id value.
553
 
554
  $blog_id = get_current_blog_id();
555
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
556
 
557
 
558
+ // If user does not have sufficient privileges to moderate or edit
559
+ // a comment then we return with error.
560
 
561
  if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
562
  $result = array('error' => true, 'message' => 'comment_reply_no_permission');
563
  return $this->_response($result);
564
  }
565
 
566
+ // Here, we're switching to the actual blog that we need
567
+ // to apply our changes.
568
 
569
  $switched = false;
570
  if (function_exists('switch_to_blog')) {
572
  }
573
 
574
 
575
+ // Get comment by comment_ID parameter.
576
  $comment = get_comment($reply['comment_id']);
577
  if ($comment) {
578
 
579
+ // Get the currently logged in user
580
  $user = wp_get_current_user();
581
 
582
+ // If the current comment was not approved yet then
583
+ // we need to approve it before we create a reply to
584
+ // to the comment, mimicking exactly the WP behaviour
585
+ // in terms of creating a reply to a comment.
586
 
587
  if (empty($comment->comment_approved)) {
588
  $update_data = array(
592
  wp_update_comment($update_data);
593
  }
594
 
595
+ // Build new comment parameters based on current user info and
596
+ // the target comment for the reply.
597
  $data = array(
598
  'comment_post_ID' => $comment->comment_post_ID,
599
  'comment_author' => $user->display_name,
606
  'comment_approved' => 1
607
  );
608
 
609
+ // Create new comment based on the parameters above, and return
610
+ // the status accordingly.
611
 
612
  if (wp_insert_comment($data)) {
613
  $result = array('error' => false, 'message' => 'comment_replied_with_comment_author', 'values' => array($comment->comment_author));
619
  }
620
 
621
 
622
+ // Here, we're restoring to the current (default) blog before we
623
+ // do the switched.
624
 
625
  if (function_exists('restore_current_blog') && $switched) {
626
  restore_current_blog();
630
  }
631
 
632
  /**
633
+ * The edit_comment function saves new information for the
634
+ * currently selected comment.
635
+ *
636
+ * @param array $params Specific params for editing a coment
637
+ * @return array
638
+ */
639
  public function edit_comment($params) {
640
 
641
+ // Extract new comment info from the passed parameters
642
  $comment = $params['comment'];
643
 
644
+ // Here, we're getting the current blog id. If blog id
645
+ // is passed along with the parameters then we override
646
+ // that current (default) value with the parameter blog id value.
647
 
648
  $blog_id = get_current_blog_id();
649
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
650
 
651
 
652
+ // If user does not have sufficient privileges to moderate or edit
653
+ // a comment then we return with error.
654
 
655
  if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
656
  $result = array('error' => true, 'message' => 'comment_edit_no_permission');
657
  return $this->_response($result);
658
  }
659
 
660
+ // Here, we're switching to the actual blog that we need
661
+ // to apply our changes.
662
 
663
  $switched = false;
664
  if (function_exists('switch_to_blog')) {
666
  }
667
 
668
 
669
+ // Get current comment details
670
  $original_comment = get_comment($comment['comment_id']);
671
  if ($original_comment) {
672
  $data = array();
673
 
674
+ // Replace "comment_id" with "comment_ID" since WP does not recognize
675
+ // the small case "id".
676
  $comment['comment_ID'] = $original_comment->comment_ID;
677
  unset($comment['comment_id']);
678
 
679
+ // Here, we're sanitizing the input fields before we save them to the database
680
+ // for safety and security reason. The "explode" and "implode" functions are meant
681
+ // to maintain the line breaks associated with a textarea input/value.
682
 
683
  foreach ($comment as $key => $value) {
684
  $data[$key] = implode("\n", array_map('sanitize_text_field', explode("\n", $value)));
685
  }
686
 
687
+ // Update existing comment based on the passed parameter fields and
688
+ // return the status accordingly.
689
 
690
  if (wp_update_comment($data)) {
691
  $result = array('error' => false, 'message' => 'comment_edited_with_comment_author', 'values' => array($original_comment->comment_author));
696
  $result = array('error' => true, 'message' => 'comment_does_not_exists_error', 'values' => array($comment['comment_id']));
697
  }
698
 
699
+ // Here, we're restoring to the current (default) blog before we
700
+ // do the switched.
701
 
702
  if (function_exists('restore_current_blog') && $switched) {
703
  restore_current_blog();
707
  }
708
 
709
  /**
710
+ * The update_comment_status function is a generic handler for the following
711
+ * comment actions:
712
+ *
713
+ * - approve comment
714
+ * - unapprove comment
715
+ * - set comment as spam
716
+ * - move commment to trash
717
+ * - delete comment permanently
718
+ * - unset comment as spam
719
+ * - restore comment
720
+ *
721
+ * @param array $params Specific params to update comment status
722
+ * @return array
723
+ */
724
  public function update_comment_status($params) {
725
 
726
+ // Here, we're getting the current blog id. If blog id
727
+ // is passed along with the parameters then we override
728
+ // that current (default) value with the parameter blog id value.
729
 
730
  $blog_id = get_current_blog_id();
731
  if (isset($params['blog_id'])) $blog_id = $params['blog_id'];
732
 
733
 
734
+ // If user does not have sufficient privileges to moderate or edit
735
+ // a comment then we return with error.
736
 
737
  if (!current_user_can_for_blog($blog_id, 'moderate_comments')) {
738
  $result = array('error' => true, 'message' => 'comment_change_status_no_permission');
739
  return $this->_response($result);
740
  }
741
 
742
+ // Here, we're switching to the actual blog that we need
743
+ // to apply our changes.
744
 
745
  $switched = false;
746
  if (function_exists('switch_to_blog')) {
748
  }
749
 
750
 
751
+ // We make sure that we still have a valid comment from the server
752
+ // before we apply the currently selected action.
753
 
754
  $comment = get_comment($params['comment_id']);
755
  if ($comment) {
756
+ $post = get_post($comment->comment_post_ID);
757
+
758
+ if ($post) $comment->in_response_to = $post->post_title;
759
+ if (!empty($comment->comment_parent)) {
760
+ $parent_comment = get_comment($comment->comment_parent);
761
+ if ($parent_comment) $comment->in_reply_to = $parent_comment->comment_author;
762
+ }
763
+
764
+ //We're formatting the comment_date to be exactly the same
765
+ //with that of WP Comments table (e.g. 2016/12/21 at 10:30 PM)
766
+
767
+ $comment->comment_date = date('Y/m/d \a\t g:i a', strtotime($comment->comment_date));
768
+
769
+ $status = wp_get_comment_status($comment->comment_ID);
770
+ if ($status) {
771
+ $comment->comment_status = $status;
772
+ }
773
+
774
  $succeeded = false;
775
  $message = '';
776
 
777
+ // Here, we're using WP's wp_set_comment_status function to change the state
778
+ // of the selected comment based on the current action, except for the "delete" action
779
+ // where we use the wp_delete_comment to delete the comment permanently by passing
780
+ // "true" to the second argument.
781
 
782
  switch ($params['action']) {
783
  case 'approve':
784
+ $succeeded = wp_set_comment_status($params['comment_id'], 'approve');
785
+ $message = 'comment_approve_with_comment_author';
786
  break;
787
  case 'unapprove':
788
+ $succeeded = wp_set_comment_status($params['comment_id'], 'hold');
789
+ $message = 'comment_unapprove_with_comment_author';
790
  break;
791
  case 'spam':
792
+ $succeeded = wp_set_comment_status($params['comment_id'], 'spam');
793
+ $message = 'comment_spam_with_comment_author';
794
  break;
795
  case 'trash':
796
+ $succeeded = wp_set_comment_status($params['comment_id'], 'trash');
797
+ $message = 'comment_trash_with_comment_author';
798
  break;
799
  case 'delete':
800
+ $succeeded = wp_delete_comment($params['comment_id'], true);
801
+ $message = 'comment_delete_with_comment_author';
802
  break;
803
  case 'notspam':
804
+ $succeeded = wp_set_comment_status($params['comment_id'], 'hold');
805
+ $message = 'comment_not_spam_with_comment_author';
806
  break;
807
  case 'restore':
808
+ $succeeded = wp_set_comment_status($params['comment_id'], 'hold');
809
+ $message = 'comment_restore_with_comment_author';
810
  break;
811
  }
812
 
813
+ // If the current action succeeded, then we return a success message, otherwise,
814
+ // we return an error message to the user issuing the request.
815
 
816
  if ($succeeded) {
817
+ $result = array('error' => false, 'message' => $message, 'values' => array($comment->comment_author), 'status' => $comment->comment_status, 'approved' => $comment->comment_approved);
818
  } else {
819
  $result = array('error' => true, 'message' => 'comment_change_status_failed_with_error', 'values' => array($comment->comment_ID));
820
  }
822
  $result = array('error' => true, 'message' => 'comment_does_not_exists_error', 'values' => array($params['comment_id']));
823
  }
824
 
825
+ // Here, we're restoring to the current (default) blog before we
826
+ // do the switched.
827
 
828
  if (function_exists('restore_current_blog') && $switched) {
829
  restore_current_blog();
831
 
832
  return $this->_response($result);
833
  }
 
834
  }
central/modules/core.php CHANGED
@@ -2,23 +2,19 @@
2
 
3
  if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
 
5
- /*
6
- - A container for RPC commands (core UpdraftCentral commands). Commands map exactly onto method names (and hence this class should not implement anything else, beyond the constructor, and private methods)
7
- - Return format is array('response' => (string - a code), 'data' => (mixed));
8
-
9
- RPC commands are not allowed to begin with an underscore. So, any private methods can be prefixed with an underscore.
10
-
11
- */
12
-
13
  class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
14
 
15
  /**
16
  * Validates the credentials entered by the user
17
  *
18
- * @param $creds - an array of filesystem credentials
19
- *
20
- * @return array $result - An array containing the result of
21
- * the validation process.
22
  */
23
  public function validate_credentials($creds) {
24
 
@@ -39,8 +35,8 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
39
  // template.php needed for submit_button() which is called by request_filesystem_credentials()
40
  $this->_admin_include('file.php', 'template.php');
41
 
42
- //Directory entities that we currently need permissions
43
- //to update.
44
  $entity_directories = array(
45
  'plugins' => WP_PLUGIN_DIR,
46
  'themes' => WP_CONTENT_DIR.'/themes',
@@ -50,8 +46,8 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
50
  $url = wp_nonce_url(site_url());
51
  $directory = $entity_directories[$entity];
52
 
53
- //Check if credentials are valid and have sufficient
54
- //privileges to create and delete (e.g. write)
55
  $credentials = request_filesystem_credentials($url, '', false, $directory);
56
  if (WP_Filesystem($credentials, $directory)) {
57
 
@@ -69,7 +65,7 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
69
  $result = array('error' => true, 'message' => 'failed_credentials', 'values' => array());
70
  }
71
 
72
- } catch(Exception $e) {
73
  $result = array('error' => true, 'message' => $e->getMessage(), 'values' => array());
74
  }
75
 
@@ -79,51 +75,51 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
79
  /**
80
  * Gets the FileSystem Credentials
81
  *
82
- * Extract the needed filesystem credentials (permissions) to be used
83
  * to update/upgrade the plugins, themes and the WP core.
84
  *
85
  * @return array $result - An array containing the creds form and some flags
86
- * to determine whether we need to extract the creds
87
  * manually from the user.
88
  */
89
  public function get_credentials() {
90
 
91
  try {
92
 
93
- //Check whether user has enough permission to update entities
94
  if (!current_user_can('update_plugins') && !current_user_can('update_themes') && !current_user_can('update_core')) return $this->_generic_error_response('updates_permission_denied');
95
 
96
- //Include the needed WP Core file(s)
97
  $this->_admin_include('file.php', 'template.php');
98
 
99
- //A container that will hold the state (in this case, either true or false) of
100
- //each directory entities (plugins, themes, core) that will be used to determine
101
- //whether or not there's a need to show a form that will ask the user for their credentials
102
- //manually.
103
  $request_filesystem_credentials = array();
104
 
105
- //A container for the filesystem credentials form if applicable.
106
  $filesystem_form = '';
107
 
108
- //Directory entities that we currently need permissions
109
- //to update.
110
  $check_fs = array(
111
  'plugins' => WP_PLUGIN_DIR,
112
  'themes' => WP_CONTENT_DIR.'/themes',
113
  'core' => untrailingslashit(ABSPATH)
114
  );
115
 
116
- //Here, we're looping through each entities and find output whether
117
- //we have sufficient permissions to update objects belonging to them.
118
  foreach ($check_fs as $entity => $dir) {
119
 
120
- //We're determining which method to use when updating
121
- //the files in the filesystem.
122
  $filesystem_method = get_filesystem_method(array(), $dir);
123
 
124
- //Buffering the output to pull the actual credentials form
125
- //currently being used by this WP instance if no sufficient permissions
126
- //is found.
127
  $url = wp_nonce_url(site_url());
128
 
129
  ob_start();
@@ -135,19 +131,19 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
135
  }
136
  ob_end_clean();
137
 
138
- //Save the state whether or not there's a need to show the
139
- //credentials form to the user.
140
- $request_filesystem_credentials[$entity] = ($filesystem_method !== 'direct' && !$filesystem_credentials_are_stored);
141
  }
142
 
143
- //Wrapping the credentials info before passing it back
144
- //to the client issuing the request.
145
  $result = array(
146
  'request_filesystem_credentials' => $request_filesystem_credentials,
147
  'filesystem_form' => $filesystem_form
148
  );
149
 
150
- } catch(Exception $e) {
151
  $result = array('error' => true, 'message' => $e->getMessage(), 'values' => array());
152
  }
153
 
@@ -158,8 +154,8 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
158
  * Fetches a browser-usable URL which will automatically log the user in to the site
159
  *
160
  * @param String $redirect_to - the URL to got to after logging in
161
- * @param Array $extra_info - valid keys are user_id, which should be a numeric user ID to log in as.
162
- */
163
  public function get_login_url($redirect_to, $extra_info) {
164
  if (is_array($extra_info) && !empty($extra_info['user_id']) && is_numeric($extra_info['user_id'])) {
165
 
@@ -171,18 +167,18 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
171
  $redirect_url = network_admin_url();
172
  if (is_array($redirect_to) && !empty($redirect_to['module'])) {
173
  switch ($redirect_to['module']) {
174
- case 'updraftplus';
175
- if ('initiate_restore' == $redirect_to['action'] && class_exists('UpdraftPlus_Options')) {
176
- $redirect_url = UpdraftPlus_Options::admin_page_url().'?page=updraftplus&udaction=initiate_restore&entities='.urlencode($redirect_to['data']['entities']).'&showdata='.urlencode($redirect_to['data']['showdata']).'&backup_timestamp='.(int)$redirect_to['data']['backup_timestamp'];
177
- } elseif ('download_file' == $redirect_to['action']) {
178
- $findex = empty($redirect_to['data']['findex']) ? 0 : (int)$redirect_to['data']['findex'];
179
- // e.g. ?udcentral_action=dl&action=updraftplus_spool_file&backup_timestamp=1455101696&findex=0&what=plugins
180
- $redirect_url = site_url().'?udcentral_action=spool_file&action=updraftplus_spool_file&findex='.$findex.'&what='.urlencode($redirect_to['data']['what']).'&backup_timestamp='.(int)$redirect_to['data']['backup_timestamp'];
181
- }
182
- break;
183
  case 'direct_url':
184
- $redirect_url = $redirect_to['url'];
185
- break;
186
  }
187
  }
188
 
@@ -207,7 +203,7 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
207
  public function phpinfo() {
208
  $phpinfo = $this->_get_phpinfo_array();
209
 
210
- if (!empty($phpinfo)){
211
  return $this->_response($phpinfo);
212
  }
213
 
@@ -216,7 +212,12 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
216
 
217
 
218
 
219
- // This is intended to be short-lived. Hence, there's no intention other than that it is random and only used once - only the most recent one is valid.
 
 
 
 
 
220
  public function _get_autologin_key($user_id) {
221
  $secure_auth_key = defined('SECURE_AUTH_KEY') ? SECURE_AUTH_KEY : hash('sha256', DB_PASSWORD).'_'.rand(0, 999999999);
222
  if (!defined('SECURE_AUTH_KEY')) return false;
@@ -247,13 +248,18 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
247
  ));
248
  }
249
 
250
- //This calls the WP_Action within WP
 
 
 
 
 
251
  public function call_wordpress_action($data){
252
  if (false === ($updraftplus_admin = $this->_load_ud_admin())) return $this->_generic_error_response('no_updraftplus');
253
 
254
  $response = $updraftplus_admin->call_wp_action($data);
255
 
256
- if(empty($data["wpaction"])){
257
  return $this->_generic_error_response("error", "no command sent");
258
  }
259
 
@@ -275,22 +281,26 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
275
 
276
  /*Private Functions*/
277
 
278
- // https://secure.php.net/phpinfo
 
 
 
 
279
  private function _get_phpinfo_array() {
280
  ob_start();
281
  phpinfo(INFO_GENERAL|INFO_CREDITS|INFO_MODULES);
282
  $phpinfo = array('phpinfo' => array());
283
 
284
- if (preg_match_all('#(?:<h2>(?:<a name=".*?">)?(.*?)(?:</a>)?</h2>)|(?:<tr(?: class=".*?")?><t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>)?)?</tr>)#s', ob_get_clean(), $matches, PREG_SET_ORDER)){
285
- foreach($matches as $match){
286
- if(strlen($match[1])){
287
  $phpinfo[$match[1]] = array();
288
- }elseif(isset($match[3])){
289
  $keys1 = array_keys($phpinfo);
290
  $phpinfo[end($keys1)][$match[2]] = isset($match[4]) ? array($match[3], $match[4]) : $match[3];
291
  } else {
292
  $keys1 = array_keys($phpinfo);
293
- $phpinfo[end($keys1)][] = $match[2];
294
 
295
  }
296
 
@@ -302,7 +312,7 @@ class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
302
 
303
  private function _load_ud_admin() {
304
  if (!defined('UPDRAFTPLUS_DIR') || !is_file(UPDRAFTPLUS_DIR.'/admin.php')) return false;
305
- require_once(UPDRAFTPLUS_DIR.'/admin.php');
306
  global $updraftplus_admin;
307
  return $updraftplus_admin;
308
  }
2
 
3
  if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
 
5
+ /**
6
+ * - A container for RPC commands (core UpdraftCentral commands). Commands map exactly onto method names (and hence this class should not implement anything else, beyond the constructor, and private methods)
7
+ * - Return format is array('response' => (string - a code), 'data' => (mixed));
8
+ *
9
+ * RPC commands are not allowed to begin with an underscore. So, any private methods can be prefixed with an underscore.
10
+ */
 
 
11
  class UpdraftCentral_Core_Commands extends UpdraftCentral_Commands {
12
 
13
  /**
14
  * Validates the credentials entered by the user
15
  *
16
+ * @param array $creds an array of filesystem credentials
17
+ * @return array An array containing the result of the validation process.
 
 
18
  */
19
  public function validate_credentials($creds) {
20
 
35
  // template.php needed for submit_button() which is called by request_filesystem_credentials()
36
  $this->_admin_include('file.php', 'template.php');
37
 
38
+ // Directory entities that we currently need permissions
39
+ // to update.
40
  $entity_directories = array(
41
  'plugins' => WP_PLUGIN_DIR,
42
  'themes' => WP_CONTENT_DIR.'/themes',
46
  $url = wp_nonce_url(site_url());
47
  $directory = $entity_directories[$entity];
48
 
49
+ // Check if credentials are valid and have sufficient
50
+ // privileges to create and delete (e.g. write)
51
  $credentials = request_filesystem_credentials($url, '', false, $directory);
52
  if (WP_Filesystem($credentials, $directory)) {
53
 
65
  $result = array('error' => true, 'message' => 'failed_credentials', 'values' => array());
66
  }
67
 
68
+ } catch (Exception $e) {
69
  $result = array('error' => true, 'message' => $e->getMessage(), 'values' => array());
70
  }
71
 
75
  /**
76
  * Gets the FileSystem Credentials
77
  *
78
+ * Extract the needed filesystem credentials (permissions) to be used
79
  * to update/upgrade the plugins, themes and the WP core.
80
  *
81
  * @return array $result - An array containing the creds form and some flags
82
+ * to determine whether we need to extract the creds
83
  * manually from the user.
84
  */
85
  public function get_credentials() {
86
 
87
  try {
88
 
89
+ // Check whether user has enough permission to update entities
90
  if (!current_user_can('update_plugins') && !current_user_can('update_themes') && !current_user_can('update_core')) return $this->_generic_error_response('updates_permission_denied');
91
 
92
+ // Include the needed WP Core file(s)
93
  $this->_admin_include('file.php', 'template.php');
94
 
95
+ // A container that will hold the state (in this case, either true or false) of
96
+ // each directory entities (plugins, themes, core) that will be used to determine
97
+ // whether or not there's a need to show a form that will ask the user for their credentials
98
+ // manually.
99
  $request_filesystem_credentials = array();
100
 
101
+ // A container for the filesystem credentials form if applicable.
102
  $filesystem_form = '';
103
 
104
+ // Directory entities that we currently need permissions
105
+ // to update.
106
  $check_fs = array(
107
  'plugins' => WP_PLUGIN_DIR,
108
  'themes' => WP_CONTENT_DIR.'/themes',
109
  'core' => untrailingslashit(ABSPATH)
110
  );
111
 
112
+ // Here, we're looping through each entities and find output whether
113
+ // we have sufficient permissions to update objects belonging to them.
114
  foreach ($check_fs as $entity => $dir) {
115
 
116
+ // We're determining which method to use when updating
117
+ // the files in the filesystem.
118
  $filesystem_method = get_filesystem_method(array(), $dir);
119
 
120
+ // Buffering the output to pull the actual credentials form
121
+ // currently being used by this WP instance if no sufficient permissions
122
+ // is found.
123
  $url = wp_nonce_url(site_url());
124
 
125
  ob_start();
131
  }
132
  ob_end_clean();
133
 
134
+ // Save the state whether or not there's a need to show the
135
+ // credentials form to the user.
136
+ $request_filesystem_credentials[$entity] = ('direct' !== $filesystem_method && !$filesystem_credentials_are_stored);
137
  }
138
 
139
+ // Wrapping the credentials info before passing it back
140
+ // to the client issuing the request.
141
  $result = array(
142
  'request_filesystem_credentials' => $request_filesystem_credentials,
143
  'filesy