diff options
author | Yury German <blueknight@gentoo.org> | 2022-01-23 19:08:06 -0500 |
---|---|---|
committer | Yury German <blueknight@gentoo.org> | 2022-01-23 19:08:06 -0500 |
commit | 0949f1a8dfdad78ba67fb1dcd58537b83a26e8a3 (patch) | |
tree | 6d09f48aa3a454b07ecafdb371b187ef4854a998 | |
parent | Bumb Mantra to 3.20 to 3.3.1 and twentififteen from 2.5 to 3.0 (diff) | |
download | blogs-gentoo-0949f1a8dfdad78ba67fb1dcd58537b83a26e8a3.tar.gz blogs-gentoo-0949f1a8dfdad78ba67fb1dcd58537b83a26e8a3.tar.bz2 blogs-gentoo-0949f1a8dfdad78ba67fb1dcd58537b83a26e8a3.zip |
Plugin - akismet update from 4.1.3 to 4.2.1
Signed-off-by: Yury German <blueknight@gentoo.org>
-rw-r--r-- | plugins/akismet/.htaccess | 2 | ||||
-rw-r--r-- | plugins/akismet/_inc/akismet.css | 83 | ||||
-rw-r--r-- | plugins/akismet/_inc/akismet.js | 207 | ||||
-rw-r--r-- | plugins/akismet/_inc/form.js | 30 | ||||
-rw-r--r-- | plugins/akismet/_inc/img/logo-a-2x.png | bin | 0 -> 904 bytes | |||
-rw-r--r-- | plugins/akismet/akismet.php | 6 | ||||
-rw-r--r-- | plugins/akismet/changelog.txt | 465 | ||||
-rw-r--r-- | plugins/akismet/class.akismet-admin.php | 167 | ||||
-rw-r--r-- | plugins/akismet/class.akismet-widget.php | 24 | ||||
-rw-r--r-- | plugins/akismet/class.akismet.php | 477 | ||||
-rw-r--r-- | plugins/akismet/readme.txt | 476 | ||||
-rw-r--r-- | plugins/akismet/views/config.php | 8 | ||||
-rw-r--r-- | plugins/akismet/views/enter.php | 2 | ||||
-rw-r--r-- | plugins/akismet/views/notice.php | 193 | ||||
-rw-r--r-- | plugins/akismet/views/setup.php | 5 | ||||
-rw-r--r-- | plugins/akismet/views/stats.php | 2 |
16 files changed, 1389 insertions, 758 deletions
diff --git a/plugins/akismet/.htaccess b/plugins/akismet/.htaccess index 49d72d71..d2675517 100644 --- a/plugins/akismet/.htaccess +++ b/plugins/akismet/.htaccess @@ -23,7 +23,7 @@ </FilesMatch> # Akismet images -<FilesMatch "^logo-full-2x\.png$"> +<FilesMatch "^logo-(a|full)-2x\.png$"> <IfModule !mod_authz_core.c> Allow from all </IfModule> diff --git a/plugins/akismet/_inc/akismet.css b/plugins/akismet/_inc/akismet.css index fea4eb7b..a62f7a84 100644 --- a/plugins/akismet/_inc/akismet.css +++ b/plugins/akismet/_inc/akismet.css @@ -79,15 +79,6 @@ table.comments td.comment p a:after { .checkforspam { display: inline-block !important; } -.checkforspam-progress { - display: none; -} -.checkforspam.checking .checkforspam-progress { - padding-left: 1ex; -} -.checkforspam.button-disabled .checkforspam-progress { - display: inline; -} .checkforspam-spinner { display: inline-block; @@ -109,12 +100,9 @@ table.comments td.comment p a:after { margin-top: .5rem; } .akismet-alert { - border: 1px solid #e5e5e5; padding: 0.4em 1em 1.4em 1em; - border-radius: 3px; - -webkit-border-radius: 3px; - border-width: 1px; - border-style: solid; + box-sizing: border-box; + box-shadow: 0 0 0 1px rgba(200, 215, 225, 0.5), 0 1px 2px #e9eff3; } .akismet-alert h3.akismet-key-status { @@ -661,3 +649,70 @@ table.comments td.comment p a:after { .akismet-section-header__actions { line-height: 1.75rem; } + +.akismet-setup-instructions { + text-align: center; +} + +.akismet-setup-instructions form { + padding-bottom: 1.5rem; +} + +div.error.akismet-usage-limit-alert { + padding: 25px 45px 25px 15px; + display: flex; + align-items: center; +} + +#akismet-plugin-container .akismet-usage-limit-alert { + margin: 0 auto 0.625rem auto; + box-sizing: border-box; + box-shadow: 0 0 0 1px rgba(200, 215, 225, 0.5), 0 1px 2px #e9eff3; + border: none; + border-left: 4px solid #d63638; +} + +.akismet-usage-limit-alert .akismet-usage-limit-logo { + width: 38px; + min-width: 38px; + height: 38px; + border-radius: 20px; + margin-right: 18px; + background: black; + position: relative; +} + +.akismet-usage-limit-alert .akismet-usage-limit-logo img { + position: absolute; + width: 22px; + left: 8px; + top: 10px; +} + +.akismet-usage-limit-alert .akismet-usage-limit-text { + flex-grow: 1; + margin-right: 18px; +} + +.akismet-usage-limit-alert h3 { + margin: 0; +} + +.akismet-usage-limit-alert .akismet-usage-limit-cta { + text-align: right; +} + +@media (max-width: 550px) { + div.error.akismet-usage-limit-alert { + display: block; + } + + .akismet-usage-limit-alert .akismet-usage-limit-logo, + .akismet-usage-limit-alert .akismet-usage-limit-text { + margin-bottom: 15px; + } + + .akismet-usage-limit-alert .akismet-usage-limit-cta { + text-align: left; + } +}
\ No newline at end of file diff --git a/plugins/akismet/_inc/akismet.js b/plugins/akismet/_inc/akismet.js index 3445a094..7ebac1a5 100644 --- a/plugins/akismet/_inc/akismet.js +++ b/plugins/akismet/_inc/akismet.js @@ -1,10 +1,12 @@ jQuery( function ( $ ) { var mshotRemovalTimer = null; - var mshotSecondTryTimer = null - var mshotThirdTryTimer = null - + var mshotRetryTimer = null; + var mshotTries = 0; + var mshotRetryInterval = 1000; var mshotEnabledLinkSelector = 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a'; - + + var preloadedMshotURLs = []; + $('.akismet-status').each(function () { var thisId = $(this).attr('commentid'); $(this).prependTo('#comment-' + thisId + ' .column-comment'); @@ -84,69 +86,142 @@ jQuery( function ( $ ) { }); // Show a preview image of the hovered URL. Applies to author URLs and URLs inside the comments. - $( '#the-comment-list' ).on( 'mouseover', mshotEnabledLinkSelector, function () { - clearTimeout( mshotRemovalTimer ); + if ( "enable_mshots" in WPAkismet && WPAkismet.enable_mshots ) { + $( '#the-comment-list' ).on( 'mouseover', mshotEnabledLinkSelector, function () { + clearTimeout( mshotRemovalTimer ); - if ( $( '.akismet-mshot' ).length > 0 ) { - if ( $( '.akismet-mshot:first' ).data( 'link' ) == this ) { - // The preview is already showing for this link. - return; + if ( $( '.akismet-mshot' ).length > 0 ) { + if ( $( '.akismet-mshot:first' ).data( 'link' ) == this ) { + // The preview is already showing for this link. + return; + } + else { + // A new link is being hovered, so remove the old preview. + $( '.akismet-mshot' ).remove(); + } + } + + clearTimeout( mshotRetryTimer ); + + var linkUrl = $( this ).attr( 'href' ); + + if ( preloadedMshotURLs.indexOf( linkUrl ) !== -1 ) { + // This preview image was already preloaded, so begin with a retry URL so the user doesn't see the placeholder image for the first second. + mshotTries = 2; } else { - // A new link is being hovered, so remove the old preview. - $( '.akismet-mshot' ).remove(); + mshotTries = 1; } - } - clearTimeout( mshotSecondTryTimer ); - clearTimeout( mshotThirdTryTimer ); + var mShot = $( '<div class="akismet-mshot mshot-container"><div class="mshot-arrow"></div><img src="' + akismet_mshot_url( linkUrl, mshotTries ) + '" width="450" height="338" class="mshot-image" /></div>' ); + mShot.data( 'link', this ); + mShot.data( 'url', linkUrl ); + + mShot.find( 'img' ).on( 'load', function () { + $( '.akismet-mshot' ).data( 'pending-request', false ); + } ); - var thisHref = $( this ).attr( 'href' ); + var offset = $( this ).offset(); - var mShot = $( '<div class="akismet-mshot mshot-container"><div class="mshot-arrow"></div><img src="' + akismet_mshot_url( thisHref ) + '" width="450" height="338" class="mshot-image" /></div>' ); - mShot.data( 'link', this ); + mShot.offset( { + left : Math.min( $( window ).width() - 475, offset.left + $( this ).width() + 10 ), // Keep it on the screen if the link is near the edge of the window. + top: offset.top + ( $( this ).height() / 2 ) - 101 // 101 = top offset of the arrow plus the top border thickness + } ); - var offset = $( this ).offset(); + $( 'body' ).append( mShot ); - mShot.offset( { - left : Math.min( $( window ).width() - 475, offset.left + $( this ).width() + 10 ), // Keep it on the screen if the link is near the edge of the window. - top: offset.top + ( $( this ).height() / 2 ) - 101 // 101 = top offset of the arrow plus the top border thickness + mshotRetryTimer = setTimeout( retryMshotUntilLoaded, mshotRetryInterval ); + } ).on( 'mouseout', 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a', function () { + mshotRemovalTimer = setTimeout( function () { + clearTimeout( mshotRetryTimer ); + + $( '.akismet-mshot' ).remove(); + }, 200 ); } ); - // These retries appear to be superfluous if .mshot-image has already loaded, but it's because mShots - // can return a "Generating thumbnail..." image if it doesn't have a thumbnail ready, so we need - // to retry to see if we can get the newly generated thumbnail. - mshotSecondTryTimer = setTimeout( function () { - mShot.find( '.mshot-image' ).attr( 'src', akismet_mshot_url( thisHref, 2 ) ); - }, 6000 ); - - mshotThirdTryTimer = setTimeout( function () { - mShot.find( '.mshot-image' ).attr( 'src', akismet_mshot_url( thisHref, 3 ) ); - }, 12000 ); - - $( 'body' ).append( mShot ); - } ).on( 'mouseout', 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a', function () { - mshotRemovalTimer = setTimeout( function () { - clearTimeout( mshotSecondTryTimer ); - clearTimeout( mshotThirdTryTimer ); - - $( '.akismet-mshot' ).remove(); - }, 200 ); - } ).on( 'mouseover', 'tr', function () { - // When the mouse hovers over a comment row, begin preloading mshots for any links in the comment or the comment author. - var linksToPreloadMshotsFor = $( this ).find( mshotEnabledLinkSelector ); - - linksToPreloadMshotsFor.each( function () { - // Don't attempt to preload an mshot for a single link twice. Browser caching should cover this, but in case of - // race conditions, save a flag locally when we've begun trying to preload one. - if ( ! $( this ).data( 'akismet-mshot-preloaded' ) ) { - akismet_preload_mshot( $( this ).attr( 'href' ) ); + var preloadDelayTimer = null; + + $( window ).on( 'scroll resize', function () { + clearTimeout( preloadDelayTimer ); + + preloadDelayTimer = setTimeout( preloadMshotsInViewport, 500 ); + } ); + + preloadMshotsInViewport(); + } + + /** + * The way mShots works is if there was no screenshot already recently generated for the URL, + * it returns a "loading..." image for the first request. Then, some subsequent request will + * receive the actual screenshot, but it's unknown how long it will take. So, what we do here + * is continually re-request the mShot, waiting a second after every response until we get the + * actual screenshot. + */ + function retryMshotUntilLoaded() { + clearTimeout( mshotRetryTimer ); + + var imageWidth = $( '.akismet-mshot img' ).get(0).naturalWidth; + + if ( imageWidth == 0 ) { + // It hasn't finished loading yet the first time. Check again shortly. + setTimeout( retryMshotUntilLoaded, mshotRetryInterval ); + } + else if ( imageWidth == 400 ) { + // It loaded the preview image. + + if ( mshotTries == 20 ) { + // Give up if we've requested the mShot 20 times already. + return; + } + + if ( ! $( '.akismet-mshot' ).data( 'pending-request' ) ) { + $( '.akismet-mshot' ).data( 'pending-request', true ); + + mshotTries++; + + $( '.akismet-mshot .mshot-image' ).attr( 'src', akismet_mshot_url( $( '.akismet-mshot' ).data( 'url' ), mshotTries ) ); + } + + mshotRetryTimer = setTimeout( retryMshotUntilLoaded, mshotRetryInterval ); + } + else { + // All done. + } + } + + function preloadMshotsInViewport() { + var windowWidth = $( window ).width(); + var windowHeight = $( window ).height(); + + $( '#the-comment-list' ).find( mshotEnabledLinkSelector ).each( function ( index, element ) { + var linkUrl = $( this ).attr( 'href' ); + + // Don't attempt to preload an mshot for a single link twice. + if ( preloadedMshotURLs.indexOf( linkUrl ) !== -1 ) { + // The URL is already preloaded. + return true; + } + + if ( typeof element.getBoundingClientRect !== 'function' ) { + // The browser is too old. Return false to stop this preloading entirely. + return false; + } + + var rect = element.getBoundingClientRect(); + + if ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= windowHeight && rect.right <= windowWidth ) { + akismet_preload_mshot( linkUrl ); $( this ).data( 'akismet-mshot-preloaded', true ); } } ); - } ); + } + + $( '.checkforspam.enable-on-load' ).on( 'click', function( e ) { + if ( $( this ).hasClass( 'ajax-disabled' ) ) { + // Akismet hasn't been configured yet. Allow the user to proceed to the button's link. + return; + } - $( '.checkforspam' ).click( function( e ) { e.preventDefault(); if ( $( this ).hasClass( 'button-disabled' ) ) { @@ -157,11 +232,8 @@ jQuery( function ( $ ) { $('.checkforspam').addClass('button-disabled').addClass( 'checking' ); $('.checkforspam-spinner').addClass( 'spinner' ).addClass( 'is-active' ); - // Update the label on the "Check for Spam" button to use the active "Checking for Spam" language. - $( '.checkforspam .akismet-label' ).text( $( '.checkforspam' ).data( 'active-label' ) ); - akismet_check_for_spam(0, 100); - }); + }).removeClass( 'button-disabled' ); var spam_count = 0; var recheck_count = 0; @@ -176,7 +248,7 @@ jQuery( function ( $ ) { var percentage_complete = Math.round( ( recheck_count / check_for_spam_buttons.data( 'pending-comment-count' ) ) * 1000 ) / 10; // Update the progress counter on the "Check for Spam" button. - $( '.checkforspam-progress' ).text( check_for_spam_buttons.data( 'progress-label-format' ).replace( '%1$s', percentage_complete ) ); + $( '.checkforspam' ).text( check_for_spam_buttons.data( 'progress-label' ).replace( '%1$s', percentage_complete ) ); $.post( ajaxurl, @@ -269,12 +341,14 @@ jQuery( function ( $ ) { * @return string The mShot URL; */ function akismet_mshot_url( linkUrl, retry ) { - var mshotUrl = '//s0.wordpress.com/mshots/v1/' + encodeURIComponent( linkUrl ) + '?w=900'; - - if ( retry ) { + var mshotUrl = '//s0.wp.com/mshots/v1/' + encodeURIComponent( linkUrl ) + '?w=900'; + + if ( retry > 1 ) { mshotUrl += '&r=' + encodeURIComponent( retry ); } - + + mshotUrl += '&source=akismet'; + return mshotUrl; } @@ -286,17 +360,10 @@ jQuery( function ( $ ) { function akismet_preload_mshot( linkUrl ) { var img = new Image(); img.src = akismet_mshot_url( linkUrl ); + + preloadedMshotURLs.push( linkUrl ); } - /** - * Sets the comment form privacy notice display to hide when one clicks Core's dismiss button on the related admin notice. - */ - $( '#akismet-privacy-notice-admin-notice' ).on( 'click', '.notice-dismiss', function () { - $.ajax( { - url: './options-general.php?page=akismet-key-config&akismet_comment_form_privacy_notice=hide', - } ); - }); - $( '.akismet-could-be-primary' ).each( function () { var form = $( this ).closest( 'form' ); diff --git a/plugins/akismet/_inc/form.js b/plugins/akismet/_inc/form.js deleted file mode 100644 index 3a5be8af..00000000 --- a/plugins/akismet/_inc/form.js +++ /dev/null @@ -1,30 +0,0 @@ -var ak_js = document.getElementById( "ak_js" ); - -if ( ! ak_js ) { - ak_js = document.createElement( 'input' ); - ak_js.setAttribute( 'id', 'ak_js' ); - ak_js.setAttribute( 'name', 'ak_js' ); - ak_js.setAttribute( 'type', 'hidden' ); -} -else { - ak_js.parentNode.removeChild( ak_js ); -} - -ak_js.setAttribute( 'value', ( new Date() ).getTime() ); - -var commentForm = document.getElementById( 'commentform' ); - -if ( commentForm ) { - commentForm.appendChild( ak_js ); -} -else { - var replyRowContainer = document.getElementById( 'replyrow' ); - - if ( replyRowContainer ) { - var children = replyRowContainer.getElementsByTagName( 'td' ); - - if ( children.length > 0 ) { - children[0].appendChild( ak_js ); - } - } -}
\ No newline at end of file diff --git a/plugins/akismet/_inc/img/logo-a-2x.png b/plugins/akismet/_inc/img/logo-a-2x.png Binary files differnew file mode 100644 index 00000000..087144ae --- /dev/null +++ b/plugins/akismet/_inc/img/logo-a-2x.png diff --git a/plugins/akismet/akismet.php b/plugins/akismet/akismet.php index 538a7dbc..2175a913 100644 --- a/plugins/akismet/akismet.php +++ b/plugins/akismet/akismet.php @@ -6,7 +6,7 @@ Plugin Name: Akismet Anti-Spam Plugin URI: https://akismet.com/ 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. -Version: 4.1.3 +Version: 4.2.1 Author: Automattic Author URI: https://automattic.com/wordpress-plugins/ License: GPLv2 or later @@ -37,8 +37,8 @@ if ( !function_exists( 'add_action' ) ) { exit; } -define( 'AKISMET_VERSION', '4.1.3' ); -define( 'AKISMET__MINIMUM_WP_VERSION', '4.0' ); +define( 'AKISMET_VERSION', '4.2.1' ); +define( 'AKISMET__MINIMUM_WP_VERSION', '5.0' ); define( 'AKISMET__PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'AKISMET_DELETE_LIMIT', 100000 ); diff --git a/plugins/akismet/changelog.txt b/plugins/akismet/changelog.txt new file mode 100644 index 00000000..680bc2e6 --- /dev/null +++ b/plugins/akismet/changelog.txt @@ -0,0 +1,465 @@ +=== Akismet Anti-Spam === + +== Archived Changelog Entries == + +This file contains older changelog entries, so we can keep the size of the standard WordPress readme.txt file reasonable. +For the latest changes, please see the "Changelog" section of the [readme.txt file](https://plugins.svn.wordpress.org/akismet/trunk/readme.txt). + += 4.1.5 = +*Release Date - 29 April 2020* + +* Based on user feedback, we have dropped the in-admin notice explaining the availability of the "privacy notice" option in the AKismet settings screen. The option itself is available, but after displaying the notice for the last 2 years, it is now considered a known fact. +* Updated the "Requires at least" to WP 4.6, based on recommendations from https://wp-info.org/tools/checkplugini18n.php?slug=akismet +* Moved older changelog entries to a separate file to keep the size of this readme reasonable, also based on recommendations from https://wp-info.org/tools/checkplugini18n.php?slug=akismet + += 4.1.4 = +*Release Date - 17 March 2020* + +* Only redirect to the Akismet setup screen upon plugin activation if the plugin was activated manually from within the plugin-related screens, to help users with non-standard install workflows, like WP-CLI. +* Update the layout of the initial setup screen to be more readable on small screens. +* If no API key has been entered, don't run code that expects an API key. +* Improve the readability of the comment history entries. +* Don't modify the comment form HTML if no API key has been set. + += 4.1.3 = +*Release Date - 31 October 2019* + +* Prevented an attacker from being able to cause a user to unknowingly recheck their Pending comments for spam. +* Improved compatibility with Jetpack 7.7+. +* Updated the plugin activation page to use consistent language and markup. +* Redirecting users to the Akismet connnection/settings screen upon plugin activation, in an effort to make it easier for people to get setup. + += 4.1.2 = +*Release Date - 14 May 2019* + +* Fixed a conflict between the Akismet setup banner and other plugin notices. +* Reduced the number of API requests made by the plugin when attempting to verify the API key. +* Include additional data in the pingback pre-check API request to help make the stats more accurate. +* Fixed a bug that was enabling the "Check for Spam" button when no comments were eligible to be checked. +* Improved Akismet's AMP compatibility. + += 4.1.1 = +*Release Date - 31 January 2019* + +* Fixed the "Setup Akismet" notice so it resizes responsively. +* Only highlight the "Save Changes" button in the Akismet config when changes have been made. +* The count of comments in your spam queue shown on the dashboard show now always be up-to-date. + += 4.1 = +*Release Date - 12 November 2018* + +* Added a WP-CLI method for retrieving stats. +* Hooked into the new "Personal Data Eraser" functionality from WordPress 4.9.6. +* Added functionality to clear outdated alerts from Akismet.com. + += 4.0.8 = +*Release Date - 19 June 2018* + +* Improved the grammar and consistency of the in-admin privacy related notes (notice and config). +* Revised in-admin explanation of the comment form privacy notice to make its usage clearer. +* Added `rel="nofollow noopener"` to the comment form privacy notice to improve SEO and security. + += 4.0.7 = +*Release Date - 28 May 2018* + +* Based on user feedback, the link on "Learn how your comment data is processed." in the optional privacy notice now has a `target` of `_blank` and opens in a new tab/window. +* Updated the in-admin privacy notice to use the term "comment" instead of "contact" in "Akismet can display a notice to your users under your comment forms." +* Only show in-admin privacy notice if Akismet has an API Key configured + += 4.0.6 = +*Release Date - 26 May 2018* + +* Moved away from using `empty( get_option() )` to instantiating a variable to be compatible with older versions of PHP (5.3, 5.4, etc). + += 4.0.5 = +*Release Date - 26 May 2018* + +* Corrected version number after tagging. Sorry... + += 4.0.4 = +*Release Date - 26 May 2018* + +* Added a hook to provide Akismet-specific privacy information for a site's privacy policy. +* Added tools to control the display of a privacy related notice under comment forms. +* Fixed HTML in activation failure message to close META and HEAD tag properly. +* Fixed a bug that would sometimes prevent Akismet from being correctly auto-configured. + += 4.0.3 = +*Release Date - 19 February 2018* + +* Added a scheduled task to remove entries in wp_commentmeta that no longer have corresponding comments in wp_comments. +* Added a new `akismet_batch_delete_count` action to the batch delete methods for people who'd like to keep track of the numbers of records being processed by those methods. + += 4.0.2 = +*Release Date - 18 December 2017* + +* Fixed a bug that could cause Akismet to recheck a comment that has already been manually approved or marked as spam. +* Fixed a bug that could cause Akismet to claim that some comments are still waiting to be checked when no comments are waiting to be checked. + += 4.0.1 = +*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. + += 4.0 = +*Release Date - 19 September 2017* + +* Added REST API endpoints for configuring Akismet and retrieving stats. +* Increased the minimum supported WordPress version to 4.0. +* Added compatibility with comments submitted via the REST API. +* Improved the progress indicator on the "Check for Spam" button. + += 3.3.4 = +*Release Date - 3 August 2017* + +* Disabled Akismet's debug log output by default unless AKISMET_DEBUG is defined. +* URL previews now begin preloading when the mouse moves near them in the comments section of wp-admin. +* When a comment is caught by the Comment Blacklist, Akismet will always allow it to stay in the trash even if it is spam as well. +* Fixed a bug that was preventing an error from being shown when a site can't reach Akismet's servers. + += 3.3.3 = +*Release Date - 13 July 2017* + +* Reduced amount of bandwidth used by the URL Preview feature. +* Improved the admin UI when the API key is manually pre-defined for the site. +* Removed a workaround for WordPress installations older than 3.3 that will improve Akismet's compatibility with other plugins. +* The number of spam blocked that is displayed on the WordPress dashboard will now be more accurate and updated more frequently. +* Fixed a bug in the Akismet widget that could cause PHP warnings. + += 3.3.2 = +*Release Date - 10 May 2017* + +* Fixed a bug causing JavaScript errors in some browsers. + += 3.3.1 = +*Release Date - 2 May 2017* + +* Improve performance by only requesting the akismet_comment_nonce option when absolutely necessary. +* Fixed two bugs that could cause PHP warnings. +* Fixed a bug that was preventing the "Remove author URL" feature from working after a comment was edited using "Quick Edit." +* Fixed a bug that was preventing the URL preview feature from working after a comment was edited using "Quick Edit." + += 3.3 = +*Release Date - 23 February 2017* + +* Updated the Akismet admin pages with a new clean design. +* Fixed bugs preventing the `akismet_add_comment_nonce` and `akismet_update_alert` wrapper functions from working properly. +* Fixed bug preventing the loading indicator from appearing when re-checking all comments for spam. +* Added a progress indicator to the "Check for Spam" button. +* Added a success message after manually rechecking the Pending queue for spam. + += 3.2 = +*Release Date - 6 September 2016* + +* Added a WP-CLI module. You can now check comments and recheck the moderation queue from the command line. +* Stopped using the deprecated jQuery function `.live()`. +* Fixed a bug in `remove_comment_author_url()` and `add_comment_author_url()` that could generate PHP notices. +* Fixed a bug that could cause an infinite loop for sites with very very very large comment IDs. +* Fixed a bug that could cause the Akismet widget title to be blank. + += 3.1.11 = +*Release Date - 12 May 2016* + +* Fixed a bug that could cause the "Check for Spam" button to skip some comments. +* Fixed a bug that could prevent some spam submissions from being sent to Akismet. +* Updated all links to use https:// when possible. +* Disabled Akismet debug logging unless WP_DEBUG and WP_DEBUG_LOG are both enabled. + += 3.1.10 = +*Release Date - 1 April 2016* + +* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue. +* Fixed a bug that could have resulted in comments that were caught by the core WordPress comment blacklist not to have a corresponding History entry. +* Fixed a bug that could have caused avoidable PHP warnings in the error log. + += 3.1.9 = +*Release Date - 28 March 2016* + +* Add compatibility with Jetpack so that Jetpack can automatically configure Akismet settings when appropriate. +* Fixed a bug preventing some comment data from being sent to Akismet. + += 3.1.8 = +*Release Date - 4 March 2016* + +* Fixed a bug preventing Akismet from being used with some plugins that rewrite admin URLs. +* Reduced the amount of bandwidth used on Akismet API calls +* Reduced the amount of space Akismet uses in the database +* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue. + += 3.1.7 = +*Release Date - 4 January 2016* + +* Added documentation for the 'akismet_comment_nonce' filter. +* The post-install activation button is now accessible to screen readers and keyboard-only users. +* Fixed a bug that was preventing the "Remove author URL" feature from working in WordPress 4.4 + += 3.1.6 = +*Release Date - 14 December 2015* + +* Improve the notices shown after activating Akismet. +* Update some strings to allow for the proper plural forms in all languages. + += 3.1.5 = +*Release Date - 13 October 2015* + +* Closes a potential XSS vulnerability. + += 3.1.4 = +*Release Date - 24 September 2015* + +* Fixed a bug that was preventing some users from automatically connecting using Jetpack if they didn't have a current Akismet subscription. +* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue. +* Error messages and instructions have been simplified to be more understandable. +* Link previews are enabled for all links inside comments, not just the author's website link. + += 3.1.3 = +*Release Date - 6 July 2015* + +* Notify users when their account status changes after previously being successfully set up. This should help any users who are seeing blank Akismet settings screens. + += 3.1.2 = +*Release Date - 7 June 2015* + +* Reduced the amount of space Akismet uses in the commentmeta table. +* Fixed a bug where some comments with quotes in the author name weren't getting history entries +* Pre-emptive security improvements to ensure that the Akismet plugin can't be used by attackers to compromise a WordPress installation. +* Better UI for the key entry field: allow whitespace to be included at the beginning or end of the key and strip it out automatically when the form is submitted. +* When deactivating the plugin, notify the Akismet API so the site can be marked as inactive. +* Clearer error messages. + += 3.1.1 = +*Release Date - 17th March, 2015* + +* Improvements to the "Remove comment author URL" JavaScript +* Include the pingback pre-check from the 2.6 branch. + += 3.1 = +*Release Date - 11th March, 2015* + +* Use HTTPS by default for all requests to Akismet. +* Fix for a situation where Akismet might strip HTML from a comment. + += 3.0.4 = +*Release Date - 11th December, 2014* + +* Fix to make .htaccess compatible with Apache 2.4. +* Fix to allow removal of https author URLs. +* Fix to avoid stripping part of the author URL when removing and re-adding. +* Removed the "Check for Spam" button from the "Trash" and "Approved" queues, where it would have no effect. +* Allow automatic API key configuration when Jetpack is installed and connected to a WordPress.com account + += 3.0.3 = +*Release Date - 3rd November, 2014* + +* Fix for sending the wrong data to delete_comment action that could have prevented old spam comments from being deleted. +* Added a filter to disable logging of Akismet debugging information. +* Added a filter for the maximum comment age when deleting old spam comments. +* Added a filter for the number per batch when deleting old spam comments. +* Removed the "Check for Spam" button from the Spam folder. + += 3.0.2 = +*Release Date - 18th August, 2014* + +* Performance improvements. +* Fixed a bug that could truncate the comment data being sent to Akismet for checking. + += 3.0.1 = +*Release Date - 9th July, 2014* + +* Removed dependency on PHP's fsockopen function +* Fix spam/ham reports to work when reported outside of the WP dashboard, e.g., from Notifications or the WP app +* Remove jQuery dependency for comment form JavaScript +* Remove unnecessary data from some Akismet comment meta +* Suspended keys will now result in all comments being put in moderation, not spam. + += 3.0.0 = +*Release Date - 15th April, 2014* + +* Move Akismet to Settings menu +* Drop Akismet Stats menu +* Add stats snapshot to Akismet settings +* Add Akismet subscription details and status to Akismet settings +* Add contextual help for each page +* Improve Akismet setup to use Jetpack to automate plugin setup +* Fix "Check for Spam" to use AJAX to avoid page timing out +* Fix Akismet settings page to be responsive +* Drop legacy code +* Tidy up CSS and Javascript +* Replace the old discard setting with a new "discard pervasive spam" feature. + += 2.6.0 = +*Release Date - 18th March, 2014* + +* 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 + += 2.5.9 = +*Release Date - 1st August, 2013* + +* Update 'Already have a key' link to redirect page rather than depend on javascript +* Fix some non-translatable strings to be translatable +* Update Activation banner in plugins page to redirect user to Akismet config page + += 2.5.8 = +*Release Date - 20th January, 2013* + +* Simplify the activation process for new users +* Remove the reporter_ip parameter +* Minor preventative security improvements + += 2.5.7 = +*Release Date - 13th December, 2012* + +* FireFox Stats iframe preview bug +* Fix mshots preview when using https +* Add .htaccess to block direct access to files +* Prevent some PHP notices +* Fix Check For Spam return location when referrer is empty +* Fix Settings links for network admins +* Fix prepare() warnings in WP 3.5 + += 2.5.6 = +*Release Date - 26th April, 2012* + +* Prevent retry scheduling problems on sites where wp_cron is misbehaving +* Preload mshot previews +* Modernize the widget code +* Fix a bug where comments were not held for moderation during an error condition +* Improve the UX and display when comments are temporarily held due to an error +* Make the Check For Spam button force a retry when comments are held due to an error +* Handle errors caused by an invalid key +* Don't retry comments that are too old +* Improve error messages when verifying an API key + += 2.5.5 = +*Release Date - 11th January, 2012* + +* Add nonce check for comment author URL remove action +* Fix the settings link + += 2.5.4 = +*Release Date - 5th January, 2012* + +* Limit Akismet CSS and Javascript loading in wp-admin to just the pages that need it +* Added author URL quick removal functionality +* Added mShot preview on Author URL hover +* Added empty index.php to prevent directory listing +* Move wp-admin menu items under Jetpack, if it is installed +* Purge old Akismet comment meta data, default of 15 days + += 2.5.3 = +*Release Date - 8th Febuary, 2011* + +* Specify the license is GPL v2 or later +* Fix a bug that could result in orphaned commentmeta entries +* Include hotfix for WordPress 3.0.5 filter issue + += 2.5.2 = +*Release Date - 14th January, 2011* + +* Properly format the comment count for author counts +* Look for super admins on multisite installs when looking up user roles +* Increase the HTTP request timeout +* Removed padding for author approved count +* Fix typo in function name +* Set Akismet stats iframe height to fixed 2500px. Better to have one tall scroll bar than two side by side. + += 2.5.1 = +*Release Date - 17th December, 2010* + +* Fix a bug that caused the "Auto delete" option to fail to discard comments correctly +* Remove the comment nonce form field from the 'Akismet Configuration' page in favor of using a filter, akismet_comment_nonce +* Fixed padding bug in "author" column of posts screen +* Added margin-top to "cleared by ..." badges on dashboard +* Fix possible error when calling akismet_cron_recheck() +* Fix more PHP warnings +* Clean up XHTML warnings for comment nonce +* Fix for possible condition where scheduled comment re-checks could get stuck +* Clean up the comment meta details after deleting a comment +* Only show the status badge if the comment status has been changed by someone/something other than Akismet +* Show a 'History' link in the row-actions +* Translation fixes +* Reduced font-size on author name +* Moved "flagged by..." notification to top right corner of comment container and removed heavy styling +* Hid "flagged by..." notification while on dashboard + += 2.5.0 = +*Release Date - 7th December, 2010* + +* Track comment actions under 'Akismet Status' on the edit comment screen +* Fix a few remaining deprecated function calls ( props Mike Glendinning ) +* Use HTTPS for the stats IFRAME when wp-admin is using HTTPS +* Use the WordPress HTTP class if available +* Move the admin UI code to a separate file, only loaded when needed +* Add cron retry feature, to replace the old connectivity check +* Display Akismet status badge beside each comment +* Record history for each comment, and display it on the edit page +* Record the complete comment as originally submitted in comment_meta, to use when reporting spam and ham +* Highlight links in comment content +* New option, "Show the number of comments you've approved beside each comment author." +* New option, "Use a nonce on the comment form." + += 2.4.0 = +*Release Date - 23rd August, 2010* + +* Spell out that the license is GPLv2 +* Fix PHP warnings +* Fix WordPress deprecated function calls +* Fire the delete_comment action when deleting comments +* Move code specific for older WP versions to legacy.php +* General code clean up + += 2.3.0 = +*Release Date - 5th June, 2010* + +* Fix "Are you sure" nonce message on config screen in WPMU +* Fix XHTML compliance issue in sidebar widget +* Change author link; remove some old references to WordPress.com accounts +* Localize the widget title (core ticket #13879) + += 2.2.9 = +*Release Date - 2nd June, 2010* + +* Eliminate a potential conflict with some plugins that may cause spurious reports + += 2.2.8 = +*Release Date - 27th May, 2010* + +* Fix bug in initial comment check for ipv6 addresses +* Report comments as ham when they are moved from spam to moderation +* Report comments as ham when clicking undo after spam +* Use transition_comment_status action when available instead of older actions for spam/ham submissions +* Better diagnostic messages when PHP network functions are unavailable +* Better handling of comments by logged-in users + += 2.2.7 = +*Release Date - 17th December, 2009* + +* Add a new AKISMET_VERSION constant +* Reduce the possibility of over-counting spam when another spam filter plugin is in use +* Disable the connectivity check when the API key is hard-coded for WPMU + += 2.2.6 = +*Release Date - 20th July, 2009* + +* Fix a global warning introduced in 2.2.5 +* Add changelog and additional readme.txt tags +* Fix an array conversion warning in some versions of PHP +* Support a new WPCOM_API_KEY constant for easier use with WordPress MU + += 2.2.5 = +*Release Date - 13th July, 2009* + +* Include a new Server Connectivity diagnostic check, to detect problems caused by firewalls + += 2.2.4 = +*Release Date - 3rd June, 2009* + +* Fixed a key problem affecting the stats feature in WordPress MU +* Provide additional blog information in Akismet API calls diff --git a/plugins/akismet/class.akismet-admin.php b/plugins/akismet/class.akismet-admin.php index b5e2ef8e..c6cb1355 100644 --- a/plugins/akismet/class.akismet-admin.php +++ b/plugins/akismet/class.akismet-admin.php @@ -32,10 +32,6 @@ class Akismet_Admin { if ( isset( $_POST['action'] ) && $_POST['action'] == 'enter-key' ) { self::enter_api_key(); } - - if ( ! empty( $_GET['akismet_comment_form_privacy_notice'] ) && empty( $_GET['settings-updated']) ) { - self::set_form_privacy_notice_option( $_GET['akismet_comment_form_privacy_notice'] ); - } } public static function init_hooks() { @@ -70,11 +66,6 @@ class Akismet_Admin { add_filter( 'all_plugins', array( 'Akismet_Admin', 'modify_plugin_description' ) ); - if ( class_exists( 'Jetpack' ) ) { - add_filter( 'akismet_comment_form_privacy_notice_url_display', array( 'Akismet_Admin', 'jetpack_comment_form_privacy_notice_url' ) ); - add_filter( 'akismet_comment_form_privacy_notice_url_hide', array( 'Akismet_Admin', 'jetpack_comment_form_privacy_notice_url' ) ); - } - // priority=1 because we need ours to run before core's comment anonymizer runs, and that's registered at priority=10 add_filter( 'wp_privacy_personal_data_erasers', array( 'Akismet_Admin', 'register_personal_data_eraser' ), 1 ); } @@ -146,7 +137,7 @@ class Akismet_Admin { wp_register_script( 'akismet.js', plugin_dir_url( __FILE__ ) . '_inc/akismet.js', array('jquery'), AKISMET_VERSION ); wp_enqueue_script( 'akismet.js' ); - + $inline_js = array( 'comment_author_url_nonce' => wp_create_nonce( 'comment_author_url_nonce' ), 'strings' => array( @@ -162,6 +153,10 @@ class Akismet_Admin { $inline_js['start_recheck'] = true; } + if ( apply_filters( 'akismet_enable_mshots', true ) ) { + $inline_js['enable_mshots'] = true; + } + wp_localize_script( 'akismet.js', 'WPAkismet', $inline_js ); } } @@ -392,27 +387,40 @@ class Akismet_Admin { return; } - $link = add_query_arg( array( 'action' => 'akismet_recheck_queue' ), admin_url( 'admin.php' ) ); + $link = ''; $comments_count = wp_count_comments(); echo '</div>'; echo '<div class="alignleft actions">'; + + $classes = array( + 'button-secondary', + 'checkforspam', + 'button-disabled' // Disable button until the page is loaded + ); + + if ( $comments_count->moderated > 0 ) { + $classes[] = 'enable-on-load'; + + if ( ! Akismet::get_api_key() ) { + $link = add_query_arg( array( 'page' => 'akismet-key-config' ), class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'options-general.php' ) ); + $classes[] = 'ajax-disabled'; + } + } + echo '<a - class="button-secondary checkforspam' . ( $comments_count->moderated == 0 ? ' button-disabled' : '' ) . '" - href="' . esc_url( $link ) . '" - data-active-label="' . esc_attr( __( 'Checking for Spam', 'akismet' ) ) . '" - data-progress-label-format="' . esc_attr( __( '(%1$s%)', 'akismet' ) ) . '" + class="' . esc_attr( implode( ' ', $classes ) ) . '"' . + ( ! empty( $link ) ? ' href="' . esc_url( $link ) . '"' : '' ) . + /* translators: The placeholder is for showing how much of the process has completed, as a percent. e.g., "Checking for Spam (40%)" */ + ' data-progress-label="' . esc_attr( __( 'Checking for Spam (%1$s%)', 'akismet' ) ) . '" data-success-url="' . esc_attr( remove_query_arg( array( 'akismet_recheck', 'akismet_recheck_error' ), add_query_arg( array( 'akismet_recheck_complete' => 1, 'recheck_count' => urlencode( '__recheck_count__' ), 'spam_count' => urlencode( '__spam_count__' ) ) ) ) ) . '" data-failure-url="' . esc_attr( remove_query_arg( array( 'akismet_recheck', 'akismet_recheck_complete' ), add_query_arg( array( 'akismet_recheck_error' => 1 ) ) ) ) . '" data-pending-comment-count="' . esc_attr( $comments_count->moderated ) . '" data-nonce="' . esc_attr( wp_create_nonce( 'akismet_check_for_spam' ) ) . '" - >'; - echo '<span class="akismet-label">' . esc_html__('Check for Spam', 'akismet') . '</span>'; - echo '<span class="checkforspam-progress"></span>'; - echo '</a>'; + ' . ( ! in_array( 'ajax-disabled', $classes ) ? 'onclick="return false;"' : '' ) . ' + >' . esc_html__('Check for Spam', 'akismet') . '</a>'; echo '<span class="checkforspam-spinner"></span>'; - } public static function recheck_queue() { @@ -575,10 +583,8 @@ class Akismet_Admin { $history = Akismet::get_comment_history( $comment->comment_ID ); if ( $history ) { - echo '<div class="akismet-history" style="margin: 13px;">'; - foreach ( $history as $row ) { - $time = date( 'D d M Y @ h:i:m a', $row['time'] ) . ' GMT'; + $time = date( 'D d M Y @ h:i:s a', $row['time'] ) . ' GMT'; $message = ''; @@ -588,56 +594,67 @@ class Akismet_Admin { // 1) Save space. // 2) The message can be translated into the current language of the blog, not stuck // in the language of the blog when the comment was made. - $message = $row['message']; + $message = esc_html( $row['message'] ); } // If possible, use a current translation. switch ( $row['event'] ) { case 'recheck-spam'; - $message = __( 'Akismet re-checked and caught this comment as spam.', 'akismet' ); + $message = esc_html( __( 'Akismet re-checked and caught this comment as spam.', 'akismet' ) ); break; case 'check-spam': - $message = __( 'Akismet caught this comment as spam.', 'akismet' ); + $message = esc_html( __( 'Akismet caught this comment as spam.', 'akismet' ) ); break; case 'recheck-ham': - $message = __( 'Akismet re-checked and cleared this comment.', 'akismet' ); + $message = esc_html( __( 'Akismet re-checked and cleared this comment.', 'akismet' ) ); break; case 'check-ham': - $message = __( 'Akismet cleared this comment.', 'akismet' ); + $message = esc_html( __( 'Akismet cleared this comment.', 'akismet' ) ); break; case 'wp-blacklisted': - $message = __( 'Comment was caught by wp_blacklist_check.', 'akismet' ); + case 'wp-disallowed': + $message = sprintf( + /* translators: The placeholder is a WordPress PHP function name. */ + esc_html( __( 'Comment was caught by %s.', 'akismet' ) ), + function_exists( 'wp_check_comment_disallowed_list' ) ? '<code>wp_check_comment_disallowed_list</code>' : '<code>wp_blacklist_check</code>' + ); break; case 'report-spam': if ( isset( $row['user'] ) ) { - $message = sprintf( __( '%s reported this comment as spam.', 'akismet' ), $row['user'] ); + $message = esc_html( sprintf( __( '%s reported this comment as spam.', 'akismet' ), $row['user'] ) ); } else if ( ! $message ) { - $message = __( 'This comment was reported as spam.', 'akismet' ); + $message = esc_html( __( 'This comment was reported as spam.', 'akismet' ) ); } break; case 'report-ham': if ( isset( $row['user'] ) ) { - $message = sprintf( __( '%s reported this comment as not spam.', 'akismet' ), $row['user'] ); + $message = esc_html( sprintf( __( '%s reported this comment as not spam.', 'akismet' ), $row['user'] ) ); } else if ( ! $message ) { - $message = __( 'This comment was reported as not spam.', 'akismet' ); + $message = esc_html( __( 'This comment was reported as not spam.', 'akismet' ) ); } break; case 'cron-retry-spam': - $message = __( 'Akismet caught this comment as spam during an automatic retry.' , 'akismet'); + $message = esc_html( __( 'Akismet caught this comment as spam during an automatic retry.' , 'akismet') ); break; case 'cron-retry-ham': - $message = __( 'Akismet cleared this comment during an automatic retry.', 'akismet'); + $message = esc_html( __( 'Akismet cleared this comment during an automatic retry.', 'akismet') ); break; case 'check-error': if ( isset( $row['meta'], $row['meta']['response'] ) ) { - $message = sprintf( __( 'Akismet was unable to check this comment (response: %s) but will automatically retry later.', 'akismet'), $row['meta']['response'] ); + $message = sprintf( esc_html( __( 'Akismet was unable to check this comment (response: %s) but will automatically retry later.', 'akismet') ), '<code>' . esc_html( $row['meta']['response'] ) . '</code>' ); + } + else { + $message = esc_html( __( 'Akismet was unable to check this comment but will automatically retry later.', 'akismet' ) ); } break; case 'recheck-error': if ( isset( $row['meta'], $row['meta']['response'] ) ) { - $message = sprintf( __( 'Akismet was unable to recheck this comment (response: %s).', 'akismet'), $row['meta']['response'] ); + $message = sprintf( esc_html( __( 'Akismet was unable to recheck this comment (response: %s).', 'akismet') ), '<code>' . esc_html( $row['meta']['response'] ) . '</code>' ); + } + else { + $message = esc_html( __( 'Akismet was unable to recheck this comment.', 'akismet' ) ); } break; default: @@ -645,27 +662,32 @@ class Akismet_Admin { // Half of these used to be saved without the dash after 'status-changed'. // See https://plugins.trac.wordpress.org/changeset/1150658/akismet/trunk $new_status = preg_replace( '/^status-changed-?/', '', $row['event'] ); - $message = sprintf( __( 'Comment status was changed to %s', 'akismet' ), $new_status ); + $message = sprintf( esc_html( __( 'Comment status was changed to %s', 'akismet' ) ), '<code>' . esc_html( $new_status ) . '</code>' ); } else if ( preg_match( '/^status-/', $row['event'] ) ) { $new_status = preg_replace( '/^status-/', '', $row['event'] ); if ( isset( $row['user'] ) ) { - $message = sprintf( __( '%1$s changed the comment status to %2$s.', 'akismet' ), $row['user'], $new_status ); + $message = sprintf( esc_html( __( '%1$s changed the comment status to %2$s.', 'akismet' ) ), $row['user'], '<code>' . esc_html( $new_status ) . '</code>' ); } } break; } - echo '<div style="margin-bottom: 13px;">'; + if ( ! empty( $message ) ) { + echo '<p>'; echo '<span style="color: #999;" alt="' . $time . '" title="' . $time . '">' . sprintf( esc_html__('%s ago', 'akismet'), human_time_diff( $row['time'] ) ) . '</span>'; echo ' - '; - echo esc_html( $message ); - echo '</div>'; + echo $message; // esc_html() is done above so that we can use HTML in some messages. + echo '</p>'; + } } - - echo '</div>'; + } + else { + echo '<p>'; + echo esc_html( __( 'No comment history.', 'akismet' ) ); + echo '</p>'; } } @@ -866,12 +888,21 @@ class Akismet_Admin { ) ); } - public static function display_privacy_notice_control_warning() { - if ( !current_user_can( 'manage_options' ) ) - return; - Akismet::view( 'notice', array( - 'type' => 'privacy', - ) ); + public static function get_usage_limit_alert_data() { + return array( + 'type' => 'usage-limit', + 'code' => (int) get_option( 'akismet_alert_code' ), + 'msg' => get_option( 'akismet_alert_msg' ), + 'api_calls' => get_option( 'akismet_alert_api_calls' ), + 'usage_limit' => get_option( 'akismet_alert_usage_limit' ), + 'upgrade_plan' => get_option( 'akismet_alert_upgrade_plan' ), + 'upgrade_url' => get_option( 'akismet_alert_upgrade_url' ), + 'upgrade_type' => get_option( 'akismet_alert_upgrade_type' ), + ); + } + + public static function display_usage_limit_alert() { + Akismet::view( 'notice', self::get_usage_limit_alert_data() ); } public static function display_spam_check_warning() { @@ -1007,8 +1038,9 @@ class Akismet_Admin { $notices[] = array( 'type' => $akismet_user->status ); } - if ( false === get_option( 'akismet_comment_form_privacy_notice' ) ) { - $notices[] = array( 'type' => 'privacy' ); + $alert_code = get_option( 'akismet_alert_code' ); + if ( isset( Akismet::$limit_notices[ $alert_code ] ) ) { + $notices[] = self::get_usage_limit_alert_data(); } /* @@ -1030,6 +1062,7 @@ class Akismet_Admin { $notices[] = array( 'type' => 'new-key-failed' ); $notices[] = array( 'type' => 'limit-reached', 'level' => 'yellow' ); $notices[] = array( 'type' => 'limit-reached', 'level' => 'red' ); + $notices[] = array( 'type' => 'usage-limit', 'api_calls' => '15000', 'usage_limit' => '10000', 'upgrade_plan' => 'Enterprise', 'upgrade_url' => 'https://akismet.com/account/' ); */ Akismet::log( compact( 'stat_totals', 'akismet_user' ) ); @@ -1046,22 +1079,28 @@ class Akismet_Admin { if ( in_array( $hook_suffix, array( 'edit-comments.php' ) ) && (int) get_option( 'akismet_alert_code' ) > 0 ) { Akismet::verify_key( Akismet::get_api_key() ); //verify that the key is still in alert state - - if ( get_option( 'akismet_alert_code' ) > 0 ) + + $alert_code = get_option( 'akismet_alert_code' ); + if ( isset( Akismet::$limit_notices[ $alert_code ] ) ) { + self::display_usage_limit_alert(); + } elseif ( $alert_code > 0 ) { self::display_alert(); + } } - elseif ( $hook_suffix == 'plugins.php' && !Akismet::get_api_key() ) { + elseif ( ( 'plugins.php' === $hook_suffix || 'edit-comments.php' === $hook_suffix ) && ! Akismet::get_api_key() ) { + // Show the "Set Up Akismet" banner on the comments and plugin pages if no API key has been set. self::display_api_key_warning(); } elseif ( $hook_suffix == 'edit-comments.php' && wp_next_scheduled( 'akismet_schedule_cron_recheck' ) ) { self::display_spam_check_warning(); } - else if ( isset( $_GET['akismet_recheck_complete'] ) ) { + + if ( isset( $_GET['akismet_recheck_complete'] ) ) { $recheck_count = (int) $_GET['recheck_count']; $spam_count = (int) $_GET['spam_count']; if ( $recheck_count === 0 ) { - $message = __( 'There were no comments to check. Akismet will only check comments in the Pending queue.', 'akismet' ); + $message = __( 'There were no comments to check. Akismet will only check comments awaiting moderation.', 'akismet' ); } else { $message = sprintf( _n( 'Akismet checked %s comment.', 'Akismet checked %s comments.', $recheck_count, 'akismet' ), number_format( $recheck_count ) ); @@ -1080,14 +1119,6 @@ class Akismet_Admin { else if ( isset( $_GET['akismet_recheck_error'] ) ) { echo '<div class="notice notice-error"><p>' . esc_html( __( 'Akismet could not recheck your comments for spam.', 'akismet' ) ) . '</p></div>'; } - - $akismet_comment_form_privacy_notice_option = get_option( 'akismet_comment_form_privacy_notice' ); - if ( ! in_array( $akismet_comment_form_privacy_notice_option, array( 'hide', 'display' ) ) ) { - $api_key = Akismet::get_api_key(); - if ( ! empty( $api_key ) ) { - self::display_privacy_notice_control_warning(); - } - } } public static function display_status() { @@ -1127,7 +1158,7 @@ class Akismet_Admin { if ( !class_exists('Jetpack') ) return false; - if ( defined( 'JETPACK__VERSION' ) && version_compare( JETPACK__VERSION, '7.7', '<' ) ) { + if ( defined( 'JETPACK__VERSION' ) && version_compare( JETPACK__VERSION, '7.7', '<' ) ) { // For version of Jetpack prior to 7.7. Jetpack::load_xml_rpc_client(); } @@ -1202,10 +1233,6 @@ class Akismet_Admin { update_option( 'akismet_comment_form_privacy_notice', $state ); } } - - public static function jetpack_comment_form_privacy_notice_url( $url ) { - return str_replace( 'options-general.php', 'admin.php', $url ); - } public static function register_personal_data_eraser( $erasers ) { $erasers['akismet'] = array( diff --git a/plugins/akismet/class.akismet-widget.php b/plugins/akismet/class.akismet-widget.php index 55b0f35c..9f0458b0 100644 --- a/plugins/akismet/class.akismet-widget.php +++ b/plugins/akismet/class.akismet-widget.php @@ -99,7 +99,29 @@ class Akismet_Widget extends WP_Widget { ?> <div class="a-stats"> - <a href="https://akismet.com" target="_blank" title=""><?php printf( _n( '<strong class="count">%1$s spam</strong> blocked by <strong>Akismet</strong>', '<strong class="count">%1$s spam</strong> blocked by <strong>Akismet</strong>', $count , 'akismet'), number_format_i18n( $count ) ); ?></a> + <a href="https://akismet.com" target="_blank" rel="noopener" title=""> + <?php + + echo wp_kses( + sprintf( + /* translators: The placeholder is the number of pieces of spam blocked by Akismet. */ + _n( + '<strong class="count">%1$s spam</strong> blocked by <strong>Akismet</strong>', + '<strong class="count">%1$s spam</strong> blocked by <strong>Akismet</strong>', + $count, + 'akismet' + ), + number_format_i18n( $count ) + ), + array( + 'strong' => array( + 'class' => true, + ), + ) + ); + + ?> + </a> </div> <?php diff --git a/plugins/akismet/class.akismet.php b/plugins/akismet/class.akismet.php index 01753014..1681d0e1 100644 --- a/plugins/akismet/class.akismet.php +++ b/plugins/akismet/class.akismet.php @@ -5,12 +5,19 @@ class Akismet { const API_PORT = 80; const MAX_DELAY_BEFORE_MODERATION_EMAIL = 86400; // One day in seconds + public static $limit_notices = array( + 10501 => 'FIRST_MONTH_OVER_LIMIT', + 10502 => 'SECOND_MONTH_OVER_LIMIT', + 10504 => 'THIRD_MONTH_APPROACHING_LIMIT', + 10508 => 'THIRD_MONTH_OVER_LIMIT', + 10516 => 'FOUR_PLUS_MONTHS_OVER_LIMIT', + ); + private static $last_comment = ''; private static $initiated = false; private static $prevent_moderation_email_for_these_comments = array(); private static $last_comment_result = null; 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' => '' ); - private static $is_rest_api_call = false; public static function init() { if ( ! self::$initiated ) { @@ -34,11 +41,7 @@ class Akismet { add_action( 'akismet_schedule_cron_recheck', array( 'Akismet', 'cron_recheck' ) ); add_action( 'comment_form', array( 'Akismet', 'add_comment_nonce' ), 1 ); - - add_action( 'admin_head-edit-comments.php', array( 'Akismet', 'load_form_js' ) ); - add_action( 'comment_form', array( 'Akismet', 'load_form_js' ) ); - add_action( 'comment_form', array( 'Akismet', 'inject_ak_js' ) ); - add_filter( 'script_loader_tag', array( 'Akismet', 'set_form_js_async' ), 10, 3 ); + add_action( 'comment_form', array( 'Akismet', 'output_custom_form_fields' ) ); add_filter( 'comment_moderation_recipients', array( 'Akismet', 'disable_moderation_emails_if_unreachable' ), 1000, 2 ); add_filter( 'pre_comment_approved', array( 'Akismet', 'last_comment_status' ), 10, 2 ); @@ -47,9 +50,20 @@ class Akismet { // Run this early in the pingback call, before doing a remote fetch of the source uri add_action( 'xmlrpc_call', array( 'Akismet', 'pre_check_pingback' ) ); - + // Jetpack compatibility add_filter( 'jetpack_options_whitelist', array( 'Akismet', 'add_to_jetpack_options_whitelist' ) ); + add_filter( 'jetpack_contact_form_html', array( 'Akismet', 'inject_custom_form_fields' ) ); + add_filter( 'jetpack_contact_form_akismet_values', array( 'Akismet', 'prepare_custom_form_values' ) ); + + // Gravity Forms + add_filter( 'gform_get_form_filter', array( 'Akismet', 'inject_custom_form_fields' ) ); + add_filter( 'gform_akismet_fields', array( 'Akismet', 'prepare_custom_form_values' ) ); + + // Contact Form 7 + add_filter( 'wpcf7_form_elements', array( 'Akismet', 'append_custom_form_fields' ) ); + add_filter( 'wpcf7_akismet_parameters', array( 'Akismet', 'prepare_custom_form_values' ) ); + add_action( 'update_option_wordpress_api_key', array( 'Akismet', 'updated_option' ), 10, 2 ); add_action( 'add_option_wordpress_api_key', array( 'Akismet', 'added_option' ), 10, 2 ); @@ -131,12 +145,23 @@ class Akismet { } public static function rest_auto_check_comment( $commentdata ) { - self::$is_rest_api_call = true; - - return self::auto_check_comment( $commentdata ); + return self::auto_check_comment( $commentdata, 'rest_api' ); } - public static function auto_check_comment( $commentdata ) { + /** + * Check a comment for spam. + * + * @param array $commentdata + * @param string $context What kind of request triggered this comment check? Possible values are 'default', 'rest_api', and 'xml-rpc'. + * @return array|WP_Error Either the $commentdata array with additional entries related to its spam status + * or a WP_Error, if it's a REST API request and the comment should be discarded. + */ + public static function auto_check_comment( $commentdata, $context = 'default' ) { + // If no key is configured, then there's no point in doing any of this. + if ( ! self::get_api_key() ) { + return $commentdata; + } + self::$last_comment_result = null; $comment = $commentdata; @@ -202,7 +227,15 @@ class Akismet { do_action( 'akismet_comment_check_response', $response ); $commentdata['comment_as_submitted'] = array_intersect_key( $comment, self::$comment_as_submitted_allowed_keys ); - $commentdata['akismet_result'] = $response[1]; + + // Also include any form fields we inject into the comment form, like ak_js + foreach ( $_POST as $key => $value ) { + if ( is_string( $value ) && strpos( $key, 'ak_' ) === 0 ) { + $commentdata['comment_as_submitted'][ 'POST_' . $key ] = $value; + } + } + + $commentdata['akismet_result'] = $response[1]; if ( isset( $response[0]['x-akismet-pro-tip'] ) ) $commentdata['akismet_pro_tip'] = $response[0]['x-akismet-pro-tip']; @@ -227,17 +260,19 @@ class Akismet { update_option( 'akismet_spam_count', get_option( 'akismet_spam_count' ) + $incr ); } - if ( self::$is_rest_api_call ) { + if ( 'rest_api' === $context ) { return new WP_Error( 'akismet_rest_comment_discarded', __( 'Comment discarded.', 'akismet' ) ); - } - else { + } else if ( 'xml-rpc' === $context ) { + // If this is a pingback that we're pre-checking, the discard behavior is the same as the normal spam response behavior. + return $commentdata; + } else { // Redirect back to the previous page, or failing that, the post permalink, or failing that, the homepage of the blog. $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : ( $post ? get_permalink( $post ) : home_url() ); wp_safe_redirect( esc_url_raw( $redirect_to ) ); die(); } } - else if ( self::$is_rest_api_call ) { + else if ( 'rest_api' === $context ) { // The way the REST API structures its calls, we can set the comment_approved value right away. $commentdata['comment_approved'] = 'spam'; } @@ -296,48 +331,56 @@ class Akismet { // as was checked by auto_check_comment if ( is_object( $comment ) && !empty( self::$last_comment ) && is_array( self::$last_comment ) ) { if ( self::matches_last_comment( $comment ) ) { - - load_plugin_textdomain( 'akismet' ); - - // normal result: true or false - if ( self::$last_comment['akismet_result'] == 'true' ) { - update_comment_meta( $comment->comment_ID, 'akismet_result', 'true' ); - self::update_comment_history( $comment->comment_ID, '', 'check-spam' ); - if ( $comment->comment_approved != 'spam' ) - self::update_comment_history( - $comment->comment_ID, - '', - 'status-changed-'.$comment->comment_approved - ); - } - elseif ( self::$last_comment['akismet_result'] == 'false' ) { - update_comment_meta( $comment->comment_ID, 'akismet_result', 'false' ); - self::update_comment_history( $comment->comment_ID, '', 'check-ham' ); - // Status could be spam or trash, depending on the WP version and whether this change applies: - // https://core.trac.wordpress.org/changeset/34726 - if ( $comment->comment_approved == 'spam' || $comment->comment_approved == 'trash' ) { - if ( wp_blacklist_check($comment->comment_author, $comment->comment_author_email, $comment->comment_author_url, $comment->comment_content, $comment->comment_author_IP, $comment->comment_agent) ) - self::update_comment_history( $comment->comment_ID, '', 'wp-blacklisted' ); - else - self::update_comment_history( $comment->comment_ID, '', 'status-changed-'.$comment->comment_approved ); - } - } // abnormal result: error - else { - update_comment_meta( $comment->comment_ID, 'akismet_error', time() ); + load_plugin_textdomain( 'akismet' ); + + // normal result: true or false + if ( self::$last_comment['akismet_result'] == 'true' ) { + update_comment_meta( $comment->comment_ID, 'akismet_result', 'true' ); + self::update_comment_history( $comment->comment_ID, '', 'check-spam' ); + if ( $comment->comment_approved != 'spam' ) { self::update_comment_history( $comment->comment_ID, '', - 'check-error', - array( 'response' => substr( self::$last_comment['akismet_result'], 0, 50 ) ) + 'status-changed-' . $comment->comment_approved ); } + } elseif ( self::$last_comment['akismet_result'] == 'false' ) { + update_comment_meta( $comment->comment_ID, 'akismet_result', 'false' ); + self::update_comment_history( $comment->comment_ID, '', 'check-ham' ); + // Status could be spam or trash, depending on the WP version and whether this change applies: + // https://core.trac.wordpress.org/changeset/34726 + if ( $comment->comment_approved == 'spam' || $comment->comment_approved == 'trash' ) { + if ( function_exists( 'wp_check_comment_disallowed_list' ) ) { + if ( wp_check_comment_disallowed_list( $comment->comment_author, $comment->comment_author_email, $comment->comment_author_url, $comment->comment_content, $comment->comment_author_IP, $comment->comment_agent ) ) { + self::update_comment_history( $comment->comment_ID, '', 'wp-disallowed' ); + } else { + self::update_comment_history( $comment->comment_ID, '', 'status-changed-' . $comment->comment_approved ); + } + } else if ( function_exists( 'wp_blacklist_check' ) && wp_blacklist_check( $comment->comment_author, $comment->comment_author_email, $comment->comment_author_url, $comment->comment_content, $comment->comment_author_IP, $comment->comment_agent ) ) { + self::update_comment_history( $comment->comment_ID, '', 'wp-blacklisted' ); + } else { + self::update_comment_history( $comment->comment_ID, '', 'status-changed-' . $comment->comment_approved ); + } + } + } else { + // abnormal result: error + update_comment_meta( $comment->comment_ID, 'akismet_error', time() ); + self::update_comment_history( + $comment->comment_ID, + '', + 'check-error', + array( 'response' => substr( self::$last_comment['akismet_result'], 0, 50 ) ) + ); + } - // record the complete original data as submitted for checking - if ( isset( self::$last_comment['comment_as_submitted'] ) ) - update_comment_meta( $comment->comment_ID, 'akismet_as_submitted', self::$last_comment['comment_as_submitted'] ); + // record the complete original data as submitted for checking + if ( isset( self::$last_comment['comment_as_submitted'] ) ) { + update_comment_meta( $comment->comment_ID, 'akismet_as_submitted', self::$last_comment['comment_as_submitted'] ); + } - if ( isset( self::$last_comment['akismet_pro_tip'] ) ) - update_comment_meta( $comment->comment_ID, 'akismet_pro_tip', self::$last_comment['akismet_pro_tip'] ); + if ( isset( self::$last_comment['akismet_pro_tip'] ) ) { + update_comment_meta( $comment->comment_ID, 'akismet_pro_tip', self::$last_comment['akismet_pro_tip'] ); + } } } } @@ -380,6 +423,10 @@ class Akismet { clean_comment_cache( $comment_ids ); do_action( 'akismet_delete_comment_batch', count( $comment_ids ) ); + + foreach ( $comment_ids as $comment_id ) { + do_action( 'deleted_comment', $comment_id ); + } } if ( apply_filters( 'akismet_optimize_table', ( mt_rand(1, 5000) == 11), $wpdb->comments ) ) // lucky number @@ -469,6 +516,44 @@ class Akismet { // get the full comment history for a given comment, as an array in reverse chronological order public static function get_comment_history( $comment_id ) { $history = get_comment_meta( $comment_id, 'akismet_history', false ); + if ( empty( $history ) || empty( $history[ 0 ] ) ) { + return false; + } + + /* + // To see all variants when testing. + $history[] = array( 'time' => 445856401, 'message' => 'Old versions of Akismet stored the message as a literal string in the commentmeta.', 'event' => null ); + $history[] = array( 'time' => 445856402, 'event' => 'recheck-spam' ); + $history[] = array( 'time' => 445856403, 'event' => 'check-spam' ); + $history[] = array( 'time' => 445856404, 'event' => 'recheck-ham' ); + $history[] = array( 'time' => 445856405, 'event' => 'check-ham' ); + $history[] = array( 'time' => 445856406, 'event' => 'wp-blacklisted' ); + $history[] = array( 'time' => 445856406, 'event' => 'wp-disallowed' ); + $history[] = array( 'time' => 445856407, 'event' => 'report-spam' ); + $history[] = array( 'time' => 445856408, 'event' => 'report-spam', 'user' => 'sam' ); + $history[] = array( 'message' => 'sam reported this comment as spam (hardcoded message).', 'time' => 445856400, 'event' => 'report-spam', 'user' => 'sam' ); + $history[] = array( 'time' => 445856409, 'event' => 'report-ham', 'user' => 'sam' ); + $history[] = array( 'message' => 'sam reported this comment as ham (hardcoded message).', 'time' => 445856400, 'event' => 'report-ham', 'user' => 'sam' ); // + $history[] = array( 'time' => 445856410, 'event' => 'cron-retry-spam' ); + $history[] = array( 'time' => 445856411, 'event' => 'cron-retry-ham' ); + $history[] = array( 'time' => 445856412, 'event' => 'check-error' ); // + $history[] = array( 'time' => 445856413, 'event' => 'check-error', 'meta' => array( 'response' => 'The server was taking a nap.' ) ); + $history[] = array( 'time' => 445856414, 'event' => 'recheck-error' ); // Should not generate a message. + $history[] = array( 'time' => 445856415, 'event' => 'recheck-error', 'meta' => array( 'response' => 'The server was taking a nap.' ) ); + $history[] = array( 'time' => 445856416, 'event' => 'status-changedtrash' ); + $history[] = array( 'time' => 445856417, 'event' => 'status-changedspam' ); + $history[] = array( 'time' => 445856418, 'event' => 'status-changedhold' ); + $history[] = array( 'time' => 445856419, 'event' => 'status-changedapprove' ); + $history[] = array( 'time' => 445856420, 'event' => 'status-changed-trash' ); + $history[] = array( 'time' => 445856421, 'event' => 'status-changed-spam' ); + $history[] = array( 'time' => 445856422, 'event' => 'status-changed-hold' ); + $history[] = array( 'time' => 445856423, 'event' => 'status-changed-approve' ); + $history[] = array( 'time' => 445856424, 'event' => 'status-trash', 'user' => 'sam' ); + $history[] = array( 'time' => 445856425, 'event' => 'status-spam', 'user' => 'sam' ); + $history[] = array( 'time' => 445856426, 'event' => 'status-hold', 'user' => 'sam' ); + $history[] = array( 'time' => 445856427, 'event' => 'status-approve', 'user' => 'sam' ); + */ + usort( $history, array( 'Akismet', '_cmp_time' ) ); return $history; } @@ -506,6 +591,10 @@ class Akismet { public static function check_db_comment( $id, $recheck_reason = 'recheck_queue' ) { global $wpdb; + if ( ! self::get_api_key() ) { + return new WP_Error( 'akismet-not-configured', __( 'Akismet is not configured. Please enter an API key.', 'akismet' ) ); + } + $c = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->comments} WHERE comment_ID = %d", $id ), ARRAY_A ); if ( ! $c ) { @@ -653,6 +742,13 @@ class Akismet { if ( 'spam' != $comment->comment_approved ) return; + self::update_comment_history( $comment_id, '', 'report-spam' ); + + // If the user hasn't configured Akismet, there's nothing else to do at this point. + if ( ! self::get_api_key() ) { + return; + } + // use the original version stored in comment_meta if available $as_submitted = self::sanitize_comment_as_submitted( get_comment_meta( $comment_id, 'akismet_as_submitted', true ) ); @@ -685,9 +781,10 @@ class Akismet { } $response = Akismet::http_post( Akismet::build_query( $comment ), 'submit-spam' ); + + update_comment_meta( $comment_id, 'akismet_user_result', 'true' ); + if ( $comment->reporter ) { - self::update_comment_history( $comment_id, '', 'report-spam' ); - update_comment_meta( $comment_id, 'akismet_user_result', 'true' ); update_comment_meta( $comment_id, 'akismet_user', $comment->reporter ); } @@ -703,6 +800,13 @@ class Akismet { if ( !$comment ) // it was deleted return; + self::update_comment_history( $comment_id, '', 'report-ham' ); + + // If the user hasn't configured Akismet, there's nothing else to do at this point. + if ( ! self::get_api_key() ) { + return; + } + // use the original version stored in comment_meta if available $as_submitted = self::sanitize_comment_as_submitted( get_comment_meta( $comment_id, 'akismet_as_submitted', true ) ); @@ -735,9 +839,10 @@ class Akismet { } $response = self::http_post( Akismet::build_query( $comment ), 'submit-ham' ); + + update_comment_meta( $comment_id, 'akismet_user_result', 'false' ); + if ( $comment->reporter ) { - self::update_comment_history( $comment_id, '', 'report-ham' ); - update_comment_meta( $comment_id, 'akismet_user_result', 'false' ); update_comment_meta( $comment_id, 'akismet_user', $comment->reporter ); } @@ -860,6 +965,11 @@ class Akismet { * has not been set and that Akismet should just choose the default behavior for that * situation. */ + + if ( ! self::get_api_key() ) { + return; + } + $akismet_comment_nonce_option = apply_filters( 'akismet_comment_nonce', get_option( 'akismet_comment_nonce' ) ); if ( $akismet_comment_nonce_option == 'true' || $akismet_comment_nonce_option == '' ) { @@ -879,7 +989,7 @@ class Akismet { if ( is_user_logged_in() ) return false; - return ( get_option( 'akismet_strictness' ) === '1' ); + return ( get_option( 'akismet_strictness' ) === '1' ); } public static function get_ip_address() { @@ -1029,10 +1139,12 @@ class Akismet { if ( ! empty( self::$prevent_moderation_email_for_these_comments ) && ! empty( $emails ) ) { $comment = get_comment( $comment_id ); - foreach ( self::$prevent_moderation_email_for_these_comments as $possible_match ) { - if ( self::comments_match( $possible_match, $comment ) ) { - update_comment_meta( $comment_id, 'akismet_delayed_moderation_email', true ); - return array(); + if ( $comment ) { + foreach ( self::$prevent_moderation_email_for_these_comments as $possible_match ) { + if ( self::comments_match( $possible_match, $comment ) ) { + update_comment_meta( $comment_id, 'akismet_delayed_moderation_email', true ); + return array(); + } } } } @@ -1163,51 +1275,106 @@ class Akismet { // given a response from an API call like check_key_status(), update the alert code options if an alert is present. public static function update_alert( $response ) { - $code = $msg = null; - if ( isset( $response[0]['x-akismet-alert-code'] ) ) { - $code = $response[0]['x-akismet-alert-code']; - $msg = $response[0]['x-akismet-alert-msg']; - } + $alert_option_prefix = 'akismet_alert_'; + $alert_header_prefix = 'x-akismet-alert-'; + $alert_header_names = array( + 'code', + 'msg', + 'api-calls', + 'usage-limit', + 'upgrade-plan', + 'upgrade-url', + 'upgrade-type', + ); - // only call update_option() if the value has changed - if ( $code != get_option( 'akismet_alert_code' ) ) { - if ( ! $code ) { - delete_option( 'akismet_alert_code' ); - delete_option( 'akismet_alert_msg' ); + foreach ( $alert_header_names as $alert_header_name ) { + $value = null; + if ( isset( $response[0][ $alert_header_prefix . $alert_header_name ] ) ) { + $value = $response[0][ $alert_header_prefix . $alert_header_name ]; } - else { - update_option( 'akismet_alert_code', $code ); - update_option( 'akismet_alert_msg', $msg ); + + $option_name = $alert_option_prefix . str_replace( '-', '_', $alert_header_name ); + if ( $value != get_option( $option_name ) ) { + if ( ! $value ) { + delete_option( $option_name ); + } else { + update_option( $option_name, $value ); + } } } } public static function load_form_js() { - if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) { - return; + /* deprecated */ + } + + public static function set_form_js_async( $tag, $handle, $src ) { + /* deprecated */ + return $tag; + } + + public static function get_akismet_form_fields() { + $fields = ''; + + $prefix = 'ak_'; + + // Contact Form 7 uses _wpcf7 as a prefix to know which fields to exclude from comment_content. + if ( 'wpcf7_form_elements' === current_filter() ) { + $prefix = '_wpcf7_ak_'; + } + + $fields .= '<p style="display: none !important;">'; + $fields .= '<label>Δ<textarea name="' . $prefix . 'hp_textarea" cols="45" rows="8" maxlength="100"></textarea></label>'; + + if ( ! function_exists( 'amp_is_request' ) || ! amp_is_request() ) { + $fields .= '<input type="hidden" id="ak_js" name="' . $prefix . 'js" value="' . mt_rand( 0, 250 ) . '"/>'; + $fields .= '<script>document.getElementById( "ak_js" ).setAttribute( "value", ( new Date() ).getTime() );</script>'; } - wp_register_script( 'akismet-form', plugin_dir_url( __FILE__ ) . '_inc/form.js', array(), AKISMET_VERSION, true ); - wp_enqueue_script( 'akismet-form' ); + $fields .= '</p>'; + + return $fields; } - + + public static function output_custom_form_fields( $post_id ) { + // phpcs:ignore WordPress.Security.EscapeOutput + echo self::get_akismet_form_fields(); + } + + public static function inject_custom_form_fields( $html ) { + $html = str_replace( '</form>', self::get_akismet_form_fields() . '</form>', $html ); + + return $html; + } + + public static function append_custom_form_fields( $html ) { + $html .= self::get_akismet_form_fields(); + + return $html; + } + /** - * Mark form.js as async. Because nothing depends on it, it can run at any time - * after it's loaded, and the browser won't have to wait for it to load to continue - * parsing the rest of the page. + * Ensure that any Akismet-added form fields are included in the comment-check call. + * + * @param array $form + * @return array $form */ - public static function set_form_js_async( $tag, $handle, $src ) { - if ( 'akismet-form' !== $handle ) { - return $tag; + public static function prepare_custom_form_values( $form ) { + $prefix = 'ak_'; + + // Contact Form 7 uses _wpcf7 as a prefix to know which fields to exclude from comment_content. + if ( 'wpcf7_akismet_parameters' === current_filter() ) { + $prefix = '_wpcf7_ak_'; } - - return preg_replace( '/^<script /i', '<script async="async" ', $tag ); - } - - public static function inject_ak_js( $fields ) { - echo '<p style="display: none;">'; - echo '<input type="hidden" id="ak_js" name="ak_js" value="' . mt_rand( 0, 250 ) . '"/>'; - echo '</p>'; + + // phpcs:ignore WordPress.Security.NonceVerification.Missing + foreach ( $_POST as $key => $val ) { + if ( 0 === strpos( $key, $prefix ) ) { + $form[ 'POST_ak_' . substr( $key, strlen( $prefix ) ) ] = $val; + } + } + + return $form; } private static function bail_on_activation( $message, $deactivate = true ) { @@ -1277,7 +1444,7 @@ p { $message = '<strong>'.sprintf(esc_html__( 'Akismet %s requires WordPress %s or higher.' , 'akismet'), AKISMET_VERSION, AKISMET__MINIMUM_WP_VERSION ).'</strong> '.sprintf(__('Please <a href="%1$s">upgrade WordPress</a> to a current version, or <a href="%2$s">downgrade to version 2.4 of the Akismet plugin</a>.', 'akismet'), 'https://codex.wordpress.org/Upgrading_WordPress', 'https://wordpress.org/extend/plugins/akismet/download/'); Akismet::bail_on_activation( $message ); - } else { + } elseif ( ! empty( $_SERVER['SCRIPT_NAME'] ) && false !== strpos( $_SERVER['SCRIPT_NAME'], '/wp-admin/plugins.php' ) ) { add_option( 'Activated_Akismet', true ); } } @@ -1333,16 +1500,98 @@ p { if ( $method !== 'pingback.ping' ) return; + // 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. + // This ticket should hopefully fix that: https://core.trac.wordpress.org/ticket/52524 + // Until that happens, when it's a system.multicall, pre_check_pingback will be called once for every internal pingback call. + // Keep track of how many times this function has been called so we know which call to reference in the XML. + static $call_count = 0; + + $call_count++; + global $wp_xmlrpc_server; - + if ( !is_object( $wp_xmlrpc_server ) ) return false; - - // Lame: tightly coupled with the IXR class. - $args = $wp_xmlrpc_server->message->params; - - if ( !empty( $args[1] ) ) { - $post_id = url_to_postid( $args[1] ); + + $is_multicall = false; + $multicall_count = 0; + + if ( 'system.multicall' === $wp_xmlrpc_server->message->methodName ) { + $is_multicall = true; + + if ( 0 === $call_count ) { + // Only pass along the number of entries in the multicall the first time we see it. + $multicall_count = count( $wp_xmlrpc_server->message->params ); + } + + /* + * $wp_xmlrpc_server->message looks like this: + * + ( + [message] => + [messageType] => methodCall + [faultCode] => + [faultString] => + [methodName] => system.multicall + [params] => Array + ( + [0] => Array + ( + [methodName] => pingback.ping + [params] => Array + ( + [0] => http://www.example.net/?p=1 // Site that created the pingback. + [1] => https://www.example.com/?p=1 // Post being pingback'd on this site. + ) + ) + [1] => Array + ( + [methodName] => pingback.ping + [params] => Array + ( + [0] => http://www.example.net/?p=1 // Site that created the pingback. + [1] => https://www.example.com/?p=2 // Post being pingback'd on this site. + ) + ) + ) + ) + */ + + // Use the params from the nth pingback.ping call in the multicall. + $pingback_calls_found = 0; + + foreach ( $wp_xmlrpc_server->message->params as $xmlrpc_action ) { + if ( 'pingback.ping' === $xmlrpc_action['methodName'] ) { + $pingback_calls_found++; + } + + if ( $call_count === $pingback_calls_found ) { + $pingback_args = $xmlrpc_action['params']; + break; + } + } + } else { + /* + * $wp_xmlrpc_server->message looks like this: + * + ( + [message] => + [messageType] => methodCall + [faultCode] => + [faultString] => + [methodName] => pingback.ping + [params] => Array + ( + [0] => http://www.example.net/?p=1 // Site that created the pingback. + [1] => https://www.example.com/?p=2 // Post being pingback'd on this site. + ) + ) + */ + $pingback_args = $wp_xmlrpc_server->message->params; + } + + if ( ! empty( $pingback_args[1] ) ) { + $post_id = url_to_postid( $pingback_args[1] ); // If pingbacks aren't open on this post, we'll still check whether this request is part of a potential DDOS, // but indicate to the server that pingbacks are indeed closed so we don't include this request in the user's stats, @@ -1355,23 +1604,30 @@ p { $pingbacks_closed = true; } + // 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. + $comment = array( - 'comment_author_url' => $args[0], + 'comment_author_url' => $pingback_args[0], 'comment_post_ID' => $post_id, 'comment_author' => '', 'comment_author_email' => '', 'comment_content' => '', 'comment_type' => 'pingback', 'akismet_pre_check' => '1', - 'comment_pingback_target' => $args[1], + 'comment_pingback_target' => $pingback_args[1], 'pingbacks_closed' => $pingbacks_closed ? '1' : '0', + 'is_multicall' => $is_multicall, + 'multicall_count' => $multicall_count, ); - $comment = Akismet::auto_check_comment( $comment ); + $comment = self::auto_check_comment( $comment, 'xml-rpc' ); if ( isset( $comment['akismet_result'] ) && 'true' == $comment['akismet_result'] ) { - // Lame: tightly coupled with the IXR classes. Unfortunately the action provides no context and no way to return anything. + // Sad: tightly coupled with the IXR classes. Unfortunately the action provides no context and no way to return anything. $wp_xmlrpc_server->error( new IXR_Error( 0, 'Invalid discovery target' ) ); + + // Also note that if this was part of a multicall, a spam result will prevent the subsequent calls from being executed. + // This is probably fine, but it raises the bar for what should be acceptable as a false positive. } } } @@ -1390,8 +1646,17 @@ p { $meta_value = (array) $meta_value; foreach ( $meta_value as $key => $value ) { - if ( ! isset( self::$comment_as_submitted_allowed_keys[$key] ) || ! is_scalar( $value ) ) { - unset( $meta_value[$key] ); + if ( ! is_scalar( $value ) ) { + unset( $meta_value[ $key ] ); + } else { + // These can change, so they're not explicitly listed in comment_as_submitted_allowed_keys. + if ( strpos( $key, 'POST_ak_' ) === 0 ) { + continue; + } + + if ( ! isset( self::$comment_as_submitted_allowed_keys[ $key ] ) ) { + unset( $meta_value[ $key ] ); + } } } diff --git a/plugins/akismet/readme.txt b/plugins/akismet/readme.txt index bf0081a9..0058c338 100644 --- a/plugins/akismet/readme.txt +++ b/plugins/akismet/readme.txt @@ -1,12 +1,12 @@ -=== Akismet Anti-Spam === +=== Akismet Spam Protection === Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, cfinke, automattic, jgs, procifer, stephdau -Tags: akismet, comments, spam, antispam, anti-spam, anti spam, comment moderation, comment spam, contact form spam, spam comments -Requires at least: 4.0 -Tested up to: 5.3 -Stable tag: 4.1.3 +Tags: comments, spam, antispam, anti-spam, contact form, anti spam, comment moderation, comment spam, contact form spam, spam comments +Requires at least: 5.0 +Tested up to: 5.8 +Stable tag: 4.2.1 License: GPLv2 or later -Akismet checks your comments and contact form submissions against our global database of spam to protect you and your site from malicious content. +The best anti-spam protection to block spam comments and spam in a contact form. The most trusted antispam solution for WordPress and WooCommerce. == Description == @@ -30,445 +30,61 @@ Upload the Akismet plugin to your blog, activate it, and then enter your Akismet == Changelog == -= 4.1.3 = -*Release Date - 31 October 2019* += 4.2.1 = +*Release Date - 1 October 2021* -* Prevented an attacker from being able to cause a user to unknowingly recheck their Pending comments for spam. -* Improved compatibility with Jetpack 7.7+. -* Updated the plugin activation page to use consistent language and markup. -* Redirecting users to the Akismet connnection/settings screen upon plugin activation, in an effort to make it easier for people to get setup. +* Fixed a bug causing AMP validation to fail on certain pages with forms. -= 4.1.2 = -*Release Date - 14 May 2019* += 4.2 = +*Release Date - 30 September 2021* -* Fixed a conflict between the Akismet setup banner and other plugin notices. -* Reduced the number of API requests made by the plugin when attempting to verify the API key. -* Include additional data in the pingback pre-check API request to help make the stats more accurate. -* Fixed a bug that was enabling the "Check for Spam" button when no comments were eligible to be checked. -* Improved Akismet's AMP compatibility. +* Added links to additional information on API usage notifications. +* Reduced the number of network requests required for a comment page when running Akismet. +* Improved compatibility with the most popular contact form plugins. +* Improved API usage buttons for clarity on what upgrade is needed. -= 4.1.1 = -*Release Date - 31 January 2019* += 4.1.12 = +*Release Date - 3 September 2021* -* Fixed the "Setup Akismet" notice so it resizes responsively. -* Only highlight the "Save Changes" button in the Akismet config when changes have been made. -* The count of comments in your spam queue shown on the dashboard show now always be up-to-date. +* Fixed "Use of undefined constant" notice. +* Improved styling of alert notices. -= 4.1 = -*Release Date - 12 November 2018* += 4.1.11 = +*Release Date - 23 August 2021* -* Added a WP-CLI method for retrieving stats. -* Hooked into the new "Personal Data Eraser" functionality from WordPress 4.9.6. -* Added functionality to clear outdated alerts from Akismet.com. - -= 4.0.8 = -*Release Date - 19 June 2018* - -* Improved the grammar and consistency of the in-admin privacy related notes (notice and config). -* Revised in-admin explanation of the comment form privacy notice to make its usage clearer. -* Added `rel="nofollow noopener"` to the comment form privacy notice to improve SEO and security. - -= 4.0.7 = -*Release Date - 28 May 2018* - -* Based on user feedback, the link on "Learn how your comment data is processed." in the optional privacy notice now has a `target` of `_blank` and opens in a new tab/window. -* Updated the in-admin privacy notice to use the term "comment" instead of "contact" in "Akismet can display a notice to your users under your comment forms." -* Only show in-admin privacy notice if Akismet has an API Key configured - -= 4.0.6 = -*Release Date - 26 May 2018* - -* Moved away from using `empty( get_option() )` to instantiating a variable to be compatible with older versions of PHP (5.3, 5.4, etc). - -= 4.0.5 = -*Release Date - 26 May 2018* - -* Corrected version number after tagging. Sorry... - -= 4.0.4 = -*Release Date - 26 May 2018* - -* Added a hook to provide Akismet-specific privacy information for a site's privacy policy. -* Added tools to control the display of a privacy related notice under comment forms. -* Fixed HTML in activation failure message to close META and HEAD tag properly. -* Fixed a bug that would sometimes prevent Akismet from being correctly auto-configured. - -= 4.0.3 = -*Release Date - 19 February 2018* - -* Added a scheduled task to remove entries in wp_commentmeta that no longer have corresponding comments in wp_comments. -* Added a new `akismet_batch_delete_count` action to the batch delete methods for people who'd like to keep track of the numbers of records being processed by those methods. - -= 4.0.2 = -*Release Date - 18 December 2017* - -* Fixed a bug that could cause Akismet to recheck a comment that has already been manually approved or marked as spam. -* Fixed a bug that could cause Akismet to claim that some comments are still waiting to be checked when no comments are waiting to be checked. - -= 4.0.1 = -*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. - -= 4.0 = -*Release Date - 19 September 2017* - -* Added REST API endpoints for configuring Akismet and retrieving stats. -* Increased the minimum supported WordPress version to 4.0. -* Added compatibility with comments submitted via the REST API. -* Improved the progress indicator on the "Check for Spam" button. - -= 3.3.4 = -*Release Date - 3 August 2017* - -* Disabled Akismet's debug log output by default unless AKISMET_DEBUG is defined. -* URL previews now begin preloading when the mouse moves near them in the comments section of wp-admin. -* When a comment is caught by the Comment Blacklist, Akismet will always allow it to stay in the trash even if it is spam as well. -* Fixed a bug that was preventing an error from being shown when a site can't reach Akismet's servers. - -= 3.3.3 = -*Release Date - 13 July 2017* - -* Reduced amount of bandwidth used by the URL Preview feature. -* Improved the admin UI when the API key is manually pre-defined for the site. -* Removed a workaround for WordPress installations older than 3.3 that will improve Akismet's compatibility with other plugins. -* The number of spam blocked that is displayed on the WordPress dashboard will now be more accurate and updated more frequently. -* Fixed a bug in the Akismet widget that could cause PHP warnings. - -= 3.3.2 = -*Release Date - 10 May 2017* - -* Fixed a bug causing JavaScript errors in some browsers. +* Added support for Akismet API usage notifications on Akismet settings and edit-comments admin pages. +* Added support for the deleted_comment action when bulk-deleting comments from Spam. -= 3.3.1 = -*Release Date - 2 May 2017* - -* Improve performance by only requesting the akismet_comment_nonce option when absolutely necessary. -* Fixed two bugs that could cause PHP warnings. -* Fixed a bug that was preventing the "Remove author URL" feature from working after a comment was edited using "Quick Edit." -* Fixed a bug that was preventing the URL preview feature from working after a comment was edited using "Quick Edit." - -= 3.3 = -*Release Date - 23 February 2017* - -* Updated the Akismet admin pages with a new clean design. -* Fixed bugs preventing the `akismet_add_comment_nonce` and `akismet_update_alert` wrapper functions from working properly. -* Fixed bug preventing the loading indicator from appearing when re-checking all comments for spam. -* Added a progress indicator to the "Check for Spam" button. -* Added a success message after manually rechecking the Pending queue for spam. - -= 3.2 = -*Release Date - 6 September 2016* - -* Added a WP-CLI module. You can now check comments and recheck the moderation queue from the command line. -* Stopped using the deprecated jQuery function `.live()`. -* Fixed a bug in `remove_comment_author_url()` and `add_comment_author_url()` that could generate PHP notices. -* Fixed a bug that could cause an infinite loop for sites with very very very large comment IDs. -* Fixed a bug that could cause the Akismet widget title to be blank. - -= 3.1.11 = -*Release Date - 12 May 2016* - -* Fixed a bug that could cause the "Check for Spam" button to skip some comments. -* Fixed a bug that could prevent some spam submissions from being sent to Akismet. -* Updated all links to use https:// when possible. -* Disabled Akismet debug logging unless WP_DEBUG and WP_DEBUG_LOG are both enabled. - -= 3.1.10 = -*Release Date - 1 April 2016* - -* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue. -* Fixed a bug that could have resulted in comments that were caught by the core WordPress comment blacklist not to have a corresponding History entry. -* Fixed a bug that could have caused avoidable PHP warnings in the error log. - -= 3.1.9 = -*Release Date - 28 March 2016* - -* Add compatibility with Jetpack so that Jetpack can automatically configure Akismet settings when appropriate. -* Fixed a bug preventing some comment data from being sent to Akismet. - -= 3.1.8 = -*Release Date - 4 March 2016* - -* Fixed a bug preventing Akismet from being used with some plugins that rewrite admin URLs. -* Reduced the amount of bandwidth used on Akismet API calls -* Reduced the amount of space Akismet uses in the database -* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue. - -= 3.1.7 = -*Release Date - 4 January 2016* - -* Added documentation for the 'akismet_comment_nonce' filter. -* The post-install activation button is now accessible to screen readers and keyboard-only users. -* Fixed a bug that was preventing the "Remove author URL" feature from working in WordPress 4.4 - -= 3.1.6 = -*Release Date - 14 December 2015* - -* Improve the notices shown after activating Akismet. -* Update some strings to allow for the proper plural forms in all languages. - -= 3.1.5 = -*Release Date - 13 October 2015* - -* Closes a potential XSS vulnerability. - -= 3.1.4 = -*Release Date - 24 September 2015* - -* Fixed a bug that was preventing some users from automatically connecting using Jetpack if they didn't have a current Akismet subscription. -* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue. -* Error messages and instructions have been simplified to be more understandable. -* Link previews are enabled for all links inside comments, not just the author's website link. - -= 3.1.3 = -*Release Date - 6 July 2015* - -* Notify users when their account status changes after previously being successfully set up. This should help any users who are seeing blank Akismet settings screens. - -= 3.1.2 = -*Release Date - 7 June 2015* - -* Reduced the amount of space Akismet uses in the commentmeta table. -* Fixed a bug where some comments with quotes in the author name weren't getting history entries -* Pre-emptive security improvements to ensure that the Akismet plugin can't be used by attackers to compromise a WordPress installation. -* Better UI for the key entry field: allow whitespace to be included at the beginning or end of the key and strip it out automatically when the form is submitted. -* When deactivating the plugin, notify the Akismet API so the site can be marked as inactive. -* Clearer error messages. - -= 3.1.1 = -*Release Date - 17th March, 2015* - -* Improvements to the "Remove comment author URL" JavaScript -* Include the pingback pre-check from the 2.6 branch. - -= 3.1 = -*Release Date - 11th March, 2015* - -* Use HTTPS by default for all requests to Akismet. -* Fix for a situation where Akismet might strip HTML from a comment. - -= 3.0.4 = -*Release Date - 11th December, 2014* - -* Fix to make .htaccess compatible with Apache 2.4. -* Fix to allow removal of https author URLs. -* Fix to avoid stripping part of the author URL when removing and re-adding. -* Removed the "Check for Spam" button from the "Trash" and "Approved" queues, where it would have no effect. -* Allow automatic API key configuration when Jetpack is installed and connected to a WordPress.com account - -= 3.0.3 = -*Release Date - 3rd November, 2014* - -* Fix for sending the wrong data to delete_comment action that could have prevented old spam comments from being deleted. -* Added a filter to disable logging of Akismet debugging information. -* Added a filter for the maximum comment age when deleting old spam comments. -* Added a filter for the number per batch when deleting old spam comments. -* Removed the "Check for Spam" button from the Spam folder. - -= 3.0.2 = -*Release Date - 18th August, 2014* - -* Performance improvements. -* Fixed a bug that could truncate the comment data being sent to Akismet for checking. - -= 3.0.1 = -*Release Date - 9th July, 2014* - -* Removed dependency on PHP's fsockopen function -* Fix spam/ham reports to work when reported outside of the WP dashboard, e.g., from Notifications or the WP app -* Remove jQuery dependency for comment form JavaScript -* Remove unnecessary data from some Akismet comment meta -* Suspended keys will now result in all comments being put in moderation, not spam. - -= 3.0.0 = -*Release Date - 15th April, 2014* - -* Move Akismet to Settings menu -* Drop Akismet Stats menu -* Add stats snapshot to Akismet settings -* Add Akismet subscription details and status to Akismet settings -* Add contextual help for each page -* Improve Akismet setup to use Jetpack to automate plugin setup -* Fix "Check for Spam" to use AJAX to avoid page timing out -* Fix Akismet settings page to be responsive -* Drop legacy code -* Tidy up CSS and Javascript -* Replace the old discard setting with a new "discard pervasive spam" feature. - -= 2.6.0 = -*Release Date - 18th March, 2014* - -* 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 - -= 2.5.9 = -*Release Date - 1st August, 2013* - -* Update 'Already have a key' link to redirect page rather than depend on javascript -* Fix some non-translatable strings to be translatable -* Update Activation banner in plugins page to redirect user to Akismet config page - -= 2.5.8 = -*Release Date - 20th January, 2013* - -* Simplify the activation process for new users -* Remove the reporter_ip parameter -* Minor preventative security improvements - -= 2.5.7 = -*Release Date - 13th December, 2012* - -* FireFox Stats iframe preview bug -* Fix mshots preview when using https -* Add .htaccess to block direct access to files -* Prevent some PHP notices -* Fix Check For Spam return location when referrer is empty -* Fix Settings links for network admins -* Fix prepare() warnings in WP 3.5 - -= 2.5.6 = -*Release Date - 26th April, 2012* - -* Prevent retry scheduling problems on sites where wp_cron is misbehaving -* Preload mshot previews -* Modernize the widget code -* Fix a bug where comments were not held for moderation during an error condition -* Improve the UX and display when comments are temporarily held due to an error -* Make the Check For Spam button force a retry when comments are held due to an error -* Handle errors caused by an invalid key -* Don't retry comments that are too old -* Improve error messages when verifying an API key - -= 2.5.5 = -*Release Date - 11th January, 2012* - -* Add nonce check for comment author URL remove action -* Fix the settings link - -= 2.5.4 = -*Release Date - 5th January, 2012* - -* Limit Akismet CSS and Javascript loading in wp-admin to just the pages that need it -* Added author URL quick removal functionality -* Added mShot preview on Author URL hover -* Added empty index.php to prevent directory listing -* Move wp-admin menu items under Jetpack, if it is installed -* Purge old Akismet comment meta data, default of 15 days - -= 2.5.3 = -*Release Date - 8th Febuary, 2011* - -* Specify the license is GPL v2 or later -* Fix a bug that could result in orphaned commentmeta entries -* Include hotfix for WordPress 3.0.5 filter issue - -= 2.5.2 = -*Release Date - 14th January, 2011* - -* Properly format the comment count for author counts -* Look for super admins on multisite installs when looking up user roles -* Increase the HTTP request timeout -* Removed padding for author approved count -* Fix typo in function name -* Set Akismet stats iframe height to fixed 2500px. Better to have one tall scroll bar than two side by side. - -= 2.5.1 = -*Release Date - 17th December, 2010* - -* Fix a bug that caused the "Auto delete" option to fail to discard comments correctly -* Remove the comment nonce form field from the 'Akismet Configuration' page in favor of using a filter, akismet_comment_nonce -* Fixed padding bug in "author" column of posts screen -* Added margin-top to "cleared by ..." badges on dashboard -* Fix possible error when calling akismet_cron_recheck() -* Fix more PHP warnings -* Clean up XHTML warnings for comment nonce -* Fix for possible condition where scheduled comment re-checks could get stuck -* Clean up the comment meta details after deleting a comment -* Only show the status badge if the comment status has been changed by someone/something other than Akismet -* Show a 'History' link in the row-actions -* Translation fixes -* Reduced font-size on author name -* Moved "flagged by..." notification to top right corner of comment container and removed heavy styling -* Hid "flagged by..." notification while on dashboard - -= 2.5.0 = -*Release Date - 7th December, 2010* - -* Track comment actions under 'Akismet Status' on the edit comment screen -* Fix a few remaining deprecated function calls ( props Mike Glendinning ) -* Use HTTPS for the stats IFRAME when wp-admin is using HTTPS -* Use the WordPress HTTP class if available -* Move the admin UI code to a separate file, only loaded when needed -* Add cron retry feature, to replace the old connectivity check -* Display Akismet status badge beside each comment -* Record history for each comment, and display it on the edit page -* Record the complete comment as originally submitted in comment_meta, to use when reporting spam and ham -* Highlight links in comment content -* New option, "Show the number of comments you've approved beside each comment author." -* New option, "Use a nonce on the comment form." - -= 2.4.0 = -*Release Date - 23rd August, 2010* - -* Spell out that the license is GPLv2 -* Fix PHP warnings -* Fix WordPress deprecated function calls -* Fire the delete_comment action when deleting comments -* Move code specific for older WP versions to legacy.php -* General code clean up - -= 2.3.0 = -*Release Date - 5th June, 2010* - -* Fix "Are you sure" nonce message on config screen in WPMU -* Fix XHTML compliance issue in sidebar widget -* Change author link; remove some old references to WordPress.com accounts -* Localize the widget title (core ticket #13879) - -= 2.2.9 = -*Release Date - 2nd June, 2010* - -* Eliminate a potential conflict with some plugins that may cause spurious reports += 4.1.10 = +*Release Date - 6 July 2021* -= 2.2.8 = -*Release Date - 27th May, 2010* +* Simplified the code around checking comments in REST API and XML-RPC requests. +* Updated Plus plan terminology in notices to match current subscription names. +* Added `rel="noopener"` to the widget link to avoid warnings in Google Lighthouse. +* Set the Akismet JavaScript as deferred instead of async to improve responsiveness. +* Improved the preloading of screenshot popups on the edit comments admin page. -* Fix bug in initial comment check for ipv6 addresses -* Report comments as ham when they are moved from spam to moderation -* Report comments as ham when clicking undo after spam -* Use transition_comment_status action when available instead of older actions for spam/ham submissions -* Better diagnostic messages when PHP network functions are unavailable -* Better handling of comments by logged-in users += 4.1.9 = +*Release Date - 2 March 2021* -= 2.2.7 = -*Release Date - 17th December, 2009* +* Improved handling of pingbacks in XML-RPC multicalls -* Add a new AKISMET_VERSION constant -* Reduce the possibility of over-counting spam when another spam filter plugin is in use -* Disable the connectivity check when the API key is hard-coded for WPMU += 4.1.8 = +*Release Date - 6 January 2021* -= 2.2.6 = -*Release Date - 20th July, 2009* +* Fixed missing fields in submit-spam and submit-ham calls that could lead to reduced accuracy. +* Fixed usage of deprecated jQuery function. -* Fix a global warning introduced in 2.2.5 -* Add changelog and additional readme.txt tags -* Fix an array conversion warning in some versions of PHP -* Support a new WPCOM_API_KEY constant for easier use with WordPress MU += 4.1.7 = +*Release Date - 22 October 2020* -= 2.2.5 = -*Release Date - 13th July, 2009* +* Show the "Set up your Akismet account" banner on the comments admin screen, where it's relevant to mention if Akismet hasn't been configured. +* Don't use wp_blacklist_check when the new wp_check_comment_disallowed_list function is available. -* Include a new Server Connectivity diagnostic check, to detect problems caused by firewalls += 4.1.6 = +*Release Date - 4 June 2020* -= 2.2.4 = -*Release Date - 3rd June, 2009* +* Disable "Check for Spam" button until the page is loaded to avoid errors with clicking through to queue recheck endpoint directly. +* Add filter "akismet_enable_mshots" to allow disabling screenshot popups on the edit comments admin page. -* Fixed a key problem affecting the stats feature in WordPress MU -* Provide additional blog information in Akismet API calls +For older changelog entries, please see the [additional changelog.txt file](https://plugins.svn.wordpress.org/akismet/trunk/changelog.txt) delivered with the plugin. diff --git a/plugins/akismet/views/config.php b/plugins/akismet/views/config.php index 6bbcd6d4..df24b91d 100644 --- a/plugins/akismet/views/config.php +++ b/plugins/akismet/views/config.php @@ -1,3 +1,9 @@ +<?php + +//phpcs:disable VariableAnalysis +// There are "undefined" variables here because they're defined in the code that includes this file as a template. + +?> <div id="akismet-plugin-container"> <div class="akismet-masthead"> <div class="akismet-masthead__inside-container"> @@ -53,7 +59,7 @@ </div> <?php endif;?> - <?php if ( $akismet_user ):?> + <?php if ( $akismet_user ) : ?> <div class="akismet-card"> <div class="akismet-section-header"> <div class="akismet-section-header__label"> diff --git a/plugins/akismet/views/enter.php b/plugins/akismet/views/enter.php index 0a79ca97..23dda40a 100644 --- a/plugins/akismet/views/enter.php +++ b/plugins/akismet/views/enter.php @@ -1,5 +1,5 @@ <div class="akismet-enter-api-key-box centered"> - <a href="#"><?php esc_html_e( 'Manually enter an API key' ); ?></a> + <a href="#"><?php esc_html_e( 'Manually enter an API key', 'akismet' ); ?></a> <div class="enter-api-key"> <form action="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>" method="post"> <?php wp_nonce_field( Akismet_Admin::NONCE ) ?> diff --git a/plugins/akismet/views/notice.php b/plugins/akismet/views/notice.php index fa098b8b..28dc6722 100644 --- a/plugins/akismet/views/notice.php +++ b/plugins/akismet/views/notice.php @@ -4,7 +4,7 @@ // There are "undefined" variables here because they're defined in the code that includes this file as a template. ?> -<?php if ( $type == 'plugin' ) :?> +<?php if ( $type == 'plugin' ) : ?> <div class="updated" id="akismet_setup_prompt"> <form name="akismet_activate" action="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>" method="POST"> <div class="akismet_activate"> @@ -18,7 +18,7 @@ </div> </form> </div> -<?php elseif ( $type == 'spam-check' ) :?> +<?php elseif ( $type == 'spam-check' ) : ?> <div class="notice notice-warning"> <p><strong><?php esc_html_e( 'Akismet has detected a problem.', 'akismet' );?></strong></p> <p><?php esc_html_e( 'Some comments have not yet been checked for spam by Akismet. They have been temporarily held for moderation and will automatically be rechecked later.', 'akismet' ); ?></p> @@ -26,7 +26,7 @@ <p><?php echo $link_text; ?></p> <?php } ?> </div> -<?php elseif ( $type == 'alert' ) :?> +<?php elseif ( $type == 'alert' ) : ?> <div class='error'> <p><strong><?php printf( esc_html__( 'Akismet Error Code: %s', 'akismet' ), $code ); ?></strong></p> <p><?php echo esc_html( $msg ); ?></p> @@ -38,49 +38,49 @@ ?> </p> </div> -<?php elseif ( $type == 'notice' ) :?> +<?php elseif ( $type == 'notice' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status failed"><?php echo $notice_header; ?></h3> <p class="akismet-description"> <?php echo $notice_text; ?> </p> </div> -<?php elseif ( $type == 'missing-functions' ) :?> +<?php elseif ( $type == 'missing-functions' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status failed"><?php esc_html_e('Network functions are disabled.', 'akismet'); ?></h3> <p class="akismet-description"><?php printf( __('Your web host or server administrator has disabled PHP’s <code>gethostbynamel</code> function. <strong>Akismet cannot work correctly until this is fixed.</strong> Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet’s system requirements</a>.', 'akismet'), 'https://blog.akismet.com/akismet-hosting-faq/'); ?></p> </div> -<?php elseif ( $type == 'servers-be-down' ) :?> +<?php elseif ( $type == 'servers-be-down' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status failed"><?php esc_html_e("Your site can’t connect to the Akismet servers.", 'akismet'); ?></h3> <p class="akismet-description"><?php printf( __('Your firewall may be blocking Akismet from connecting to its API. Please contact your host and refer to <a href="%s" target="_blank">our guide about firewalls</a>.', 'akismet'), 'https://blog.akismet.com/akismet-hosting-faq/'); ?></p> </div> -<?php elseif ( $type == 'active-dunning' ) :?> +<?php elseif ( $type == 'active-dunning' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status"><?php esc_html_e("Please update your payment information.", 'akismet'); ?></h3> <p class="akismet-description"><?php printf( __('We cannot process your payment. Please <a href="%s" target="_blank">update your payment details</a>.', 'akismet'), 'https://akismet.com/account/'); ?></p> </div> -<?php elseif ( $type == 'cancelled' ) :?> +<?php elseif ( $type == 'cancelled' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status"><?php esc_html_e("Your Akismet plan has been cancelled.", 'akismet'); ?></h3> <p class="akismet-description"><?php printf( __('Please visit your <a href="%s" target="_blank">Akismet account page</a> to reactivate your subscription.', 'akismet'), 'https://akismet.com/account/'); ?></p> </div> -<?php elseif ( $type == 'suspended' ) :?> +<?php elseif ( $type == 'suspended' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status failed"><?php esc_html_e("Your Akismet subscription is suspended.", 'akismet'); ?></h3> <p class="akismet-description"><?php printf( __('Please contact <a href="%s" target="_blank">Akismet support</a> for assistance.', 'akismet'), 'https://akismet.com/contact/'); ?></p> </div> -<?php elseif ( $type == 'active-notice' && $time_saved ) :?> +<?php elseif ( $type == 'active-notice' && $time_saved ) : ?> <div class="akismet-alert akismet-active"> <h3 class="akismet-key-status"><?php echo esc_html( $time_saved ); ?></h3> <p class="akismet-description"><?php printf( __('You can help us fight spam and upgrade your account by <a href="%s" target="_blank">contributing a token amount</a>.', 'akismet'), 'https://akismet.com/account/upgrade/'); ?></p> </div> -<?php elseif ( $type == 'missing' ) :?> +<?php elseif ( $type == 'missing' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status failed"><?php esc_html_e( 'There is a problem with your API key.', 'akismet'); ?></h3> <p class="akismet-description"><?php printf( __('Please contact <a href="%s" target="_blank">Akismet support</a> for assistance.', 'akismet'), 'https://akismet.com/contact/'); ?></p> </div> -<?php elseif ( $type == 'no-sub' ) :?> +<?php elseif ( $type == 'no-sub' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status failed"><?php esc_html_e( 'You don’t have an Akismet plan.', 'akismet'); ?></h3> <p class="akismet-description"> @@ -107,30 +107,83 @@ <p class="akismet-description"><?php printf( __( 'Would you like to <a href="%s">check pending comments</a>?', 'akismet' ), esc_url( $check_pending_link ) ); ?></p> <?php } ?> </div> -<?php elseif ( $type == 'new-key-invalid' ) :?> +<?php elseif ( $type == 'new-key-invalid' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status"><?php esc_html_e( 'The key you entered is invalid. Please double-check it.' , 'akismet'); ?></h3> </div> -<?php elseif ( $type == 'existing-key-invalid' ) :?> +<?php elseif ( $type == 'existing-key-invalid' ) : ?> <div class="akismet-alert akismet-critical"> - <h3 class="akismet-key-status"><?php esc_html_e( 'Your API key is no longer valid. Please enter a new key or contact support@akismet.com.' , 'akismet'); ?></h3> + <h3 class="akismet-key-status"><?php echo esc_html( __( 'Your API key is no longer valid.', 'akismet' ) ); ?></h3> + <p class="akismet-description"> + <?php + + echo wp_kses( + sprintf( + /* translators: The placeholder is a URL. */ + __( 'Please enter a new key or <a href="%s" target="_blank">contact Akismet support</a>.', 'akismet' ), + 'https://akismet.com/contact/' + ), + array( + 'a' => array( + 'href' => true, + 'target' => true, + ), + ) + ); + + ?> + </p> </div> -<?php elseif ( $type == 'new-key-failed' ) :?> +<?php elseif ( $type == 'new-key-failed' ) : ?> <div class="akismet-alert akismet-critical"> <h3 class="akismet-key-status"><?php esc_html_e( 'The API key you entered could not be verified.' , 'akismet'); ?></h3> - <p class="akismet-description"><?php printf( __('The connection to akismet.com could not be established. Please refer to <a href="%s" target="_blank">our guide about firewalls</a> and check your server configuration.', 'akismet'), 'https://blog.akismet.com/akismet-hosting-faq/'); ?></p> + <p class="akismet-description"> + <?php + + echo wp_kses( + sprintf( + /* translators: The placeholder is a URL. */ + __( 'The connection to akismet.com could not be established. Please refer to <a href="%s" target="_blank">our guide about firewalls</a> and check your server configuration.', 'akismet' ), + 'https://blog.akismet.com/akismet-hosting-faq/' + ), + array( + 'a' => array( + 'href' => true, + 'target' => true, + ), + ) + ); + + ?> + </p> </div> -<?php elseif ( $type == 'limit-reached' && in_array( $level, array( 'yellow', 'red' ) ) ) :?> +<?php elseif ( $type == 'limit-reached' && in_array( $level, array( 'yellow', 'red' ) ) ) : ?> <div class="akismet-alert akismet-critical"> <?php if ( $level == 'yellow' ): ?> - <h3 class="akismet-key-status failed"><?php esc_html_e( 'You’re using your Akismet key on more sites than your Pro subscription allows.', 'akismet' ); ?></h3> + <h3 class="akismet-key-status failed"><?php esc_html_e( 'You’re using your Akismet key on more sites than your Plus subscription allows.', 'akismet' ); ?></h3> <p class="akismet-description"> - <?php printf( __( 'Your Pro subscription allows the use of Akismet on only one site. Please <a href="%s" target="_blank">purchase additional Pro subscriptions</a> or upgrade to an Enterprise subscription that allows the use of Akismet on unlimited sites.', 'akismet' ), 'https://docs.akismet.com/billing/add-more-sites/' ); ?> + <?php + + echo wp_kses( + sprintf( + /* translators: The placeholder is a URL. */ + __( 'Your Plus subscription allows the use of Akismet on only one site. Please <a href="%s" target="_blank">purchase additional Plus subscriptions</a> or upgrade to an Enterprise subscription that allows the use of Akismet on unlimited sites.', 'akismet' ), + 'https://docs.akismet.com/billing/add-more-sites/' + ), + array( + 'a' => array( + 'href' => true, + 'target' => true, + ), + ) + ); + + ?> <br /><br /> <?php printf( __( 'Please <a href="%s" target="_blank">contact our support team</a> with any questions.', 'akismet' ), 'https://akismet.com/contact/'); ?> </p> <?php elseif ( $level == 'red' ): ?> - <h3 class="akismet-key-status failed"><?php esc_html_e( 'You’re using Akismet on far too many sites for your Pro subscription.', 'akismet' ); ?></h3> + <h3 class="akismet-key-status failed"><?php esc_html_e( 'You’re using Akismet on far too many sites for your Plus subscription.', 'akismet' ); ?></h3> <p class="akismet-description"> <?php printf( __( 'To continue your service, <a href="%s" target="_blank">upgrade to an Enterprise subscription</a>, which covers an unlimited number of sites.', 'akismet'), 'https://akismet.com/account/upgrade/' ); ?> <br /><br /> @@ -138,10 +191,96 @@ </p> <?php endif; ?> </div> -<?php elseif ( $type == 'privacy' ) :?> -<div class="notice notice-warning is-dismissible" id="akismet-privacy-notice-admin-notice"> - <p><strong><?php esc_html_e( 'Akismet & Privacy.', 'akismet' );?></strong></p> - <p><?php esc_html_e( 'To help your site with transparency under privacy laws like the GDPR, Akismet can display a notice to your users under your comment forms. This feature is disabled by default, however, you can turn it on below.', 'akismet' ); ?></p> - <p><?php printf( __(' Please <a href="%s">enable</a> or <a href="%s">disable</a> this feature. <a href="%s" id="akismet-privacy-notice-control-notice-info-link" target="_blank">More information</a>.', 'akismet' ), admin_url( apply_filters( 'akismet_comment_form_privacy_notice_url_display', 'options-general.php?page=akismet-key-config&akismet_comment_form_privacy_notice=display' ) ), admin_url( apply_filters( 'akismet_comment_form_privacy_notice_url_hide', 'options-general.php?page=akismet-key-config&akismet_comment_form_privacy_notice=hide' ) ), 'https://akismet.com/privacy/' ); ?></p> +<?php elseif ( $type == 'usage-limit' && isset( Akismet::$limit_notices[ $code ] ) ) : ?> +<div class="error akismet-usage-limit-alert"> + <div class="akismet-usage-limit-logo"> + <img src="<?php echo esc_url( plugins_url( '../_inc/img/logo-a-2x.png', __FILE__ ) ); ?>" alt="Akismet" /> + </div> + <div class="akismet-usage-limit-text"> + <h3> + <?php + switch ( Akismet::$limit_notices[ $code ] ) { + case 'FIRST_MONTH_OVER_LIMIT': + case 'SECOND_MONTH_OVER_LIMIT': + esc_html_e( 'Your Akismet account usage is over your plan’s limit', 'akismet' ); + break; + case 'THIRD_MONTH_APPROACHING_LIMIT': + esc_html_e( 'Your Akismet account usage is approaching your plan’s limit', 'akismet' ); + break; + case 'THIRD_MONTH_OVER_LIMIT': + case 'FOUR_PLUS_MONTHS_OVER_LIMIT': + esc_html_e( 'Your account has been restricted', 'akismet' ); + break; + default: + } + ?> + </h3> + <p> + <?php + switch ( Akismet::$limit_notices[ $code ] ) { + case 'FIRST_MONTH_OVER_LIMIT': + echo esc_html( + sprintf( + /* translators: The first placeholder is a date, the second is a (formatted) number, the third is another formatted number. */ + __( 'Since %1$s, your account made %2$s API calls, compared to your plan’s limit of %3$s.', 'akismet' ), + esc_html( gmdate( 'F' ) . ' 1' ), + number_format( $api_calls ), + number_format( $usage_limit ) + ) + ); + + echo '<a href="https://docs.akismet.com/akismet-api-usage-limits/" target="_blank">'; + echo esc_html( __( 'Learn more about usage limits.', 'akismet' ) ); + echo '</a>'; + + break; + case 'SECOND_MONTH_OVER_LIMIT': + echo esc_html( __( 'Your Akismet usage has been over your plan’s limit for two consecutive months. Next month, we will restrict your account after you reach the limit. Please consider upgrading your plan.', 'akismet' ) ); + + echo '<a href="https://docs.akismet.com/akismet-api-usage-limits/" target="_blank">'; + echo esc_html( __( 'Learn more about usage limits.', 'akismet' ) ); + echo '</a>'; + + break; + case 'THIRD_MONTH_APPROACHING_LIMIT': + echo esc_html( __( 'Your Akismet usage is nearing your plan’s limit for the third consecutive month. We will restrict your account after you reach the limit. Upgrade your plan so Akismet can continue blocking spam.', 'akismet' ) ); + + echo '<a href="https://docs.akismet.com/akismet-api-usage-limits/" target="_blank">'; + echo esc_html( __( 'Learn more about usage limits.', 'akismet' ) ); + echo '</a>'; + + break; + case 'THIRD_MONTH_OVER_LIMIT': + case 'FOUR_PLUS_MONTHS_OVER_LIMIT': + echo esc_html( __( 'Your Akismet usage has been over your plan’s limit for three consecutive months. We have restricted your account for the rest of the month. Upgrade your plan so Akismet can continue blocking spam.', 'akismet' ) ); + + echo '<a href="https://docs.akismet.com/akismet-api-usage-limits/" target="_blank">'; + echo esc_html( __( 'Learn more about usage limits.', 'akismet' ) ); + echo '</a>'; + + break; + default: + } + ?> + </p> + </div> + <div class="akismet-usage-limit-cta"> + <a href="<?php echo esc_attr( $upgrade_url ); ?>" class="button" target="_blank"> + <?php + // If only a qty upgrade is required, show a more generic message. + if ( ! empty( $upgrade_type ) && 'qty' === $upgrade_type ) { + esc_html_e( 'Upgrade your Subscription Level', 'akismet' ); + } else { + echo esc_html( + sprintf( + /* translators: The placeholder is the name of a subscription level, like "Plus" or "Enterprise" . */ + __( 'Upgrade to %s', 'akismet' ), + $upgrade_plan + ) + ); + } + ?> + </a> + </div> </div> -<?php endif;?>
\ No newline at end of file +<?php endif; ?> diff --git a/plugins/akismet/views/setup.php b/plugins/akismet/views/setup.php index d21c89a9..50780090 100644 --- a/plugins/akismet/views/setup.php +++ b/plugins/akismet/views/setup.php @@ -1,5 +1,4 @@ -<h3><?php esc_html_e( 'Set Up Akismet' , 'akismet' );?></h3> -<div class="akismet-right"> +<div class="akismet-setup-instructions"> + <p><?php esc_html_e( 'Set up your Akismet account to enable spam filtering on this site.', 'akismet' ); ?></p> <?php Akismet::view( 'get', array( 'text' => __( 'Set up your Akismet account' , 'akismet' ), 'classes' => array( 'akismet-button', 'akismet-is-primary' ) ) ); ?> </div> -<p><?php esc_html_e( 'Set up your Akismet account to enable spam filtering on this site.', 'akismet' ); ?></p>
\ No newline at end of file diff --git a/plugins/akismet/views/stats.php b/plugins/akismet/views/stats.php index 2302c11a..81d82ce4 100644 --- a/plugins/akismet/views/stats.php +++ b/plugins/akismet/views/stats.php @@ -1,7 +1,7 @@ <div id="akismet-plugin-container"> <div class="akismet-masthead"> <div class="akismet-masthead__inside-container"> - <a href="<?php echo esc_url( Akismet_Admin::get_page_url() );?>" class="akismet-right"><?php esc_html_e( 'Akismet Settings' , 'akismet' ); ?></a> + <a href="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>" class="akismet-right"><?php esc_html_e( 'Anti-Spam Settings', 'akismet' ); ?></a> <div class="akismet-masthead__logo-container"> <img class="akismet-masthead__logo" src="<?php echo esc_url( plugins_url( '../_inc/img/logo-full-2x.png', __FILE__ ) ); ?>" alt="Akismet" /> </div> |