Akismet Anti-Spam - Version 2.6.0

Version Description

  • Add ajax paging to the check for spam button to handle large volumes of comments
  • Optimize javascript and add localization support
  • Fix bug in link to spam comments from right now dashboard widget
  • Fix bug with deleting old comments to avoid timeouts dealing with large volumes of comments
  • Include X-Pingback-Forwarded-For header in outbound WordPress pingback verifications
  • Add pre-check for pingbacks, to stop spam before an outbound verification request is made
Download this release

Release Info

Developer tellyworth
Plugin Icon 128x128 Akismet Anti-Spam
Version 2.6.0
Comparing to
See all releases

Code changes from version 2.5.9 to 2.6.0

Files changed (5) hide show
  1. admin.php +39 -21
  2. akismet.css +1 -1
  3. akismet.js +83 -50
  4. akismet.php +123 -36
  5. readme.txt +10 -2
admin.php CHANGED
@@ -39,13 +39,20 @@ function akismet_load_js_and_css() {
39
  'plugins_page_akismet-key-config',
40
  'jetpack_page_akismet-key-config',
41
  ) ) ) {
42
- wp_register_style( 'akismet.css', AKISMET_PLUGIN_URL . 'akismet.css', array(), '2.5.9' );
43
  wp_enqueue_style( 'akismet.css');
44
 
45
- wp_register_script( 'akismet.js', AKISMET_PLUGIN_URL . 'akismet.js', array('jquery'), '2.5.9' );
46
  wp_enqueue_script( 'akismet.js' );
47
  wp_localize_script( 'akismet.js', 'WPAkismet', array(
48
- 'comment_author_url_nonce' => wp_create_nonce( 'comment_author_url_nonce' )
 
 
 
 
 
 
 
49
  ) );
50
  }
51
  }
@@ -335,11 +342,7 @@ function akismet_stats() {
335
  $path = plugin_basename(__FILE__);
336
  echo '<h3>' . _x( 'Spam', 'comments' ) . '</h3>';
337
  global $submenu;
338
- if ( isset( $submenu['edit-comments.php'] ) )
339
- $link = 'edit-comments.php';
340
- else
341
- $link = 'edit.php';
342
- echo '<p>'.sprintf( _n( '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', $count ), 'http://akismet.com/?return=true', clean_url("$link?page=akismet-admin"), number_format_i18n($count) ).'</p>';
343
  }
344
  add_action('activity_box_end', 'akismet_stats');
345
 
@@ -546,11 +549,11 @@ function akismet_rightnow() {
546
  global $submenu, $wp_db_version;
547
 
548
  if ( 8645 < $wp_db_version ) // 2.7
549
- $link = 'edit-comments.php?comment_status=spam';
550
  elseif ( isset( $submenu['edit-comments.php'] ) )
551
- $link = 'edit-comments.php?page=akismet-admin';
552
  else
553
- $link = 'edit.php?page=akismet-admin';
554
 
555
  if ( $count = get_option('akismet_spam_count') ) {
556
  $intro = sprintf( _n(
@@ -581,14 +584,17 @@ add_action('rightnow_end', 'akismet_rightnow');
581
 
582
 
583
  // For WP >= 2.5
584
- function akismet_check_for_spam_button($comment_status) {
585
  if ( 'approved' == $comment_status )
586
  return;
 
587
  if ( function_exists('plugins_url') )
588
- $link = 'admin.php?action=akismet_recheck_queue';
589
  else
590
- $link = 'edit-comments.php?page=akismet-admin&amp;recheckqueue=true&amp;noheader=true';
591
- echo "</div><div class='alignleft'><a class='button-secondary checkforspam' href='$link'>" . __('Check for Spam') . "</a>";
 
 
592
  }
593
  add_action('manage_comments_nav', 'akismet_check_for_spam_button');
594
 
@@ -771,8 +777,12 @@ function akismet_recheck_queue() {
771
 
772
  if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
773
  return;
774
-
775
- $moderation = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = '0'", ARRAY_A );
 
 
 
 
776
  foreach ( (array) $moderation as $c ) {
777
  $c['user_ip'] = $c['comment_author_IP'];
778
  $c['user_agent'] = $c['comment_agent'];
@@ -780,7 +790,7 @@ function akismet_recheck_queue() {
780
  $c['blog'] = get_bloginfo('url');
781
  $c['blog_lang'] = get_locale();
782
  $c['blog_charset'] = get_option('blog_charset');
783
- $c['permalink'] = get_permalink($c['comment_post_ID']);
784
 
785
  $c['user_role'] = '';
786
  if ( isset( $c['user_ID'] ) )
@@ -815,12 +825,20 @@ function akismet_recheck_queue() {
815
 
816
  delete_comment_meta( $c['comment_ID'], 'akismet_rechecking' );
817
  }
818
- $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url( 'edit-comments.php' );
819
- wp_safe_redirect( $redirect_to );
820
- exit;
 
 
 
 
 
 
 
821
  }
822
 
823
  add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
 
824
 
825
  // Adds an 'x' link next to author URLs, clicking will remove the author URL and show an undo link
826
  function akismet_remove_comment_author_url() {
39
  'plugins_page_akismet-key-config',
40
  'jetpack_page_akismet-key-config',
41
  ) ) ) {
42
+ wp_register_style( 'akismet.css', AKISMET_PLUGIN_URL . 'akismet.css', array(), AKISMET_VERSION );
43
  wp_enqueue_style( 'akismet.css');
44
 
45
+ wp_register_script( 'akismet.js', AKISMET_PLUGIN_URL . 'akismet.js', array('jquery'), AKISMET_VERSION );
46
  wp_enqueue_script( 'akismet.js' );
47
  wp_localize_script( 'akismet.js', 'WPAkismet', array(
48
+ 'comment_author_url_nonce' => wp_create_nonce( 'comment_author_url_nonce' ),
49
+ 'strings' => array(
50
+ 'Remove this URL' => __( 'Remove this URL' ),
51
+ 'Removing...' => __( 'Removing...' ),
52
+ 'URL removed' => __( 'URL removed' ),
53
+ '(undo)' => __( '(undo)' ),
54
+ 'Re-adding...' => __( 'Re-adding...' ),
55
+ )
56
  ) );
57
  }
58
  }
342
  $path = plugin_basename(__FILE__);
343
  echo '<h3>' . _x( 'Spam', 'comments' ) . '</h3>';
344
  global $submenu;
345
+ echo '<p>'.sprintf( _n( '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', $count ), 'http://akismet.com/?return=true', esc_url( add_query_arg( array( 'page' => 'akismet-admin' ), admin_url( isset( $submenu['edit-comments.php'] ) ? 'edit-comments.php' : 'edit.php' ) ) ), number_format_i18n($count) ).'</p>';
 
 
 
 
346
  }
347
  add_action('activity_box_end', 'akismet_stats');
348
 
549
  global $submenu, $wp_db_version;
550
 
551
  if ( 8645 < $wp_db_version ) // 2.7
552
+ $link = add_query_arg( array( 'comment_status' => 'spam' ), admin_url( 'edit-comments.php' ) );
553
  elseif ( isset( $submenu['edit-comments.php'] ) )
554
+ $link = add_query_arg( array( 'page' => 'akismet-admin' ), admin_url( 'edit-comments.php' ) );
555
  else
556
+ $link = add_query_arg( array( 'page' => 'akismet-admin' ), admin_url( 'edit.php' ) );
557
 
558
  if ( $count = get_option('akismet_spam_count') ) {
559
  $intro = sprintf( _n(
584
 
585
 
586
  // For WP >= 2.5
587
+ function akismet_check_for_spam_button( $comment_status ) {
588
  if ( 'approved' == $comment_status )
589
  return;
590
+
591
  if ( function_exists('plugins_url') )
592
+ $link = add_query_arg( array( 'action' => 'akismet_recheck_queue' ), admin_url( 'admin.php' ) );
593
  else
594
+ $link = add_query_arg( array( 'page' => 'akismet-admin', 'recheckqueue' => 'true', 'noheader' => 'true' ), admin_url( 'edit-comments.php' ) );
595
+
596
+ echo '</div><div class="alignleft"><a class="button-secondary checkforspam" href="' . $link . '">' . esc_html__('Check for Spam') . '</a>';
597
+ echo '<img src="' . esc_url( admin_url( 'images/wpspin_light.gif' ) ) . '" class="checkforspam-spinner" />';
598
  }
599
  add_action('manage_comments_nav', 'akismet_check_for_spam_button');
600
 
777
 
778
  if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
779
  return;
780
+
781
+ $paginate = '';
782
+ if ( isset( $_POST['limit'] ) && isset( $_POST['offset'] ) ) {
783
+ $paginate = $wpdb->prepare( " LIMIT %d OFFSET %d", array( $_POST['limit'], $_POST['offset'] ) );
784
+ }
785
+ $moderation = $wpdb->get_results( "SELECT * FROM {$wpdb->comments} WHERE comment_approved = '0'{$paginate}", ARRAY_A );
786
  foreach ( (array) $moderation as $c ) {
787
  $c['user_ip'] = $c['comment_author_IP'];
788
  $c['user_agent'] = $c['comment_agent'];
790
  $c['blog'] = get_bloginfo('url');
791
  $c['blog_lang'] = get_locale();
792
  $c['blog_charset'] = get_option('blog_charset');
793
+ $c['permalink'] = get_permalink($c['comment_post_ID']);
794
 
795
  $c['user_role'] = '';
796
  if ( isset( $c['user_ID'] ) )
825
 
826
  delete_comment_meta( $c['comment_ID'], 'akismet_rechecking' );
827
  }
828
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
829
+ wp_send_json( array(
830
+ 'processed' => count((array) $moderation),
831
+ ));
832
+ }
833
+ else {
834
+ $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url( 'edit-comments.php' );
835
+ wp_safe_redirect( $redirect_to );
836
+ exit;
837
+ }
838
  }
839
 
840
  add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
841
+ add_action('wp_ajax_akismet_recheck_queue', 'akismet_recheck_queue');
842
 
843
  // Adds an 'x' link next to author URLs, clicking will remove the author URL and show an undo link
844
  function akismet_remove_comment_author_url() {
akismet.css CHANGED
@@ -1 +1 @@
1
- #submitted-on{position:relative}#the-comment-list .author .akismet-user-comment-count{display:inline}#the-comment-list .author a span{text-decoration:none;color:#999}#the-comment-list .remove_url{margin-left:3px;color:#999;padding:2px 3px 2px 0}#the-comment-list .remove_url:hover{color:#A7301F;font-weight:bold;padding:2px 2px 2px 0}#dashboard_recent_comments .akismet-status{display:none}.akismet-status{float:right}.akismet-status a{color:#AAA;font-style:italic}span.comment-link a{text-decoration:underline}span.comment-link:after{content:" "attr(title) " ";color:#aaa;text-decoration:none}.mshot-arrow{width:0;height:0;border-top:10px solid transparent;border-bottom:10px solid transparent;border-right:10px solid #5C5C5C;position:absolute;left:-6px;top:91px}.mshot-container{background:#5C5C5C;position:absolute;top:-94px;padding:7px;width:450px;height:338px;z-index:20000;-moz-border-radius:6px;border-radius:6px;-webkit-border-radius:6px}h2.ak-header{padding-left:38px;background:url('img/logo.png') no-repeat 0 9px;margin-bottom:14px;line-height:32px}.key-status{padding:0.4em 1em;color:#fff;font-weight:bold;text-align:center;-webkit-border-radius:3px;border-radius:3px;border-width:1px;border-style:solid;max-width:23.3em}input#key{width:25.3em !important}input#key.valid{border-color:#4F800D}input#key.invalid,input#key.failed{border-color:#888}.key-status.under-input{margin-top:-5px;padding-bottom:0px}.key-status.invalid,.key-status.failed{background-color:#888}.key-status.valid{background-color:#4F800D}.key-status.some{background-color:#993300}.key-status.empty{display:none}table.network-status th,table.network-status td{padding:0.4em;margin:0;text-align:center}table.network-status{border-color:#dfdfdf;border-width:0 0 1px 1px;border-style:solid;border-spacing:0;width:25.6em}table.network-status th,table.network-status td{border-color:#dfdfdf;border-width:1px 1px 0 0;border-style:solid;margin:0;border-spacing:0}table.network-status td.key-status{border-radius:0px;-webkit-border-radius:0px}
1
+ #submitted-on{position:relative}#the-comment-list .author .akismet-user-comment-count{display:inline}#the-comment-list .author a span{text-decoration:none;color:#999}#the-comment-list .remove_url{margin-left:3px;color:#999;padding:2px 3px 2px 0}#the-comment-list .remove_url:hover{color:#A7301F;font-weight:bold;padding:2px 2px 2px 0}#dashboard_recent_comments .akismet-status{display:none}.akismet-status{float:right}.akismet-status a{color:#AAA;font-style:italic}span.comment-link a{text-decoration:underline}span.comment-link:after{content:" "attr(title) " ";color:#aaa;text-decoration:none}.mshot-arrow{width:0;height:0;border-top:10px solid transparent;border-bottom:10px solid transparent;border-right:10px solid #5C5C5C;position:absolute;left:-6px;top:91px}.mshot-container{background:#5C5C5C;position:absolute;top:-94px;padding:7px;width:450px;height:338px;z-index:20000;-moz-border-radius:6px;border-radius:6px;-webkit-border-radius:6px}h2.ak-header{padding-left:38px;background:url('img/logo.png') no-repeat 0 9px;margin-bottom:14px;line-height:32px}.key-status{padding:0.4em 1em;color:#fff;font-weight:bold;text-align:center;-webkit-border-radius:3px;border-radius:3px;border-width:1px;border-style:solid;max-width:23.3em}input#key{width:25.3em !important}input#key.valid{border-color:#4F800D}input#key.invalid,input#key.failed{border-color:#888}.key-status.under-input{margin-top:-5px;padding-bottom:0px}.key-status.invalid,.key-status.failed{background-color:#888}.key-status.valid{background-color:#4F800D}.key-status.some{background-color:#993300}.key-status.empty{display:none}table.network-status th,table.network-status td{padding:0.4em;margin:0;text-align:center}table.network-status{border-color:#dfdfdf;border-width:0 0 1px 1px;border-style:solid;border-spacing:0;width:25.6em}table.network-status th,table.network-status td{border-color:#dfdfdf;border-width:1px 1px 0 0;border-style:solid;margin:0;border-spacing:0}table.network-status td.key-status{border-radius:0px;-webkit-border-radius:0px}.checkforspam{display:inline-block !important;}.checkforspam-spinner{display:none;margin-top:10px;}
akismet.js CHANGED
@@ -1,114 +1,154 @@
1
- jQuery(document).ready(function () {
2
- jQuery( '.switch-have-key' ).click( function() {
3
- var no_key = jQuery( this ).parents().find('div.no-key');
4
- var have_key = jQuery( this ).parents().find('div.have-key');
5
 
6
  no_key.addClass( 'hidden' );
7
  have_key.removeClass( 'hidden' );
8
 
9
  return false;
10
  });
11
- jQuery( 'p.need-key a' ).click( function(){
12
  document.akismet_activate.submit();
13
  });
14
- jQuery('.akismet-status').each(function () {
15
- var thisId = jQuery(this).attr('commentid');
16
- jQuery(this).prependTo('#comment-' + thisId + ' .column-comment div:first-child');
17
  });
18
- jQuery('.akismet-user-comment-count').each(function () {
19
- var thisId = jQuery(this).attr('commentid');
20
- jQuery(this).insertAfter('#comment-' + thisId + ' .author strong:first').show();
21
  });
22
- jQuery('#the-comment-list tr.comment .column-author a[title ^= "http://"]').each(function () {
23
- var thisTitle = jQuery(this).attr('title');
24
- thisCommentId = jQuery(this).parents('tr:first').attr('id').split("-");
25
 
26
- jQuery(this).attr("id", "author_comment_url_"+ thisCommentId[1]);
27
 
28
  if (thisTitle) {
29
- jQuery(this).after(' <a href="#" class="remove_url" commentid="'+ thisCommentId[1] +'" title="Remove this URL">x</a>');
 
 
 
 
30
  }
31
  });
32
- jQuery('.remove_url').live('click', function () {
33
- var thisId = jQuery(this).attr('commentid');
34
  var data = {
35
  action: 'comment_author_deurl',
36
  _wpnonce: WPAkismet.comment_author_url_nonce,
37
  id: thisId
38
  };
39
- jQuery.ajax({
40
  url: ajaxurl,
41
  type: 'POST',
42
  data: data,
43
  beforeSend: function () {
44
  // Removes "x" link
45
- jQuery("a[commentid='"+ thisId +"']").hide();
46
  // Show temp status
47
- jQuery("#author_comment_url_"+ thisId).html('<span>Removing...</span>');
48
  },
49
  success: function (response) {
50
  if (response) {
51
  // Show status/undo link
52
- jQuery("#author_comment_url_"+ thisId).attr('cid', thisId).addClass('akismet_undo_link_removal').html('<span>URL removed (</span>undo<span>)</span>');
53
- }
 
 
 
 
 
 
 
 
 
 
 
54
  }
55
  });
56
 
57
  return false;
58
  });
59
- jQuery('.akismet_undo_link_removal').live('click', function () {
60
- var thisId = jQuery(this).attr('cid');
61
- var thisUrl = jQuery(this).attr('href').replace("http://www.", "").replace("http://", "");
62
  var data = {
63
  action: 'comment_author_reurl',
64
  _wpnonce: WPAkismet.comment_author_url_nonce,
65
  id: thisId,
66
  url: thisUrl
67
  };
68
- jQuery.ajax({
69
  url: ajaxurl,
70
  type: 'POST',
71
  data: data,
72
  beforeSend: function () {
73
  // Show temp status
74
- jQuery("#author_comment_url_"+ thisId).html('<span>Re-adding…</span>');
75
  },
76
  success: function (response) {
77
  if (response) {
78
  // Add "x" link
79
- jQuery("a[commentid='"+ thisId +"']").show();
80
  // Show link
81
- jQuery("#author_comment_url_"+ thisId).removeClass('akismet_undo_link_removal').html(thisUrl);
82
  }
83
  }
84
  });
85
 
86
  return false;
87
  });
88
- jQuery('a[id^="author_comment_url"]').mouseover(function () {
89
  var wpcomProtocol = ( 'https:' === location.protocol ) ? 'https://' : 'http://';
90
  // Need to determine size of author column
91
- var thisParentWidth = jQuery(this).parent().width();
92
  // It changes based on if there is a gravatar present
93
- thisParentWidth = (jQuery(this).parent().find('.grav-hijack').length) ? thisParentWidth - 42 + 'px' : thisParentWidth + 'px';
94
- if (jQuery(this).find('.mShot').length == 0 && !jQuery(this).hasClass('akismet_undo_link_removal')) {
95
- var thisId = jQuery(this).attr('id').replace('author_comment_url_', '');
96
- jQuery('.widefat td').css('overflow', 'visible');
97
- jQuery(this).css('position', 'relative');
98
- var thisHref = jQuery.URLEncode(jQuery(this).attr('href'));
99
- jQuery(this).append('<div class="mShot mshot-container" style="left: '+thisParentWidth+'"><div class="mshot-arrow"></div><img src="'+wpcomProtocol+'s0.wordpress.com/mshots/v1/'+thisHref+'?w=450" width="450" class="mshot-image_'+thisId+'" style="margin: 0;" /></div>');
100
  setTimeout(function () {
101
- jQuery('.mshot-image_'+thisId).attr('src', wpcomProtocol+'s0.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=2');
102
  }, 6000);
103
  setTimeout(function () {
104
- jQuery('.mshot-image_'+thisId).attr('src', wpcomProtocol+'s0.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=3');
105
  }, 12000);
106
  } else {
107
- jQuery(this).find('.mShot').css('left', thisParentWidth).show();
108
  }
109
  }).mouseout(function () {
110
- jQuery(this).find('.mShot').hide();
111
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  });
113
  // URL encode plugin
114
  jQuery.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a-zA-Z0-9_.]*)/;
@@ -117,10 +157,3 @@ jQuery.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a
117
  }else{if(c[x]==' ')o+='+';else{var d=c.charCodeAt(x);var h=d.toString(16);
118
  o+='%'+(h.length<2?'0':'')+h.toUpperCase();}x++;}}return o;}
119
  });
120
- // Preload mshot images after everything else has loaded
121
- jQuery(window).load(function() {
122
- var wpcomProtocol = ( 'https:' === location.protocol ) ? 'https://' : 'http://';
123
- jQuery('a[id^="author_comment_url"]').each(function () {
124
- jQuery.get(wpcomProtocol+'s0.wordpress.com/mshots/v1/'+jQuery.URLEncode(jQuery(this).attr('href'))+'?w=450');
125
- });
126
- });
1
+ jQuery( function ( $ ) {
2
+ $( '.switch-have-key' ).click( function() {
3
+ var no_key = $( this ).parents().find('div.no-key');
4
+ var have_key = $( this ).parents().find('div.have-key');
5
 
6
  no_key.addClass( 'hidden' );
7
  have_key.removeClass( 'hidden' );
8
 
9
  return false;
10
  });
11
+ $( 'p.need-key a' ).click( function(){
12
  document.akismet_activate.submit();
13
  });
14
+ $('.akismet-status').each(function () {
15
+ var thisId = $(this).attr('commentid');
16
+ $(this).prependTo('#comment-' + thisId + ' .column-comment div:first-child');
17
  });
18
+ $('.akismet-user-comment-count').each(function () {
19
+ var thisId = $(this).attr('commentid');
20
+ $(this).insertAfter('#comment-' + thisId + ' .author strong:first').show();
21
  });
22
+ $('#the-comment-list').find('tr.comment, tr[id ^= "comment-"]').find('.column-author a[title ^= "http://"]').each(function () {
23
+ var thisTitle = $(this).attr('title');
24
+ thisCommentId = $(this).parents('tr:first').attr('id').split("-");
25
 
26
+ $(this).attr("id", "author_comment_url_"+ thisCommentId[1]);
27
 
28
  if (thisTitle) {
29
+ $(this).after(
30
+ $( '<a href="#" class="remove_url">x</a>' )
31
+ .attr( 'commentid', thisCommentId[1] )
32
+ .attr( 'title', WPAkismet.strings['Remove this URL'] )
33
+ );
34
  }
35
  });
36
+ $('.remove_url').live('click', function () {
37
+ var thisId = $(this).attr('commentid');
38
  var data = {
39
  action: 'comment_author_deurl',
40
  _wpnonce: WPAkismet.comment_author_url_nonce,
41
  id: thisId
42
  };
43
+ $.ajax({
44
  url: ajaxurl,
45
  type: 'POST',
46
  data: data,
47
  beforeSend: function () {
48
  // Removes "x" link
49
+ $("a[commentid='"+ thisId +"']").hide();
50
  // Show temp status
51
+ $("#author_comment_url_"+ thisId).html( $( '<span/>' ).text( WPAkismet.strings['Removing...'] ) );
52
  },
53
  success: function (response) {
54
  if (response) {
55
  // Show status/undo link
56
+ $("#author_comment_url_"+ thisId)
57
+ .attr('cid', thisId)
58
+ .addClass('akismet_undo_link_removal')
59
+ .html(
60
+ $( '<span/>' ).text( WPAkismet.strings['URL removed'] )
61
+ )
62
+ .append( ' ' )
63
+ .append(
64
+ $( '<span/>' )
65
+ .text( WPAkismet.strings['(undo)'] )
66
+ .addClass( 'akismet-span-link' )
67
+ );
68
+ }
69
  }
70
  });
71
 
72
  return false;
73
  });
74
+ $('.akismet_undo_link_removal').live('click', function () {
75
+ var thisId = $(this).attr('cid');
76
+ var thisUrl = $(this).attr('href').replace("http://www.", "").replace("http://", "");
77
  var data = {
78
  action: 'comment_author_reurl',
79
  _wpnonce: WPAkismet.comment_author_url_nonce,
80
  id: thisId,
81
  url: thisUrl
82
  };
83
+ $.ajax({
84
  url: ajaxurl,
85
  type: 'POST',
86
  data: data,
87
  beforeSend: function () {
88
  // Show temp status
89
+ $("#author_comment_url_"+ thisId).html( $( '<span/>' ).text( WPAkismet.strings['Re-adding...'] ) );
90
  },
91
  success: function (response) {
92
  if (response) {
93
  // Add "x" link
94
+ $("a[commentid='"+ thisId +"']").show();
95
  // Show link
96
+ $("#author_comment_url_"+ thisId).removeClass('akismet_undo_link_removal').html(thisUrl);
97
  }
98
  }
99
  });
100
 
101
  return false;
102
  });
103
+ $('a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type').mouseover(function () {
104
  var wpcomProtocol = ( 'https:' === location.protocol ) ? 'https://' : 'http://';
105
  // Need to determine size of author column
106
+ var thisParentWidth = $(this).parent().width();
107
  // It changes based on if there is a gravatar present
108
+ thisParentWidth = ($(this).parent().find('.grav-hijack').length) ? thisParentWidth - 42 + 'px' : thisParentWidth + 'px';
109
+ if ($(this).find('.mShot').length == 0 && !$(this).hasClass('akismet_undo_link_removal')) {
110
+ var self = $( this );
111
+ $('.widefat td').css('overflow', 'visible');
112
+ $(this).css('position', 'relative');
113
+ var thisHref = $.URLEncode( $(this).attr('href') );
114
+ $(this).append('<div class="mShot mshot-container" style="left: '+thisParentWidth+'"><div class="mshot-arrow"></div><img src="//s0.wordpress.com/mshots/v1/'+thisHref+'?w=450" width="450" class="mshot-image" style="margin: 0;" /></div>');
115
  setTimeout(function () {
116
+ self.find( '.mshot-image' ).attr('src', '//s0.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=2');
117
  }, 6000);
118
  setTimeout(function () {
119
+ self.find( '.mshot-image' ).attr('src', '//s0.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=3');
120
  }, 12000);
121
  } else {
122
+ $(this).find('.mShot').css('left', thisParentWidth).show();
123
  }
124
  }).mouseout(function () {
125
+ $(this).find('.mShot').hide();
126
  });
127
+ $('.checkforspam:not(.button-disabled)').click( function(e) {
128
+ $('.checkforspam:not(.button-disabled)').addClass('button-disabled');
129
+ $('.checkforspam-spinner').show();
130
+ akismet_check_for_spam(0, 100);
131
+ e.preventDefault();
132
+ });
133
+
134
+ function akismet_check_for_spam(offset, limit) {
135
+ $.post(
136
+ ajaxurl,
137
+ {
138
+ 'action': 'akismet_recheck_queue',
139
+ 'offset': offset,
140
+ 'limit': limit
141
+ },
142
+ function(result) {
143
+ if (result.processed < limit) {
144
+ window.location.reload();
145
+ }
146
+ else {
147
+ akismet_check_for_spam(offset + limit, limit);
148
+ }
149
+ }
150
+ );
151
+ }
152
  });
153
  // URL encode plugin
154
  jQuery.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a-zA-Z0-9_.]*)/;
157
  }else{if(c[x]==' ')o+='+';else{var d=c.charCodeAt(x);var h=d.toString(16);
158
  o+='%'+(h.length<2?'0':'')+h.toUpperCase();}x++;}}return o;}
159
  });
 
 
 
 
 
 
 
akismet.php CHANGED
@@ -6,7 +6,7 @@
6
  Plugin Name: Akismet
7
  Plugin URI: http://akismet.com/?return=true
8
  Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from comment and trackback spam</strong>. It keeps your site protected from spam even while you sleep. To get started: 1) Click the "Activate" link to the left of this description, 2) <a href="http://akismet.com/get/?return=true">Sign up for an Akismet API key</a>, and 3) Go to your Akismet configuration page, and save your API key.
9
- Version: 2.5.9
10
  Author: Automattic
11
  Author URI: http://automattic.com/wordpress-plugins/
12
  License: GPLv2 or later
@@ -34,8 +34,9 @@ if ( !function_exists( 'add_action' ) ) {
34
  exit;
35
  }
36
 
37
- define('AKISMET_VERSION', '2.5.9');
38
  define('AKISMET_PLUGIN_URL', plugin_dir_url( __FILE__ ));
 
39
 
40
  /** If you hardcode a WP.com API key here, all key config screens will be hidden */
41
  if ( defined('WPCOM_API_KEY') )
@@ -197,17 +198,26 @@ function akismet_http_post($request, $host, $path, $port = 80, $ip=null) {
197
 
198
  // filter handler used to return a spam result to pre_comment_approved
199
  function akismet_result_spam( $approved ) {
 
 
 
 
200
  // bump the counter here instead of when the filter is added to reduce the possibility of overcounting
201
  if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
202
  update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
 
203
  // this is a one-shot deal
204
- remove_filter( 'pre_comment_approved', 'akismet_result_spam' );
205
  return 'spam';
206
  }
207
 
208
  function akismet_result_hold( $approved ) {
 
 
 
 
209
  // once only
210
- remove_filter( 'pre_comment_approved', 'akismet_result_hold' );
211
  return '0';
212
  }
213
 
@@ -321,7 +331,7 @@ function akismet_auto_check_comment( $commentdata ) {
321
  global $akismet_api_host, $akismet_api_port, $akismet_last_comment;
322
 
323
  $comment = $commentdata;
324
- $comment['user_ip'] = $_SERVER['REMOTE_ADDR'];
325
  $comment['user_agent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
326
  $comment['referrer'] = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
327
  $comment['blog'] = get_option('home');
@@ -422,58 +432,70 @@ function akismet_auto_check_comment( $commentdata ) {
422
 
423
  add_action('preprocess_comment', 'akismet_auto_check_comment', 1);
424
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
  function akismet_delete_old() {
426
  global $wpdb;
427
- $now_gmt = current_time('mysql', 1);
428
- $comment_ids = $wpdb->get_col("SELECT comment_id FROM $wpdb->comments WHERE DATE_SUB('$now_gmt', INTERVAL 15 DAY) > comment_date_gmt AND comment_approved = 'spam'");
429
- if ( empty( $comment_ids ) )
430
- return;
431
 
432
- $comma_comment_ids = implode( ', ', array_map('intval', $comment_ids) );
433
 
434
- do_action( 'delete_comment', $comment_ids );
435
- $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_id IN ( $comma_comment_ids )");
436
- $wpdb->query("DELETE FROM $wpdb->commentmeta WHERE comment_id IN ( $comma_comment_ids )");
437
- clean_comment_cache( $comment_ids );
438
- $n = mt_rand(1, 5000);
439
- if ( apply_filters('akismet_optimize_table', ($n == 11)) ) // lucky number
440
- $wpdb->query("OPTIMIZE TABLE $wpdb->comments");
 
 
441
 
 
 
442
  }
443
 
444
  function akismet_delete_old_metadata() {
445
  global $wpdb;
446
 
447
- $now_gmt = current_time( 'mysql', 1 );
448
  $interval = apply_filters( 'akismet_delete_commentmeta_interval', 15 );
449
 
450
  # enfore a minimum of 1 day
451
  $interval = absint( $interval );
452
- if ( $interval < 1 ) {
453
- return;
454
- }
455
 
456
  // akismet_as_submitted meta values are large, so expire them
457
  // after $interval days regardless of the comment status
458
- while ( TRUE ) {
459
- $comment_ids = $wpdb->get_col( "SELECT $wpdb->comments.comment_id FROM $wpdb->commentmeta INNER JOIN $wpdb->comments USING(comment_id) WHERE meta_key = 'akismet_as_submitted' AND DATE_SUB('$now_gmt', INTERVAL {$interval} DAY) > comment_date_gmt LIMIT 10000" );
460
-
461
- if ( empty( $comment_ids ) ) {
462
- return;
463
- }
464
-
465
  foreach ( $comment_ids as $comment_id ) {
466
  delete_comment_meta( $comment_id, 'akismet_as_submitted' );
467
  }
468
  }
469
-
470
- /*
471
- $n = mt_rand( 1, 5000 );
472
- if ( apply_filters( 'akismet_optimize_table', ( $n == 11 ), 'commentmeta' ) ) { // lucky number
473
- $wpdb->query( "OPTIMIZE TABLE $wpdb->commentmeta" );
474
- }
475
- */
476
- }
477
 
478
  add_action('akismet_scheduled_delete', 'akismet_delete_old');
479
  add_action('akismet_scheduled_delete', 'akismet_delete_old_metadata');
@@ -588,6 +610,71 @@ $akismet_comment_nonce_option = apply_filters( 'akismet_comment_nonce', get_opti
588
  if ( $akismet_comment_nonce_option == 'true' || $akismet_comment_nonce_option == '' )
589
  add_action( 'comment_form', 'akismet_add_comment_nonce' );
590
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
591
  global $wp_version;
592
  if ( '3.0.5' == $wp_version ) {
593
  remove_filter( 'comment_text', 'wp_kses_data' );
6
  Plugin Name: Akismet
7
  Plugin URI: http://akismet.com/?return=true
8
  Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from comment and trackback spam</strong>. It keeps your site protected from spam even while you sleep. To get started: 1) Click the "Activate" link to the left of this description, 2) <a href="http://akismet.com/get/?return=true">Sign up for an Akismet API key</a>, and 3) Go to your Akismet configuration page, and save your API key.
9
+ Version: 2.6.0
10
  Author: Automattic
11
  Author URI: http://automattic.com/wordpress-plugins/
12
  License: GPLv2 or later
34
  exit;
35
  }
36
 
37
+ define('AKISMET_VERSION', '2.6.0');
38
  define('AKISMET_PLUGIN_URL', plugin_dir_url( __FILE__ ));
39
+ define('AKISMET_DELETE_LIMIT', 10000);
40
 
41
  /** If you hardcode a WP.com API key here, all key config screens will be hidden */
42
  if ( defined('WPCOM_API_KEY') )
198
 
199
  // filter handler used to return a spam result to pre_comment_approved
200
  function akismet_result_spam( $approved ) {
201
+ static $just_once = false;
202
+ if ( $just_once )
203
+ return $approved;
204
+
205
  // bump the counter here instead of when the filter is added to reduce the possibility of overcounting
206
  if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
207
  update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
208
+
209
  // this is a one-shot deal
210
+ $just_once = true;
211
  return 'spam';
212
  }
213
 
214
  function akismet_result_hold( $approved ) {
215
+ static $just_once = false;
216
+ if ( $just_once )
217
+ return $approved;
218
+
219
  // once only
220
+ $just_once = true;
221
  return '0';
222
  }
223
 
331
  global $akismet_api_host, $akismet_api_port, $akismet_last_comment;
332
 
333
  $comment = $commentdata;
334
+ $comment['user_ip'] = akismet_get_ip_address();
335
  $comment['user_agent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
336
  $comment['referrer'] = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
337
  $comment['blog'] = get_option('home');
432
 
433
  add_action('preprocess_comment', 'akismet_auto_check_comment', 1);
434
 
435
+ function akismet_get_ip_address() {
436
+ foreach( array( 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR' ) as $key ) {
437
+ if ( array_key_exists( $key, $_SERVER ) === true ) {
438
+ foreach ( explode( ',', $_SERVER[$key] ) as $ip ) {
439
+ $ip = trim($ip);
440
+
441
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false ) {
442
+ return $ip;
443
+ }
444
+ }
445
+ }
446
+ }
447
+ return null;
448
+ }
449
+
450
  function akismet_delete_old() {
451
  global $wpdb;
452
+
453
+ while( $comment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT comment_id FROM {$wpdb->comments} WHERE DATE_SUB(NOW(), INTERVAL 15 DAY) > comment_date_gmt AND comment_approved = 'spam' LIMIT %d", defined( 'AKISMET_DELETE_LIMIT' ) ? AKISMET_DELETE_LIMIT : 10000 ) ) ) {
454
+ if ( empty( $comment_ids ) )
455
+ return;
456
 
457
+ $wpdb->queries = array();
458
 
459
+ do_action( 'delete_comment', $comment_ids );
460
+
461
+ $comma_comment_ids = implode( ', ', array_map('intval', $comment_ids) );
462
+
463
+ $wpdb->query("DELETE FROM {$wpdb->comments} WHERE comment_id IN ( $comma_comment_ids )");
464
+ $wpdb->query("DELETE FROM {$wpdb->commentmeta} WHERE comment_id IN ( $comma_comment_ids )");
465
+
466
+ clean_comment_cache( $comment_ids );
467
+ }
468
 
469
+ if ( apply_filters( 'akismet_optimize_table', ( mt_rand(1, 5000) == 11) ) ) // lucky number
470
+ $wpdb->query("OPTIMIZE TABLE {$wpdb->comments}");
471
  }
472
 
473
  function akismet_delete_old_metadata() {
474
  global $wpdb;
475
 
 
476
  $interval = apply_filters( 'akismet_delete_commentmeta_interval', 15 );
477
 
478
  # enfore a minimum of 1 day
479
  $interval = absint( $interval );
480
+ if ( $interval < 1 )
481
+ $interval = 1;
 
482
 
483
  // akismet_as_submitted meta values are large, so expire them
484
  // after $interval days regardless of the comment status
485
+ while ( $comment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT m.comment_id FROM {$wpdb->commentmeta} as m INNER JOIN {$wpdb->comments} as c USING(comment_id) WHERE m.meta_key = 'akismet_as_submitted' AND DATE_SUB(NOW(), INTERVAL %d DAY) > c.comment_date_gmt LIMIT 10000", $interval ) ) ) {
486
+ if ( empty( $comment_ids ) )
487
+ return;
488
+
489
+ $wpdb->queries = array();
490
+
 
491
  foreach ( $comment_ids as $comment_id ) {
492
  delete_comment_meta( $comment_id, 'akismet_as_submitted' );
493
  }
494
  }
495
+
496
+ if ( apply_filters( 'akismet_optimize_table', ( mt_rand(1, 5000) == 11) ) ) // lucky number
497
+ $wpdb->query("OPTIMIZE TABLE {$wpdb->comments}");
498
+ }
 
 
 
 
499
 
500
  add_action('akismet_scheduled_delete', 'akismet_delete_old');
501
  add_action('akismet_scheduled_delete', 'akismet_delete_old_metadata');
610
  if ( $akismet_comment_nonce_option == 'true' || $akismet_comment_nonce_option == '' )
611
  add_action( 'comment_form', 'akismet_add_comment_nonce' );
612
 
613
+ function akismet_pingback_forwarded_for( $r, $url ) {
614
+ static $urls = array();
615
+
616
+ // Call this with $r == null to prime the callback to add headers on a specific URL
617
+ if ( is_null( $r ) && !in_array( $url, $urls ) ) {
618
+ $urls[] = $url;
619
+ }
620
+
621
+ // Add X-Pingback-Forwarded-For header, but only for requests to a specific URL (the apparent pingback source)
622
+ if ( is_array( $r ) && is_array( $r['headers'] ) && !isset( $r['headers']['X-Pingback-Forwarded-For'] ) && in_array( $url, $urls ) ) {
623
+ $remote_ip = preg_replace( '/[^a-fx0-9:.,]/i', '', $_SERVER['REMOTE_ADDR'] );
624
+
625
+ // Note: this assumes REMOTE_ADDR is correct, and it may not be if a reverse proxy or CDN is in use
626
+ $r['headers']['X-Pingback-Forwarded-For'] = $remote_ip;
627
+
628
+ // Also identify the request as a pingback verification in the UA string so it appears in logs
629
+ $r['user-agent'] .= '; verifying pingback from ' . $remote_ip;
630
+ }
631
+
632
+ return $r;
633
+ }
634
+
635
+ function akismet_pre_check_pingback( $method ) {
636
+
637
+ if ( $method !== 'pingback.ping' )
638
+ return;
639
+
640
+ global $wp_xmlrpc_server;
641
+
642
+ if ( !is_object( $wp_xmlrpc_server ) )
643
+ return false;
644
+
645
+ // Lame: tightly coupled with the IXR class.
646
+ $args = $wp_xmlrpc_server->message->params;
647
+
648
+ if ( !empty( $args[1] ) ) {
649
+ $post_id = url_to_postid( $args[1] );
650
+
651
+ // If this gets through the pre-check, make sure we properly identify the outbound request as a pingback verification
652
+ akismet_pingback_forwarded_for( null, $args[0] );
653
+ add_filter( 'http_request_args', 'akismet_pingback_forwarded_for', 10, 2 );
654
+
655
+ $comment = array(
656
+ 'comment_author_url' => $args[0],
657
+ 'comment_post_ID' => $post_id,
658
+ 'comment_author' => '',
659
+ 'comment_author_email' => '',
660
+ 'comment_content' => '',
661
+ 'comment_type' => 'pingback',
662
+ 'akismet_pre_check' => '1',
663
+ 'comment_pingback_target' => $args[1],
664
+ );
665
+
666
+ $comment = akismet_auto_check_comment( $comment );
667
+
668
+ if ( isset( $comment['akismet_result'] ) && 'true' == $comment['akismet_result'] ) {
669
+ // Lame: tightly coupled with the IXR classes. Unfortunately the action provides no context and no way to return anything.
670
+ $wp_xmlrpc_server->error( new IXR_Error( 0, 'Invalid discovery target' ) );
671
+ }
672
+ }
673
+ }
674
+
675
+ // Run this early in the pingback call, before doing a remote fetch of the source uri
676
+ add_action( 'xmlrpc_call', 'akismet_pre_check_pingback' );
677
+
678
  global $wp_version;
679
  if ( '3.0.5' == $wp_version ) {
680
  remove_filter( 'comment_text', 'wp_kses_data' );
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, automattic
3
  Tags: akismet, comments, spam
4
  Requires at least: 3.0
5
- Tested up to: 3.6
6
- Stable tag: 2.5.9
7
  License: GPLv2 or later
8
 
9
  Akismet checks your comments against the Akismet web service to see if they look like spam or not.
@@ -31,6 +31,14 @@ Upload the Akismet plugin to your blog, Activate it, then enter your [Akismet.co
31
 
32
  == Changelog ==
33
 
 
 
 
 
 
 
 
 
34
  = 2.5.9 =
35
  * Update 'Already have a key' link to redirect page rather than depend on javascript
36
  * Fix some non-translatable strings to be translatable
2
  Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, automattic
3
  Tags: akismet, comments, spam
4
  Requires at least: 3.0
5
+ Tested up to: 3.8.1
6
+ Stable tag: 2.6.0
7
  License: GPLv2 or later
8
 
9
  Akismet checks your comments against the Akismet web service to see if they look like spam or not.
31
 
32
  == Changelog ==
33
 
34
+ = 2.6.0 =
35
+ * Add ajax paging to the check for spam button to handle large volumes of comments
36
+ * Optimize javascript and add localization support
37
+ * Fix bug in link to spam comments from right now dashboard widget
38
+ * Fix bug with deleting old comments to avoid timeouts dealing with large volumes of comments
39
+ * Include X-Pingback-Forwarded-For header in outbound WordPress pingback verifications
40
+ * Add pre-check for pingbacks, to stop spam before an outbound verification request is made
41
+
42
  = 2.5.9 =
43
  * Update 'Already have a key' link to redirect page rather than depend on javascript
44
  * Fix some non-translatable strings to be translatable