WPBruiser {no- Captcha anti-Spam} - Version 3.1.3

Version Description

Improvements - Prevent oEmbed and WP Rest API user enumeration.

Download this release

Release Info

Developer mihche
Plugin Icon 128x128 WPBruiser {no- Captcha anti-Spam}
Version 3.1.3
Comparing to
See all releases

Code changes from version 3.1.1 to 3.1.3

engine/modules/brute-force/GdbcBruteForceAdminModule.php CHANGED
@@ -49,7 +49,7 @@ class GdbcBruteForceAdminModule extends GdbcBaseAdminModule
49
  'Id' => 2,
50
  'Value' => true,
51
  'LabelText' => __('Prevent User Enumeration', GoodByeCaptcha::PLUGIN_SLUG),
52
- 'Description' => __('Prevents bots from enumerating users by ID in order to find their real username', GoodByeCaptcha::PLUGIN_SLUG),
53
  'DisplayText' => __('UserEnumeration', GoodByeCaptcha::PLUGIN_SLUG),
54
  'InputType' => MchGdbcHtmlUtils::FORM_ELEMENT_INPUT_CHECKBOX
55
  ),
49
  'Id' => 2,
50
  'Value' => true,
51
  'LabelText' => __('Prevent User Enumeration', GoodByeCaptcha::PLUGIN_SLUG),
52
+ 'Description' => __('Prevents bots from enumerating users through \'/?author=N\' scans, the oEmbed API, and the WordPress REST API', GoodByeCaptcha::PLUGIN_SLUG),
53
  'DisplayText' => __('UserEnumeration', GoodByeCaptcha::PLUGIN_SLUG),
54
  'InputType' => MchGdbcHtmlUtils::FORM_ELEMENT_INPUT_CHECKBOX
55
  ),
engine/modules/brute-force/GdbcBruteForcePublicModule.php CHANGED
@@ -20,35 +20,89 @@
20
  class GdbcBruteForcePublicModule extends GdbcBasePublicModule
21
  {
22
  private $preventUserEnumHookIndex = null;
23
-
24
  protected function __construct()
25
  {
26
  parent::__construct();
27
-
28
  if($this->getOption(GdbcBruteForceAdminModule::OPTION_PREVENT_USER_ENUM))
29
  {
30
- $this->preventUserEnumHookIndex = $this->addActionHook('pre_get_posts', array($this, 'checkUserEnumeration'), 10, 1);
 
 
31
  }
32
-
33
  }
34
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  public function checkUserEnumeration($wpQuery)
36
  {
37
  if(!$wpQuery->is_main_query() || !$wpQuery->is_author() || empty($_REQUEST['author']) || !is_numeric($_REQUEST['author']))
38
  return;
39
-
40
  $wpQuery->set('author_name', '');
41
-
42
  $this->attemptEntity->SectionId = $this->getOptionIdByOptionName(GdbcBruteForceAdminModule::OPTION_PREVENT_USER_ENUM);
43
  $this->attemptEntity->Notes = array('authorid'=>absint($_REQUEST['author']));
44
  $this->attemptEntity->ReasonId = GdbcRequestController::REJECT_REASON_USER_ENUMERATION;
45
-
46
  GdbcBruteGuardian::logRejectedAttempt($this->attemptEntity);
47
-
48
  GdbcRequestController::redirectToHomePage();
49
  }
50
-
51
-
52
  /**
53
  * @return int
54
  */
@@ -56,11 +110,11 @@ class GdbcBruteForcePublicModule extends GdbcBasePublicModule
56
  {
57
  return GdbcModulesController::getModuleIdByName(GdbcModulesController::MODULE_BRUTE_FORCE);
58
  }
59
-
60
  public static function getInstance()
61
  {
62
  static $publicInstance = null;
63
  return null !== $publicInstance ? $publicInstance : $publicInstance = new self();
64
  }
65
-
66
  }
20
  class GdbcBruteForcePublicModule extends GdbcBasePublicModule
21
  {
22
  private $preventUserEnumHookIndex = null;
23
+
24
  protected function __construct()
25
  {
26
  parent::__construct();
27
+
28
  if($this->getOption(GdbcBruteForceAdminModule::OPTION_PREVENT_USER_ENUM))
29
  {
30
+ $this->addActionHook('pre_get_posts', array($this, 'checkUserEnumeration'), 10, 1);
31
+ $this->addFilterHook('oembed_response_data', array($this, 'checkoEmbedUserEnumeration'), 10, 1);
32
+ $this->addFilterHook('rest_request_before_callbacks', array($this, 'checkRestAPIUserEnumeration'), 10, 3);
33
  }
34
+
35
  }
36
+
37
+
38
+ public function checkRestAPIUserEnumeration($response, $handler, $request)
39
+ {
40
+ if(current_user_can('list_users') || !class_exists('WP_REST_Users_Controller'))
41
+ return $response;
42
+
43
+ $route = $request->get_route();
44
+
45
+ $restController = new WP_REST_Users_Controller();
46
+
47
+ $reflection = new ReflectionClass($restController);
48
+ $namespaceProperty = $reflection->getProperty('namespace');
49
+ $namespaceProperty->setAccessible(true);
50
+ $namespace = $namespaceProperty->getValue($restController);
51
+
52
+ $restBaseProperty = $reflection->getProperty('rest_base');
53
+ $restBaseProperty->setAccessible(true);
54
+ $restBase = $restBaseProperty->getValue($restController);
55
+
56
+ $urlBase = rtrim($namespace . '/' .$restBase, '/');
57
+
58
+ $error = null;
59
+ if (preg_match('~' . preg_quote($urlBase, '~') . '/*$~', $route)) {
60
+ $error = new WP_Error('rest_user_cannot_view', __('Sorry, you are not allowed to list users.'), array('status' => rest_authorization_required_code()));
61
+ $response = rest_ensure_response($error);
62
+ }
63
+ else if (preg_match('~' . preg_quote($urlBase, '~') . '/+(\d+)/*$~', $route, $matches)) {
64
+ $id = (int) $matches[1];
65
+ if (get_current_user_id() !== $id) {
66
+ $error = new WP_Error('rest_user_invalid_id', __('Invalid user ID.'), array('status' => 404));
67
+ $response = rest_ensure_response($error);
68
+ }
69
+ }
70
+
71
+ $this->attemptEntity->SectionId = $this->getOptionIdByOptionName(GdbcBruteForceAdminModule::OPTION_PREVENT_USER_ENUM);
72
+ $this->attemptEntity->ReasonId = GdbcRequestController::REJECT_REASON_USER_ENUMERATION;
73
+
74
+ if(null !== $error) {
75
+ GdbcBruteGuardian::logRejectedAttempt( $this->attemptEntity );
76
+ }
77
+
78
+ return $response;
79
+
80
+ }
81
+
82
+ public function checkoEmbedUserEnumeration($postInfo)
83
+ {
84
+ unset($postInfo['author_name']);
85
+ unset($postInfo['author_url']);
86
+ return $postInfo;
87
+ }
88
+
89
  public function checkUserEnumeration($wpQuery)
90
  {
91
  if(!$wpQuery->is_main_query() || !$wpQuery->is_author() || empty($_REQUEST['author']) || !is_numeric($_REQUEST['author']))
92
  return;
93
+
94
  $wpQuery->set('author_name', '');
95
+
96
  $this->attemptEntity->SectionId = $this->getOptionIdByOptionName(GdbcBruteForceAdminModule::OPTION_PREVENT_USER_ENUM);
97
  $this->attemptEntity->Notes = array('authorid'=>absint($_REQUEST['author']));
98
  $this->attemptEntity->ReasonId = GdbcRequestController::REJECT_REASON_USER_ENUMERATION;
99
+
100
  GdbcBruteGuardian::logRejectedAttempt($this->attemptEntity);
101
+
102
  GdbcRequestController::redirectToHomePage();
103
  }
104
+
105
+
106
  /**
107
  * @return int
108
  */
110
  {
111
  return GdbcModulesController::getModuleIdByName(GdbcModulesController::MODULE_BRUTE_FORCE);
112
  }
113
+
114
  public static function getInstance()
115
  {
116
  static $publicInstance = null;
117
  return null !== $publicInstance ? $publicInstance : $publicInstance = new self();
118
  }
119
+
120
  }
engine/modules/licenses/GdbcLicensesAdminModule.php CHANGED
@@ -23,7 +23,7 @@ class GdbcLicensesAdminModule extends GdbcBaseAdminModule
23
  {
24
  parent::__construct();
25
 
26
- add_filter('upgrader_package_options', array($this, 'setModuleDestinationFolders'));
27
  add_action( 'admin_init', array($this, 'checkForModuleUpdates'), 0 );
28
 
29
  }
23
  {
24
  parent::__construct();
25
 
26
+ //add_filter('upgrader_package_options', array($this, 'setModuleDestinationFolders'));
27
  add_action( 'admin_init', array($this, 'checkForModuleUpdates'), 0 );
28
 
29
  }
engine/modules/wordpress-tweaks/GdbcWordPressTweaksAdminModule.php CHANGED
@@ -98,7 +98,7 @@ class GdbcWordPressTweaksAdminModule extends GdbcBaseAdminModule
98
 
99
  self::WORDPRESS_COMMENTS_FORM_WEBSITE_FIELD => array(
100
  'Id' => 7,
101
- 'Value' => TRUE,
102
  'LabelText' => __('Hide Comments Website Field', GoodByeCaptcha::PLUGIN_SLUG),
103
  'Description' => __('Hides Comments Form Website Url', GoodByeCaptcha::PLUGIN_SLUG),
104
  'InputType' => MchGdbcHtmlUtils::FORM_ELEMENT_INPUT_CHECKBOX
98
 
99
  self::WORDPRESS_COMMENTS_FORM_WEBSITE_FIELD => array(
100
  'Id' => 7,
101
+ 'Value' => NULL,
102
  'LabelText' => __('Hide Comments Website Field', GoodByeCaptcha::PLUGIN_SLUG),
103
  'Description' => __('Hides Comments Form Website Url', GoodByeCaptcha::PLUGIN_SLUG),
104
  'InputType' => MchGdbcHtmlUtils::FORM_ELEMENT_INPUT_CHECKBOX
goodbye-captcha.php CHANGED
@@ -10,7 +10,7 @@
10
  * Plugin Name: WPBruiser
11
  * Plugin URI: http://www.wpbruiser.com
12
  * Description: An extremely powerful anti-spam plugin that blocks spambots without annoying captcha images.
13
- * Version: 3.1.1
14
  * Author: Mihai Chelaru
15
  * Author URI: http://www.wpbruiser.com
16
  * Text Domain: wp-bruiser
@@ -23,7 +23,7 @@ if(!class_exists('GoodByeCaptcha', false))
23
  {
24
  class GoodByeCaptcha
25
  {
26
- CONST PLUGIN_VERSION = '3.1.1';
27
  CONST PLUGIN_SLUG = 'wp-bruiser';
28
  CONST PLUGIN_NAME = 'WPBruiser';
29
  CONST PLUGIN_SITE_URL = 'http://www.wpbruiser.com';
10
  * Plugin Name: WPBruiser
11
  * Plugin URI: http://www.wpbruiser.com
12
  * Description: An extremely powerful anti-spam plugin that blocks spambots without annoying captcha images.
13
+ * Version: 3.1.3
14
  * Author: Mihai Chelaru
15
  * Author URI: http://www.wpbruiser.com
16
  * Text Domain: wp-bruiser
23
  {
24
  class GoodByeCaptcha
25
  {
26
+ CONST PLUGIN_VERSION = '3.1.3';
27
  CONST PLUGIN_SLUG = 'wp-bruiser';
28
  CONST PLUGIN_NAME = 'WPBruiser';
29
  CONST PLUGIN_SITE_URL = 'http://www.wpbruiser.com';
includes/plugin/MchGdbcPluginUpdater.php CHANGED
@@ -3,16 +3,19 @@
3
  * Allows plugins to use their own update API.
4
  *
5
  * @author Pippin Williamson
6
- * @version 1.6
7
  */
8
 
 
9
  class MchGdbcPluginUpdater
10
  {
11
- private $api_url = '';
12
- private $api_data = array();
13
- private $name = '';
14
- private $slug = '';
15
- private $version = '';
 
 
16
 
17
  /**
18
  * Class constructor.
@@ -24,16 +27,23 @@ class MchGdbcPluginUpdater
24
  * @param string $_plugin_file Path to the plugin file.
25
  * @param array $_api_data Optional data to send with API calls.
26
  */
27
- function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
28
- $this->api_url = trailingslashit( $_api_url );
29
- $this->api_data = $_api_data;
30
- $this->name = plugin_basename( $_plugin_file );
31
- $this->slug = basename( $_plugin_file, '.php' );
32
- $this->version = $_api_data['version'];
 
 
 
 
 
 
 
 
33
 
34
  // Set up hooks.
35
  $this->init();
36
- add_action( 'admin_init', array( $this, 'show_changelog' ) );
37
 
38
  }
39
 
@@ -45,11 +55,13 @@ class MchGdbcPluginUpdater
45
  * @return void
46
  */
47
  public function init() {
48
- add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
49
- add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
50
 
 
 
51
  remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10, 2 );
52
  add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
 
 
53
  }
54
 
55
  /**
@@ -65,37 +77,44 @@ class MchGdbcPluginUpdater
65
  * @param array $_transient_data Update array build by WordPress.
66
  * @return array Modified update array with custom plugin data.
67
  */
68
- function check_update( $_transient_data ) {
69
 
70
  global $pagenow;
71
 
72
- if( ! is_object( $_transient_data ) ) {
73
  $_transient_data = new stdClass;
74
  }
75
 
76
- if( 'plugins.php' == $pagenow && is_multisite() ) {
77
  return $_transient_data;
78
  }
79
 
80
- if ( empty( $_transient_data->response ) || empty( $_transient_data->response[ $this->name ] ) ) {
 
 
81
 
82
- $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
83
 
84
- if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
 
85
 
86
- if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
 
87
 
88
- $_transient_data->response[ $this->name ] = $version_info;
89
 
90
- }
91
 
92
- $_transient_data->last_checked = time();
93
- $_transient_data->checked[ $this->name ] = $this->version;
94
 
95
  }
96
 
 
 
 
97
  }
98
 
 
99
  return $_transient_data;
100
  }
101
 
@@ -107,6 +126,10 @@ class MchGdbcPluginUpdater
107
  */
108
  public function show_update_notification( $file, $plugin ) {
109
 
 
 
 
 
110
  if( ! current_user_can( 'update_plugins' ) ) {
111
  return;
112
  }
@@ -128,22 +151,19 @@ class MchGdbcPluginUpdater
128
 
129
  if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
130
 
131
- $cache_key = md5( 'edd_plugin_' .sanitize_key( $this->name ) . '_version_info' );
132
- $version_info = get_transient( $cache_key );
133
-
134
- if( false === $version_info ) {
135
 
 
136
  $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
137
 
138
- set_transient( $cache_key, $version_info, 3600 );
139
  }
140
 
141
-
142
- if( ! is_object( $version_info ) ) {
143
  return;
144
  }
145
 
146
- if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
147
 
148
  $update_cache->response[ $this->name ] = $version_info;
149
 
@@ -167,32 +187,39 @@ class MchGdbcPluginUpdater
167
 
168
  // build a plugin list row, with update notification
169
  $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
170
- echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
 
 
 
171
 
172
  $changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' );
173
 
174
  if ( empty( $version_info->download_link ) ) {
175
  printf(
176
- __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a>.', 'edd' ),
177
  esc_html( $version_info->name ),
178
- esc_url( $changelog_link ),
179
- esc_html( $version_info->new_version )
 
180
  );
181
  } else {
182
  printf(
183
- __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a> or <a href="%4$s">update now</a>.', 'edd' ),
184
  esc_html( $version_info->name ),
185
- esc_url( $changelog_link ),
186
  esc_html( $version_info->new_version ),
187
- esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) )
 
 
188
  );
189
  }
190
 
 
 
191
  echo '</div></td></tr>';
192
  }
193
  }
194
 
195
-
196
  /**
197
  * Updates information on the "View version x.x details" page with custom data.
198
  *
@@ -203,7 +230,7 @@ class MchGdbcPluginUpdater
203
  * @param object $_args
204
  * @return object $_data
205
  */
206
- function plugins_api_filter( $_data, $_action = '', $_args = null ) {
207
 
208
 
209
  if ( $_action != 'plugin_information' ) {
@@ -227,16 +254,28 @@ class MchGdbcPluginUpdater
227
  )
228
  );
229
 
230
- $api_response = $this->api_request( 'plugin_information', $to_send );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
 
232
- if ( false !== $api_response ) {
233
- $_data = $api_response;
234
  }
235
 
236
  return $_data;
237
  }
238
 
239
-
240
  /**
241
  * Disable SSL verification in order to prevent download update failures
242
  *
@@ -244,7 +283,7 @@ class MchGdbcPluginUpdater
244
  * @param string $url
245
  * @return object $array
246
  */
247
- function http_request_args( $args, $url ) {
248
  // If it is an https request and we are performing a package download, disable ssl verification
249
  if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
250
  $args['sslverify'] = false;
@@ -273,7 +312,7 @@ class MchGdbcPluginUpdater
273
  return;
274
  }
275
 
276
- if( $this->api_url == home_url() ) {
277
  return false; // Don't allow a plugin to ping itself
278
  }
279
 
@@ -283,8 +322,9 @@ class MchGdbcPluginUpdater
283
  'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
284
  'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
285
  'slug' => $data['slug'],
286
- 'author' => ! empty( $data['author'] ) ? $data['author'] : '',
287
- 'url' => home_url()
 
288
  );
289
 
290
  $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
@@ -304,6 +344,7 @@ class MchGdbcPluginUpdater
304
 
305
  public function show_changelog() {
306
 
 
307
 
308
  if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
309
  return;
@@ -318,15 +359,43 @@ class MchGdbcPluginUpdater
318
  }
319
 
320
  if( ! current_user_can( 'update_plugins' ) ) {
321
- wp_die( __( 'You do not have permission to install plugin updates', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
322
  }
323
 
324
- $response = $this->api_request( 'plugin_latest_version', array( 'slug' => $_REQUEST['slug'] ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
 
326
- if( $response && isset( $response->sections['changelog'] ) ) {
327
- echo '<div style="background:#fff;padding:10px;">' . $response->sections['changelog'] . '</div>';
328
  }
329
 
 
 
 
330
 
331
  exit;
332
  }
3
  * Allows plugins to use their own update API.
4
  *
5
  * @author Pippin Williamson
6
+ * @version 1.6.6
7
  */
8
 
9
+
10
  class MchGdbcPluginUpdater
11
  {
12
+ private $api_url = '';
13
+ private $api_data = array();
14
+ private $name = '';
15
+ private $slug = '';
16
+ private $version = '';
17
+ private $wp_override = false;
18
+ private $cache_key = '';
19
 
20
  /**
21
  * Class constructor.
27
  * @param string $_plugin_file Path to the plugin file.
28
  * @param array $_api_data Optional data to send with API calls.
29
  */
30
+ public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
31
+
32
+ global $edd_plugin_data;
33
+
34
+ $this->api_url = trailingslashit( $_api_url );
35
+ $this->api_data = $_api_data;
36
+ $this->name = plugin_basename( $_plugin_file );
37
+ $this->slug = basename( $_plugin_file, '.php' );
38
+ $this->version = $_api_data['version'];
39
+ $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
40
+
41
+ $this->cache_key = md5( serialize( $this->slug . $this->api_data['license'] ) );
42
+
43
+ $edd_plugin_data[ $this->slug ] = $this->api_data;
44
 
45
  // Set up hooks.
46
  $this->init();
 
47
 
48
  }
49
 
55
  * @return void
56
  */
57
  public function init() {
 
 
58
 
59
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
60
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
61
  remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10, 2 );
62
  add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
63
+ add_action( 'admin_init', array( $this, 'show_changelog' ) );
64
+
65
  }
66
 
67
  /**
77
  * @param array $_transient_data Update array build by WordPress.
78
  * @return array Modified update array with custom plugin data.
79
  */
80
+ public function check_update( $_transient_data ) {
81
 
82
  global $pagenow;
83
 
84
+ if ( ! is_object( $_transient_data ) ) {
85
  $_transient_data = new stdClass;
86
  }
87
 
88
+ if ( 'plugins.php' == $pagenow && is_multisite() ) {
89
  return $_transient_data;
90
  }
91
 
92
+ if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
93
+ return $_transient_data;
94
+ }
95
 
96
+ $version_info = get_transient( $this->cache_key );
97
 
98
+ if ( false === $version_info ) {
99
+ $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
100
 
101
+ set_transient( $this->cache_key, $version_info, 3600 );
102
+ }
103
 
104
+ if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
105
 
106
+ if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
107
 
108
+ $_transient_data->response[ $this->name ] = $version_info;
 
109
 
110
  }
111
 
112
+ $_transient_data->last_checked = time();
113
+ $_transient_data->checked[ $this->name ] = $this->version;
114
+
115
  }
116
 
117
+ //print_r($_transient_data);exit;
118
  return $_transient_data;
119
  }
120
 
126
  */
127
  public function show_update_notification( $file, $plugin ) {
128
 
129
+ if ( is_network_admin() ) {
130
+ return;
131
+ }
132
+
133
  if( ! current_user_can( 'update_plugins' ) ) {
134
  return;
135
  }
151
 
152
  if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
153
 
154
+ $version_info = get_transient( $this->cache_key );
 
 
 
155
 
156
+ if ( false === $version_info ) {
157
  $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
158
 
159
+ set_transient( $this->cache_key, $version_info, 3600 );
160
  }
161
 
162
+ if ( ! is_object( $version_info ) ) {
 
163
  return;
164
  }
165
 
166
+ if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
167
 
168
  $update_cache->response[ $this->name ] = $version_info;
169
 
187
 
188
  // build a plugin list row, with update notification
189
  $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
190
+ # <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange">
191
+ echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">';
192
+ echo '<td colspan="3" class="plugin-update colspanchange">';
193
+ echo '<div class="update-message notice inline notice-warning notice-alt">';
194
 
195
  $changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' );
196
 
197
  if ( empty( $version_info->download_link ) ) {
198
  printf(
199
+ __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'easy-digital-downloads' ),
200
  esc_html( $version_info->name ),
201
+ '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
202
+ esc_html( $version_info->new_version ),
203
+ '</a>'
204
  );
205
  } else {
206
  printf(
207
+ __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'easy-digital-downloads' ),
208
  esc_html( $version_info->name ),
209
+ '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
210
  esc_html( $version_info->new_version ),
211
+ '</a>',
212
+ '<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) .'">',
213
+ '</a>'
214
  );
215
  }
216
 
217
+ do_action( "in_plugin_update_message-{$file}", $plugin, $version_info );
218
+
219
  echo '</div></td></tr>';
220
  }
221
  }
222
 
 
223
  /**
224
  * Updates information on the "View version x.x details" page with custom data.
225
  *
230
  * @param object $_args
231
  * @return object $_data
232
  */
233
+ public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
234
 
235
 
236
  if ( $_action != 'plugin_information' ) {
254
  )
255
  );
256
 
257
+ $cache_key = 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data->license ) );
258
+
259
+ //Get the transient where we store the api request for this plugin for 24 hours
260
+ $edd_api_request_transient = get_site_transient( $cache_key );
261
+
262
+ //If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now.
263
+ if ( empty( $edd_api_request_transient ) ){
264
+
265
+ $api_response = $this->api_request( 'plugin_information', $to_send );
266
+
267
+ //Expires in 1 day
268
+ set_site_transient( $cache_key, $api_response, DAY_IN_SECONDS );
269
+
270
+ if ( false !== $api_response ) {
271
+ $_data = $api_response;
272
+ }
273
 
 
 
274
  }
275
 
276
  return $_data;
277
  }
278
 
 
279
  /**
280
  * Disable SSL verification in order to prevent download update failures
281
  *
283
  * @param string $url
284
  * @return object $array
285
  */
286
+ public function http_request_args( $args, $url ) {
287
  // If it is an https request and we are performing a package download, disable ssl verification
288
  if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
289
  $args['sslverify'] = false;
312
  return;
313
  }
314
 
315
+ if( $this->api_url == trailingslashit (home_url() ) ) {
316
  return false; // Don't allow a plugin to ping itself
317
  }
318
 
322
  'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
323
  'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
324
  'slug' => $data['slug'],
325
+ 'author' => isset($data['author']) ? $data['author'] : 'MihChe',
326
+ 'url' => home_url(),
327
+ 'beta' => isset( $data['beta'] ) ? $data['beta'] : false,
328
  );
329
 
330
  $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
344
 
345
  public function show_changelog() {
346
 
347
+ global $edd_plugin_data;
348
 
349
  if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
350
  return;
359
  }
360
 
361
  if( ! current_user_can( 'update_plugins' ) ) {
362
+ wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
363
  }
364
 
365
+ $data = $edd_plugin_data[ $_REQUEST['slug'] ];
366
+ $cache_key = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_version_info' );
367
+ $version_info = get_transient( $cache_key );
368
+
369
+ if( false === $version_info ) {
370
+
371
+ $api_params = array(
372
+ 'edd_action' => 'get_version',
373
+ 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
374
+ 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
375
+ 'slug' => $_REQUEST['slug'],
376
+ 'author' => isset($data['author']) ? $data['author'] : 'MihChe',
377
+ 'url' => home_url()
378
+ );
379
+
380
+ $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
381
+
382
+ if ( ! is_wp_error( $request ) ) {
383
+ $version_info = json_decode( wp_remote_retrieve_body( $request ) );
384
+ }
385
+
386
+ if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
387
+ $version_info->sections = maybe_unserialize( $version_info->sections );
388
+ } else {
389
+ $version_info = false;
390
+ }
391
+
392
+ set_transient( $cache_key, $version_info, 3600 );
393
 
 
 
394
  }
395
 
396
+ if( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) {
397
+ echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>';
398
+ }
399
 
400
  exit;
401
  }
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: mihche
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XVC3TSGEJQP2U
4
  Tags: captcha, antispam, anti-spam, spam, mailpoet, antispambot, brute force, comment spam, jetpack contact form, contact form 7, ninja forms, formidable forms, wp bruiser
5
  Requires at least: 3.5
6
- Tested up to: 4.6
7
- Stable tag: 3.1.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -218,10 +218,14 @@ Studies shown that visual CAPTCHAs take around 5-10 seconds to complete and audi
218
 
219
 
220
  == Upgrade Notice ==
221
- Compatibility with MailChimp for WP version 4.0.4 and up. For those having WPBruiser protecting subscription forms built using MailChimp for WP, this update is a must.
222
 
223
  == Changelog ==
224
 
 
 
 
 
225
  = 3.1.1 =
226
  **Fixes**
227
  - Compatibility with MailChimp for WP version 4.0.4 and up.
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XVC3TSGEJQP2U
4
  Tags: captcha, antispam, anti-spam, spam, mailpoet, antispambot, brute force, comment spam, jetpack contact form, contact form 7, ninja forms, formidable forms, wp bruiser
5
  Requires at least: 3.5
6
+ Tested up to: 4.7
7
+ Stable tag: 3.1.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
218
 
219
 
220
  == Upgrade Notice ==
221
+ Added protection for oEmbed and WP Rest API user enumeration.
222
 
223
  == Changelog ==
224
 
225
+ = 3.1.3 =
226
+ **Improvements**
227
+ - Prevent oEmbed and WP Rest API user enumeration.
228
+
229
  = 3.1.1 =
230
  **Fixes**
231
  - Compatibility with MailChimp for WP version 4.0.4 and up.