Akismet Anti-Spam - Version 4.0.1

Version Description

Release Date - 6 November 2017

  • Fixed a bug that could prevent some users from connecting Akismet via their Jetpack connection.
  • Ensured that any pending Akismet-related events are unscheduled if the plugin is deactivated.
  • Allow some JavaScript to be run asynchronously to avoid affecting page render speeds.
Download this release

Release Info

Developer cfinke
Plugin Icon 128x128 Akismet Anti-Spam
Version 4.0.1
Comparing to
See all releases

Code changes from version 4.0 to 4.0.1

Files changed (4) hide show
  1. akismet.php +2 -2
  2. class.akismet-admin.php +19 -5
  3. class.akismet.php +53 -13
  4. readme.txt +11 -4
akismet.php CHANGED
@@ -6,7 +6,7 @@
6
  Plugin Name: Akismet Anti-Spam
7
  Plugin URI: https://akismet.com/
8
  Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. It keeps your site protected even while you sleep. To get started: activate the Akismet plugin and then go to your Akismet Settings page to set up your API key.
9
- Version: 4.0
10
  Author: Automattic
11
  Author URI: https://automattic.com/wordpress-plugins/
12
  License: GPLv2 or later
@@ -37,7 +37,7 @@ if ( !function_exists( 'add_action' ) ) {
37
  exit;
38
  }
39
 
40
- define( 'AKISMET_VERSION', '4.0' );
41
  define( 'AKISMET__MINIMUM_WP_VERSION', '4.0' );
42
  define( 'AKISMET__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
43
  define( 'AKISMET_DELETE_LIMIT', 100000 );
6
  Plugin Name: Akismet Anti-Spam
7
  Plugin URI: https://akismet.com/
8
  Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. It keeps your site protected even while you sleep. To get started: activate the Akismet plugin and then go to your Akismet Settings page to set up your API key.
9
+ Version: 4.0.1
10
  Author: Automattic
11
  Author URI: https://automattic.com/wordpress-plugins/
12
  License: GPLv2 or later
37
  exit;
38
  }
39
 
40
+ define( 'AKISMET_VERSION', '4.0.1' );
41
  define( 'AKISMET__MINIMUM_WP_VERSION', '4.0' );
42
  define( 'AKISMET__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
43
  define( 'AKISMET_DELETE_LIMIT', 100000 );
class.akismet-admin.php CHANGED
@@ -92,10 +92,10 @@ class Akismet_Admin {
92
 
93
  public static function load_menu() {
94
  if ( class_exists( 'Jetpack' ) ) {
95
- $hook = add_submenu_page( 'jetpack', __( 'Akismet' , 'akismet'), __( 'Akismet' , 'akismet'), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ) );
96
  }
97
  else {
98
- $hook = add_options_page( __('Akismet', 'akismet'), __('Akismet', 'akismet'), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ) );
99
  }
100
 
101
  if ( $hook ) {
@@ -1061,8 +1061,22 @@ class Akismet_Admin {
1061
  if ( !$xml->isError() ) {
1062
  $responses = $xml->getResponse();
1063
  if ( count( $responses ) > 1 ) {
1064
- $api_key = array_shift( $responses[0] );
1065
- $user_id = (int) array_shift( $responses[1] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1066
  return compact( 'api_key', 'user_id' );
1067
  }
1068
  }
@@ -1100,4 +1114,4 @@ class Akismet_Admin {
1100
 
1101
  return $all_plugins;
1102
  }
1103
- }
92
 
93
  public static function load_menu() {
94
  if ( class_exists( 'Jetpack' ) ) {
95
+ $hook = add_submenu_page( 'jetpack', __( 'Akismet Anti-Spam' , 'akismet'), __( 'Akismet Anti-Spam' , 'akismet'), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ) );
96
  }
97
  else {
98
+ $hook = add_options_page( __('Akismet Anti-Spam', 'akismet'), __('Akismet Anti-Spam', 'akismet'), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ) );
99
  }
100
 
101
  if ( $hook ) {
1061
  if ( !$xml->isError() ) {
1062
  $responses = $xml->getResponse();
1063
  if ( count( $responses ) > 1 ) {
1064
+ // Due to a quirk in how Jetpack does multi-calls, the response order
1065
+ // can't be trusted to match the call order. It's a good thing our
1066
+ // return values can be mostly differentiated from each other.
1067
+ $first_response_value = array_shift( $responses[0] );
1068
+ $second_response_value = array_shift( $responses[1] );
1069
+
1070
+ // If WPCOM ever reaches 100 billion users, this will fail. :-)
1071
+ if ( preg_match( '/^[a-f0-9]{12}$/i', $first_response_value ) ) {
1072
+ $api_key = $first_response_value;
1073
+ $user_id = (int) $second_response_value;
1074
+ }
1075
+ else {
1076
+ $api_key = $second_response_value;
1077
+ $user_id = (int) $first_response_value;
1078
+ }
1079
+
1080
  return compact( 'api_key', 'user_id' );
1081
  }
1082
  }
1114
 
1115
  return $all_plugins;
1116
  }
1117
+ }
class.akismet.php CHANGED
@@ -37,6 +37,7 @@ class Akismet {
37
  add_action( 'admin_head-edit-comments.php', array( 'Akismet', 'load_form_js' ) );
38
  add_action( 'comment_form', array( 'Akismet', 'load_form_js' ) );
39
  add_action( 'comment_form', array( 'Akismet', 'inject_ak_js' ) );
 
40
 
41
  add_filter( 'comment_moderation_recipients', array( 'Akismet', 'disable_moderation_emails_if_unreachable' ), 1000, 2 );
42
  add_filter( 'pre_comment_approved', array( 'Akismet', 'last_comment_status' ), 10, 2 );
@@ -533,24 +534,36 @@ class Akismet {
533
  if ( get_comment_meta( $comment->comment_ID, 'akismet_rechecking' ) )
534
  return;
535
 
536
- global $current_user;
537
- $reporter = '';
538
- if ( is_object( $current_user ) )
539
- $reporter = $current_user->user_login;
540
-
541
  // Assumption alert:
542
  // We want to submit comments to Akismet only when a moderator explicitly spams or approves it - not if the status
543
  // is changed automatically by another plugin. Unfortunately WordPress doesn't provide an unambiguous way to
544
  // determine why the transition_comment_status action was triggered. And there are several different ways by which
545
  // to spam and unspam comments: bulk actions, ajax, links in moderation emails, the dashboard, and perhaps others.
546
  // We'll assume that this is an explicit user action if certain POST/GET variables exist.
547
- if ( ( isset( $_POST['status'] ) && in_array( $_POST['status'], array( 'spam', 'unspam' ) ) ) ||
548
- ( isset( $_POST['spam'] ) && (int) $_POST['spam'] == 1 ) ||
549
- ( isset( $_POST['unspam'] ) && (int) $_POST['unspam'] == 1 ) ||
550
- ( isset( $_POST['comment_status'] ) && in_array( $_POST['comment_status'], array( 'spam', 'unspam' ) ) ) ||
551
- ( isset( $_GET['action'] ) && in_array( $_GET['action'], array( 'spam', 'unspam', 'spamcomment', 'unspamcomment', ) ) ) ||
552
- ( isset( $_POST['action'] ) && in_array( $_POST['action'], array( 'editedcomment' ) ) ) ||
553
- ( isset( $_GET['for'] ) && ( 'jetpack' == $_GET['for'] ) ) // Moderation via WP.com notifications/WP app/etc.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  ) {
555
  if ( $new_status == 'spam' && ( $old_status == 'approved' || $old_status == 'unapproved' || !$old_status ) ) {
556
  return self::submit_spam_comment( $comment->comment_ID );
@@ -1104,6 +1117,19 @@ class Akismet {
1104
  wp_enqueue_script( 'akismet-form' );
1105
  }
1106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1107
  public static function inject_ak_js( $fields ) {
1108
  echo '<p style="display: none;">';
1109
  echo '<input type="hidden" id="ak_js" name="ak_js" value="' . mt_rand( 0, 250 ) . '"/>';
@@ -1184,7 +1210,21 @@ p {
1184
  * @static
1185
  */
1186
  public static function plugin_deactivation( ) {
1187
- return self::deactivate_key( self::get_api_key() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1188
  }
1189
 
1190
  /**
37
  add_action( 'admin_head-edit-comments.php', array( 'Akismet', 'load_form_js' ) );
38
  add_action( 'comment_form', array( 'Akismet', 'load_form_js' ) );
39
  add_action( 'comment_form', array( 'Akismet', 'inject_ak_js' ) );
40
+ add_filter( 'script_loader_tag', array( 'Akismet', 'set_form_js_async' ), 10, 3 );
41
 
42
  add_filter( 'comment_moderation_recipients', array( 'Akismet', 'disable_moderation_emails_if_unreachable' ), 1000, 2 );
43
  add_filter( 'pre_comment_approved', array( 'Akismet', 'last_comment_status' ), 10, 2 );
534
  if ( get_comment_meta( $comment->comment_ID, 'akismet_rechecking' ) )
535
  return;
536
 
 
 
 
 
 
537
  // Assumption alert:
538
  // We want to submit comments to Akismet only when a moderator explicitly spams or approves it - not if the status
539
  // is changed automatically by another plugin. Unfortunately WordPress doesn't provide an unambiguous way to
540
  // determine why the transition_comment_status action was triggered. And there are several different ways by which
541
  // to spam and unspam comments: bulk actions, ajax, links in moderation emails, the dashboard, and perhaps others.
542
  // We'll assume that this is an explicit user action if certain POST/GET variables exist.
543
+ if (
544
+ // status=spam: Marking as spam via the REST API or...
545
+ // status=unspam: I'm not sure. Maybe this used to be used instead of status=approved? Or the UI for removing from spam but not approving has been since removed?...
546
+ // status=approved: Unspamming via the REST API (Calypso) or...
547
+ ( isset( $_POST['status'] ) && in_array( $_POST['status'], array( 'spam', 'unspam', 'approved', ) ) )
548
+ // spam=1: Clicking "Spam" underneath a comment in wp-admin and allowing the AJAX request to happen.
549
+ || ( isset( $_POST['spam'] ) && (int) $_POST['spam'] == 1 )
550
+ // unspam=1: Clicking "Not Spam" underneath a comment in wp-admin and allowing the AJAX request to happen. Or, clicking "Undo" after marking something as spam.
551
+ || ( isset( $_POST['unspam'] ) && (int) $_POST['unspam'] == 1 )
552
+ // comment_status=spam/unspam: It's unclear where this is happening.
553
+ || ( isset( $_POST['comment_status'] ) && in_array( $_POST['comment_status'], array( 'spam', 'unspam' ) ) )
554
+ // action=spam: Choosing "Mark as Spam" from the Bulk Actions dropdown in wp-admin (or the "Spam it" link in notification emails).
555
+ // action=unspam: Choosing "Not Spam" from the Bulk Actions dropdown in wp-admin.
556
+ // action=spamcomment: Following the "Spam" link below a comment in wp-admin (not allowing AJAX request to happen).
557
+ // action=unspamcomment: Following the "Not Spam" link below a comment in wp-admin (not allowing AJAX request to happen).
558
+ || ( isset( $_GET['action'] ) && in_array( $_GET['action'], array( 'spam', 'unspam', 'spamcomment', 'unspamcomment', ) ) )
559
+ // action=editedcomment: Editing a comment via wp-admin (and possibly changing its status).
560
+ || ( isset( $_POST['action'] ) && in_array( $_POST['action'], array( 'editedcomment' ) ) )
561
+ // for=jetpack: Moderation via the WordPress app, Calypso, anything powered by the Jetpack connection.
562
+ || ( isset( $_GET['for'] ) && ( 'jetpack' == $_GET['for'] ) && ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) )
563
+ // Certain WordPress.com API requests
564
+ || ( defined( 'REST_API_REQUEST' ) && REST_API_REQUEST )
565
+ // WordPress.org REST API requests
566
+ || ( defined( 'REST_REQUEST' ) && REST_REQUEST )
567
  ) {
568
  if ( $new_status == 'spam' && ( $old_status == 'approved' || $old_status == 'unapproved' || !$old_status ) ) {
569
  return self::submit_spam_comment( $comment->comment_ID );
1117
  wp_enqueue_script( 'akismet-form' );
1118
  }
1119
 
1120
+ /**
1121
+ * Mark form.js as async. Because nothing depends on it, it can run at any time
1122
+ * after it's loaded, and the browser won't have to wait for it to load to continue
1123
+ * parsing the rest of the page.
1124
+ */
1125
+ public static function set_form_js_async( $tag, $handle, $src ) {
1126
+ if ( 'akismet-form' !== $handle ) {
1127
+ return $tag;
1128
+ }
1129
+
1130
+ return preg_replace( '/^<script /i', '<script async="async" ', $tag );
1131
+ }
1132
+
1133
  public static function inject_ak_js( $fields ) {
1134
  echo '<p style="display: none;">';
1135
  echo '<input type="hidden" id="ak_js" name="ak_js" value="' . mt_rand( 0, 250 ) . '"/>';
1210
  * @static
1211
  */
1212
  public static function plugin_deactivation( ) {
1213
+ self::deactivate_key( self::get_api_key() );
1214
+
1215
+ // Remove any scheduled cron jobs.
1216
+ $akismet_cron_events = array(
1217
+ 'akismet_schedule_cron_recheck',
1218
+ 'akismet_scheduled_delete',
1219
+ );
1220
+
1221
+ foreach ( $akismet_cron_events as $akismet_cron_event ) {
1222
+ $timestamp = wp_next_scheduled( $akismet_cron_event );
1223
+
1224
+ if ( $timestamp ) {
1225
+ wp_unschedule_event( $timestamp, $akismet_cron_event );
1226
+ }
1227
+ }
1228
  }
1229
 
1230
  /**
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
- === Akismet ===
2
- Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, cfinke, automattic, jgs
3
  Tags: akismet, comments, spam, antispam, anti-spam, anti spam, comment moderation, comment spam, contact form spam, spam comments
4
  Requires at least: 4.0
5
- Tested up to: 4.8.1
6
- Stable tag: 4.0
7
  License: GPLv2 or later
8
 
9
  Akismet checks your comments and contact form submissions against our global database of spam to protect you and your site from malicious content.
@@ -30,6 +30,13 @@ Upload the Akismet plugin to your blog, Activate it, then enter your [Akismet.co
30
 
31
  == Changelog ==
32
 
 
 
 
 
 
 
 
33
  = 4.0 =
34
  *Release Date - 19 September 2017*
35
 
1
+ === Akismet Anti-Spam ===
2
+ Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, cfinke, automattic, jgs, procifer
3
  Tags: akismet, comments, spam, antispam, anti-spam, anti spam, comment moderation, comment spam, contact form spam, spam comments
4
  Requires at least: 4.0
5
+ Tested up to: 4.9
6
+ Stable tag: 4.0.1
7
  License: GPLv2 or later
8
 
9
  Akismet checks your comments and contact form submissions against our global database of spam to protect you and your site from malicious content.
30
 
31
  == Changelog ==
32
 
33
+ = 4.0.1 =
34
+ *Release Date - 6 November 2017*
35
+
36
+ * Fixed a bug that could prevent some users from connecting Akismet via their Jetpack connection.
37
+ * Ensured that any pending Akismet-related events are unscheduled if the plugin is deactivated.
38
+ * Allow some JavaScript to be run asynchronously to avoid affecting page render speeds.
39
+
40
  = 4.0 =
41
  *Release Date - 19 September 2017*
42