Version Description
Release Date - 2 March 2021
- Improved handling of pingbacks in XML-RPC multicalls
Download this release
Release Info
| Developer | cfinke |
| Plugin | |
| 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 |
|
