Version Description
Release Date - 2 March 2021
- Improved handling of pingbacks in XML-RPC multicalls
Download this release
Release Info
Developer | cfinke |
Plugin | Akismet Anti-Spam |
Version | 4.1.9 |
Comparing to | |
See all releases |
Code changes from version 4.1.8 to 4.1.9
- akismet.php +2 -2
- class.akismet.php +115 -15
- readme.txt +7 -2
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.1.
|
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.1.
|
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.1.9
|
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.1.9' );
|
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.php
CHANGED
@@ -10,8 +10,14 @@ class Akismet {
|
|
10 |
private static $prevent_moderation_email_for_these_comments = array();
|
11 |
private static $last_comment_result = null;
|
12 |
private static $comment_as_submitted_allowed_keys = array( 'blog' => '', 'blog_charset' => '', 'blog_lang' => '', 'blog_ua' => '', 'comment_agent' => '', 'comment_author' => '', 'comment_author_IP' => '', 'comment_author_email' => '', 'comment_author_url' => '', 'comment_content' => '', 'comment_date_gmt' => '', 'comment_tags' => '', 'comment_type' => '', 'guid' => '', 'is_test' => '', 'permalink' => '', 'reporter' => '', 'site_domain' => '', 'submit_referer' => '', 'submit_uri' => '', 'user_ID' => '', 'user_agent' => '', 'user_id' => '', 'user_ip' => '' );
|
13 |
-
private static $is_rest_api_call = false;
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
public static function init() {
|
16 |
if ( ! self::$initiated ) {
|
17 |
self::init_hooks();
|
@@ -131,7 +137,7 @@ class Akismet {
|
|
131 |
}
|
132 |
|
133 |
public static function rest_auto_check_comment( $commentdata ) {
|
134 |
-
self::$
|
135 |
|
136 |
return self::auto_check_comment( $commentdata );
|
137 |
}
|
@@ -240,7 +246,7 @@ class Akismet {
|
|
240 |
update_option( 'akismet_spam_count', get_option( 'akismet_spam_count' ) + $incr );
|
241 |
}
|
242 |
|
243 |
-
if ( self::$
|
244 |
return new WP_Error( 'akismet_rest_comment_discarded', __( 'Comment discarded.', 'akismet' ) );
|
245 |
}
|
246 |
else {
|
@@ -250,7 +256,7 @@ class Akismet {
|
|
250 |
die();
|
251 |
}
|
252 |
}
|
253 |
-
else if ( self::$
|
254 |
// The way the REST API structures its calls, we can set the comment_approved value right away.
|
255 |
$commentdata['comment_approved'] = 'spam';
|
256 |
}
|
@@ -1420,16 +1426,100 @@ p {
|
|
1420 |
if ( $method !== 'pingback.ping' )
|
1421 |
return;
|
1422 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1423 |
global $wp_xmlrpc_server;
|
1424 |
-
|
1425 |
if ( !is_object( $wp_xmlrpc_server ) )
|
1426 |
return false;
|
1427 |
-
|
1428 |
-
|
1429 |
-
|
1430 |
-
|
1431 |
-
|
1432 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1433 |
|
1434 |
// If pingbacks aren't open on this post, we'll still check whether this request is part of a potential DDOS,
|
1435 |
// but indicate to the server that pingbacks are indeed closed so we don't include this request in the user's stats,
|
@@ -1442,23 +1532,33 @@ p {
|
|
1442 |
$pingbacks_closed = true;
|
1443 |
}
|
1444 |
|
|
|
|
|
1445 |
$comment = array(
|
1446 |
-
'comment_author_url' => $
|
1447 |
'comment_post_ID' => $post_id,
|
1448 |
'comment_author' => '',
|
1449 |
'comment_author_email' => '',
|
1450 |
'comment_content' => '',
|
1451 |
'comment_type' => 'pingback',
|
1452 |
'akismet_pre_check' => '1',
|
1453 |
-
'comment_pingback_target' => $
|
1454 |
'pingbacks_closed' => $pingbacks_closed ? '1' : '0',
|
|
|
|
|
1455 |
);
|
1456 |
|
1457 |
$comment = Akismet::auto_check_comment( $comment );
|
1458 |
|
1459 |
-
if (
|
1460 |
-
|
|
|
|
|
|
|
1461 |
$wp_xmlrpc_server->error( new IXR_Error( 0, 'Invalid discovery target' ) );
|
|
|
|
|
|
|
1462 |
}
|
1463 |
}
|
1464 |
}
|
10 |
private static $prevent_moderation_email_for_these_comments = array();
|
11 |
private static $last_comment_result = null;
|
12 |
private static $comment_as_submitted_allowed_keys = array( 'blog' => '', 'blog_charset' => '', 'blog_lang' => '', 'blog_ua' => '', 'comment_agent' => '', 'comment_author' => '', 'comment_author_IP' => '', 'comment_author_email' => '', 'comment_author_url' => '', 'comment_content' => '', 'comment_date_gmt' => '', 'comment_tags' => '', 'comment_type' => '', 'guid' => '', 'is_test' => '', 'permalink' => '', 'reporter' => '', 'site_domain' => '', 'submit_referer' => '', 'submit_uri' => '', 'user_ID' => '', 'user_agent' => '', 'user_id' => '', 'user_ip' => '' );
|
|
|
13 |
|
14 |
+
/**
|
15 |
+
* Is the comment check happening in the context of an API call? Of if false, then it's during the POST that happens after filling out a comment form.
|
16 |
+
*
|
17 |
+
* @var type bool
|
18 |
+
*/
|
19 |
+
private static $is_api_call = false;
|
20 |
+
|
21 |
public static function init() {
|
22 |
if ( ! self::$initiated ) {
|
23 |
self::init_hooks();
|
137 |
}
|
138 |
|
139 |
public static function rest_auto_check_comment( $commentdata ) {
|
140 |
+
self::$is_api_call = true;
|
141 |
|
142 |
return self::auto_check_comment( $commentdata );
|
143 |
}
|
246 |
update_option( 'akismet_spam_count', get_option( 'akismet_spam_count' ) + $incr );
|
247 |
}
|
248 |
|
249 |
+
if ( self::$is_api_call ) {
|
250 |
return new WP_Error( 'akismet_rest_comment_discarded', __( 'Comment discarded.', 'akismet' ) );
|
251 |
}
|
252 |
else {
|
256 |
die();
|
257 |
}
|
258 |
}
|
259 |
+
else if ( self::$is_api_call ) {
|
260 |
// The way the REST API structures its calls, we can set the comment_approved value right away.
|
261 |
$commentdata['comment_approved'] = 'spam';
|
262 |
}
|
1426 |
if ( $method !== 'pingback.ping' )
|
1427 |
return;
|
1428 |
|
1429 |
+
// A lot of this code is tightly coupled with the IXR class because the xmlrpc_call action doesn't pass along any information besides the method name.
|
1430 |
+
// This ticket should hopefully fix that: https://core.trac.wordpress.org/ticket/52524
|
1431 |
+
// Until that happens, when it's a system.multicall, pre_check_pingback will be called once for every internal pingback call.
|
1432 |
+
// Keep track of how many times this function has been called so we know which call to reference in the XML.
|
1433 |
+
static $call_count = 0;
|
1434 |
+
|
1435 |
+
$call_count++;
|
1436 |
+
|
1437 |
global $wp_xmlrpc_server;
|
1438 |
+
|
1439 |
if ( !is_object( $wp_xmlrpc_server ) )
|
1440 |
return false;
|
1441 |
+
|
1442 |
+
self::$is_api_call = true;
|
1443 |
+
|
1444 |
+
$is_multicall = false;
|
1445 |
+
$multicall_count = 0;
|
1446 |
+
|
1447 |
+
if ( 'system.multicall' === $wp_xmlrpc_server->message->methodName ) {
|
1448 |
+
$is_multicall = true;
|
1449 |
+
|
1450 |
+
if ( 0 === $call_count ) {
|
1451 |
+
// Only pass along the number of entries in the multicall the first time we see it.
|
1452 |
+
$multicall_count = count( $wp_xmlrpc_server->message->params );
|
1453 |
+
}
|
1454 |
+
|
1455 |
+
/*
|
1456 |
+
* $wp_xmlrpc_server->message looks like this:
|
1457 |
+
*
|
1458 |
+
(
|
1459 |
+
[message] =>
|
1460 |
+
[messageType] => methodCall
|
1461 |
+
[faultCode] =>
|
1462 |
+
[faultString] =>
|
1463 |
+
[methodName] => system.multicall
|
1464 |
+
[params] => Array
|
1465 |
+
(
|
1466 |
+
[0] => Array
|
1467 |
+
(
|
1468 |
+
[methodName] => pingback.ping
|
1469 |
+
[params] => Array
|
1470 |
+
(
|
1471 |
+
[0] => http://www.example.net/?p=1 // Site that created the pingback.
|
1472 |
+
[1] => https://www.example.com/?p=1 // Post being pingback'd on this site.
|
1473 |
+
)
|
1474 |
+
)
|
1475 |
+
[1] => Array
|
1476 |
+
(
|
1477 |
+
[methodName] => pingback.ping
|
1478 |
+
[params] => Array
|
1479 |
+
(
|
1480 |
+
[0] => http://www.example.net/?p=1 // Site that created the pingback.
|
1481 |
+
[1] => https://www.example.com/?p=2 // Post being pingback'd on this site.
|
1482 |
+
)
|
1483 |
+
)
|
1484 |
+
)
|
1485 |
+
)
|
1486 |
+
*/
|
1487 |
+
|
1488 |
+
// Use the params from the nth pingback.ping call in the multicall.
|
1489 |
+
$pingback_calls_found = 0;
|
1490 |
+
|
1491 |
+
foreach ( $wp_xmlrpc_server->message->params as $xmlrpc_action ) {
|
1492 |
+
if ( 'pingback.ping' === $xmlrpc_action['methodName'] ) {
|
1493 |
+
$pingback_calls_found++;
|
1494 |
+
}
|
1495 |
+
|
1496 |
+
if ( $call_count === $pingback_calls_found ) {
|
1497 |
+
$pingback_args = $xmlrpc_action['params'];
|
1498 |
+
break;
|
1499 |
+
}
|
1500 |
+
}
|
1501 |
+
} else {
|
1502 |
+
/*
|
1503 |
+
* $wp_xmlrpc_server->message looks like this:
|
1504 |
+
*
|
1505 |
+
(
|
1506 |
+
[message] =>
|
1507 |
+
[messageType] => methodCall
|
1508 |
+
[faultCode] =>
|
1509 |
+
[faultString] =>
|
1510 |
+
[methodName] => pingback.ping
|
1511 |
+
[params] => Array
|
1512 |
+
(
|
1513 |
+
[0] => http://www.example.net/?p=1 // Site that created the pingback.
|
1514 |
+
[1] => https://www.example.com/?p=2 // Post being pingback'd on this site.
|
1515 |
+
)
|
1516 |
+
)
|
1517 |
+
*/
|
1518 |
+
$pingback_args = $wp_xmlrpc_server->message->params;
|
1519 |
+
}
|
1520 |
+
|
1521 |
+
if ( ! empty( $pingback_args[1] ) ) {
|
1522 |
+
$post_id = url_to_postid( $pingback_args[1] );
|
1523 |
|
1524 |
// If pingbacks aren't open on this post, we'll still check whether this request is part of a potential DDOS,
|
1525 |
// but indicate to the server that pingbacks are indeed closed so we don't include this request in the user's stats,
|
1532 |
$pingbacks_closed = true;
|
1533 |
}
|
1534 |
|
1535 |
+
// Note: If is_multicall is true and multicall_count=0, then we know this is at least the 2nd pingback we've processed in this multicall.
|
1536 |
+
|
1537 |
$comment = array(
|
1538 |
+
'comment_author_url' => $pingback_args[0],
|
1539 |
'comment_post_ID' => $post_id,
|
1540 |
'comment_author' => '',
|
1541 |
'comment_author_email' => '',
|
1542 |
'comment_content' => '',
|
1543 |
'comment_type' => 'pingback',
|
1544 |
'akismet_pre_check' => '1',
|
1545 |
+
'comment_pingback_target' => $pingback_args[1],
|
1546 |
'pingbacks_closed' => $pingbacks_closed ? '1' : '0',
|
1547 |
+
'is_multicall' => $is_multicall,
|
1548 |
+
'multicall_count' => $multicall_count,
|
1549 |
);
|
1550 |
|
1551 |
$comment = Akismet::auto_check_comment( $comment );
|
1552 |
|
1553 |
+
if (
|
1554 |
+
is_wp_error( $comment ) // This triggered a 'discard' directive.
|
1555 |
+
|| ( isset( $comment['akismet_result'] ) && 'true' == $comment['akismet_result'] ) // It was just a normal spam response.
|
1556 |
+
) {
|
1557 |
+
// Sad: tightly coupled with the IXR classes. Unfortunately the action provides no context and no way to return anything.
|
1558 |
$wp_xmlrpc_server->error( new IXR_Error( 0, 'Invalid discovery target' ) );
|
1559 |
+
|
1560 |
+
// Also note that if this was part of a multicall, a spam result will prevent the subsequent calls from being executed.
|
1561 |
+
// This is probably fine, but it raises the bar for what should be acceptable as a false positive.
|
1562 |
}
|
1563 |
}
|
1564 |
}
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, cfinke, automattic, jgs, procifer, stephdau
|
3 |
Tags: comments, spam, antispam, anti-spam, contact form, anti spam, comment moderation, comment spam, contact form spam, spam comments
|
4 |
Requires at least: 4.6
|
5 |
-
Tested up to: 5.
|
6 |
-
Stable tag: 4.1.
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
The best anti-spam protection to block spam comments and spam in a contact form. The most trusted antispam solution for WordPress and WooCommerce.
|
@@ -30,6 +30,11 @@ Upload the Akismet plugin to your blog, activate it, and then enter your Akismet
|
|
30 |
|
31 |
== Changelog ==
|
32 |
|
|
|
|
|
|
|
|
|
|
|
33 |
= 4.1.8 =
|
34 |
*Release Date - 6 January 2021*
|
35 |
|
2 |
Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, cfinke, automattic, jgs, procifer, stephdau
|
3 |
Tags: comments, spam, antispam, anti-spam, contact form, anti spam, comment moderation, comment spam, contact form spam, spam comments
|
4 |
Requires at least: 4.6
|
5 |
+
Tested up to: 5.7
|
6 |
+
Stable tag: 4.1.9
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
The best anti-spam protection to block spam comments and spam in a contact form. The most trusted antispam solution for WordPress and WooCommerce.
|
30 |
|
31 |
== Changelog ==
|
32 |
|
33 |
+
= 4.1.9 =
|
34 |
+
*Release Date - 2 March 2021*
|
35 |
+
|
36 |
+
* Improved handling of pingbacks in XML-RPC multicalls
|
37 |
+
|
38 |
= 4.1.8 =
|
39 |
*Release Date - 6 January 2021*
|
40 |
|