wp_check_comment_disallowed_list
' : 'wp_blacklist_check
'
);
break;
case 'report-spam':
if ( isset( $row['user'] ) ) {
/* translators: The placeholder is a username. */
$message = esc_html( sprintf( __( '%s reported this comment as spam.', 'akismet' ), $row['user'] ) );
} else if ( ! $message ) {
$message = esc_html( __( 'This comment was reported as spam.', 'akismet' ) );
}
break;
case 'report-ham':
if ( isset( $row['user'] ) ) {
/* translators: The placeholder is a username. */
$message = esc_html( sprintf( __( '%s reported this comment as not spam.', 'akismet' ), $row['user'] ) );
} else if ( ! $message ) {
$message = esc_html( __( 'This comment was reported as not spam.', 'akismet' ) );
}
break;
case 'cron-retry-spam':
$message = esc_html( __( 'Akismet caught this comment as spam during an automatic retry.', 'akismet' ) );
break;
case 'cron-retry-ham':
$message = esc_html( __( 'Akismet cleared this comment during an automatic retry.', 'akismet' ) );
break;
case 'check-error':
if ( isset( $row['meta'], $row['meta']['response'] ) ) {
/* translators: The placeholder is an error response returned by the API server. */
$message = sprintf( esc_html( __( 'Akismet was unable to check this comment (response: %s) but will automatically retry later.', 'akismet' ) ), '' . esc_html( $row['meta']['response'] ) . '
' );
} 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'] ) ) {
/* translators: The placeholder is an error response returned by the API server. */
$message = sprintf( esc_html( __( 'Akismet was unable to recheck this comment (response: %s).', 'akismet' ) ), '' . esc_html( $row['meta']['response'] ) . '
' );
} else {
$message = esc_html( __( 'Akismet was unable to recheck this comment.', 'akismet' ) );
}
break;
default:
if ( preg_match( '/^status-changed/', $row['event'] ) ) {
// 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'] );
/* translators: The placeholder is a short string (like 'spam' or 'approved') denoting the new comment status. */
$message = sprintf( esc_html( __( 'Comment status was changed to %s', 'akismet' ) ), '' . esc_html( $new_status ) . '
' );
} else if ( preg_match( '/^status-/', $row['event'] ) ) {
$new_status = preg_replace( '/^status-/', '', $row['event'] );
if ( isset( $row['user'] ) ) {
/* translators: %1$s is a username; %2$s is a short string (like 'spam' or 'approved') denoting the new comment status. */
$message = sprintf( esc_html( __( '%1$s changed the comment status to %2$s.', 'akismet' ) ), $row['user'], '' . esc_html( $new_status ) . '
' );
}
}
break;
}
}
if ( ! empty( $message ) ) {
echo ''; if ( isset( $row['time'] ) ) { $time = gmdate( 'D d M Y @ h:i:s a', $row['time'] ) . ' GMT'; /* translators: The placeholder is an amount of time, like "7 seconds" or "3 days" returned by the function human_time_diff(). */ $time_html = '' . sprintf( esc_html__( '%s ago', 'akismet' ), human_time_diff( $row['time'] ) ) . ''; echo sprintf( /* translators: %1$s is a human-readable time difference, like "3 hours ago", and %2$s is an already-translated phrase describing how a comment's status changed, like "This comment was reported as spam." */ esc_html( __( '%1$s - %2$s', 'akismet' ) ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $time_html, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $message ); // esc_html() is done above so that we can use HTML in $message. } else { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $message; // esc_html() is done above so that we can use HTML in $message. } echo '
'; } } } else { echo ''; echo esc_html( __( 'No comment history.', 'akismet' ) ); echo '
'; } } public static function plugin_action_links( $links, $file ) { if ( $file == plugin_basename( plugin_dir_url( __FILE__ ) . '/akismet.php' ) ) { $links[] = ''.esc_html__( 'Settings' , 'akismet').''; } return $links; } // Total spam in queue // get_option( 'akismet_spam_count' ) is the total caught ever public static function get_spam_count( $type = false ) { global $wpdb; if ( !$type ) { // total $count = wp_cache_get( 'akismet_spam_count', 'widget' ); if ( false === $count ) { $count = wp_count_comments(); $count = $count->spam; wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 ); } return $count; } elseif ( 'comments' == $type || 'comment' == $type ) { // comments $type = ''; } return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE comment_approved = 'spam' AND comment_type = %s", $type ) ); } // Check connectivity between the WordPress blog and Akismet's servers. // Returns an associative array of server IP addresses, where the key is the IP address, and value is true (available) or false (unable to connect). public static function check_server_ip_connectivity() { $servers = $ips = array(); // Some web hosts may disable this function if ( function_exists('gethostbynamel') ) { $ips = gethostbynamel( 'rest.akismet.com' ); if ( $ips && is_array($ips) && count($ips) ) { $api_key = Akismet::get_api_key(); foreach ( $ips as $ip ) { $response = Akismet::verify_key( $api_key, $ip ); // even if the key is invalid, at least we know we have connectivity if ( $response == 'valid' || $response == 'invalid' ) $servers[$ip] = 'connected'; else $servers[$ip] = $response ? $response : 'unable to connect'; } } } return $servers; } // Simpler connectivity check public static function check_server_connectivity($cache_timeout = 86400) { $debug = array(); $debug[ 'PHP_VERSION' ] = PHP_VERSION; $debug[ 'WORDPRESS_VERSION' ] = $GLOBALS['wp_version']; $debug[ 'AKISMET_VERSION' ] = AKISMET_VERSION; $debug[ 'AKISMET__PLUGIN_DIR' ] = AKISMET__PLUGIN_DIR; $debug[ 'SITE_URL' ] = site_url(); $debug[ 'HOME_URL' ] = home_url(); $servers = get_option('akismet_available_servers'); if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false ) { $servers = self::check_server_ip_connectivity(); update_option('akismet_available_servers', $servers); update_option('akismet_connectivity_time', time()); } if ( wp_http_supports( array( 'ssl' ) ) ) { $response = wp_remote_get( 'https://rest.akismet.com/1.1/test' ); } else { $response = wp_remote_get( 'http://rest.akismet.com/1.1/test' ); } $debug[ 'gethostbynamel' ] = function_exists('gethostbynamel') ? 'exists' : 'not here'; $debug[ 'Servers' ] = $servers; $debug[ 'Test Connection' ] = $response; Akismet::log( $debug ); if ( $response && 'connected' == wp_remote_retrieve_body( $response ) ) return true; return false; } // Check the server connectivity and store the available servers in an option. public static function get_server_connectivity($cache_timeout = 86400) { return self::check_server_connectivity( $cache_timeout ); } /** * Find out whether any comments in the Pending queue have not yet been checked by Akismet. * * @return bool */ public static function are_any_comments_waiting_to_be_checked() { return !! get_comments( array( // Exclude comments that are not pending. This would happen if someone manually approved or spammed a comment // that was waiting to be checked. The akismet_error meta entry will eventually be removed by the cron recheck job. 'status' => 'hold', // This is the commentmeta that is saved when a comment couldn't be checked. 'meta_key' => 'akismet_error', // We only need to know whether at least one comment is waiting for a check. 'number' => 1, ) ); } public static function get_page_url( $page = 'config' ) { $args = array( 'page' => 'akismet-key-config' ); if ( $page == 'stats' ) { $args = array( 'page' => 'akismet-key-config', 'view' => 'stats' ); } elseif ( $page == 'delete_key' ) { $args = array( 'page' => 'akismet-key-config', 'view' => 'start', 'action' => 'delete-key', '_wpnonce' => wp_create_nonce( self::NONCE ) ); } elseif ( $page === 'init' ) { $args = array( 'page' => 'akismet-key-config', 'view' => 'start' ); } return add_query_arg( $args, menu_page_url( 'akismet-key-config', false ) ); } public static function get_akismet_user( $api_key ) { $akismet_user = false; $subscription_verification = Akismet::http_post( Akismet::build_query( array( 'key' => $api_key, 'blog' => get_option( 'home' ) ) ), 'get-subscription' ); if ( ! empty( $subscription_verification[1] ) ) { if ( 'invalid' !== $subscription_verification[1] ) { $akismet_user = json_decode( $subscription_verification[1] ); } } return $akismet_user; } public static function get_stats( $api_key ) { $stat_totals = array(); foreach( array( '6-months', 'all' ) as $interval ) { $response = Akismet::http_post( Akismet::build_query( array( 'blog' => get_option( 'home' ), 'key' => $api_key, 'from' => $interval ) ), 'get-stats' ); if ( ! empty( $response[1] ) ) { $stat_totals[$interval] = json_decode( $response[1] ); } } return $stat_totals; } public static function verify_wpcom_key( $api_key, $user_id, $extra = array() ) { $akismet_account = Akismet::http_post( Akismet::build_query( array_merge( array( 'user_id' => $user_id, 'api_key' => $api_key, 'get_account_type' => 'true' ), $extra ) ), 'verify-wpcom-key' ); if ( ! empty( $akismet_account[1] ) ) $akismet_account = json_decode( $akismet_account[1] ); Akismet::log( compact( 'akismet_account' ) ); return $akismet_account; } public static function connect_jetpack_user() { if ( $jetpack_user = self::get_jetpack_user() ) { if ( isset( $jetpack_user['user_id'] ) && isset( $jetpack_user['api_key'] ) ) { $akismet_user = self::verify_wpcom_key( $jetpack_user['api_key'], $jetpack_user['user_id'], array( 'action' => 'connect_jetpack_user' ) ); if ( is_object( $akismet_user ) ) { self::save_key( $akismet_user->api_key ); return in_array( $akismet_user->status, array( 'active', 'active-dunning', 'no-sub' ) ); } } } return false; } public static function display_alert() { Akismet::view( 'notice', array( 'type' => 'alert', 'code' => (int) get_option( 'akismet_alert_code' ), 'msg' => get_option( 'akismet_alert_msg' ) ) ); } 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() { Akismet::fix_scheduled_recheck(); if ( wp_next_scheduled('akismet_schedule_cron_recheck') > time() && self::are_any_comments_waiting_to_be_checked() ) { /* * The 'akismet_display_cron_disabled_notice' filter can be used to control whether the WP-Cron disabled notice is displayed. */ if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON && apply_filters( 'akismet_display_cron_disabled_notice', true ) ) { Akismet::view( 'notice', array( 'type' => 'spam-check-cron-disabled' ) ); } else { /* translators: The Akismet configuration page URL. */ $link_text = apply_filters( 'akismet_spam_check_warning_link_text', sprintf( __( 'Please check your Akismet configuration and contact your web host if problems persist.', 'akismet' ), esc_url( self::get_page_url() ) ) ); Akismet::view( 'notice', array( 'type' => 'spam-check', 'link_text' => $link_text ) ); } } } public static function display_api_key_warning() { Akismet::view( 'notice', array( 'type' => 'plugin' ) ); } public static function display_page() { if ( !Akismet::get_api_key() || ( isset( $_GET['view'] ) && $_GET['view'] == 'start' ) ) self::display_start_page(); elseif ( isset( $_GET['view'] ) && $_GET['view'] == 'stats' ) self::display_stats_page(); else self::display_configuration_page(); } public static function display_start_page() { if ( isset( $_GET['action'] ) ) { if ( $_GET['action'] == 'delete-key' ) { if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], self::NONCE ) ) delete_option( 'wordpress_api_key' ); } } if ( $api_key = Akismet::get_api_key() && ( empty( self::$notices['status'] ) || 'existing-key-invalid' != self::$notices['status'] ) ) { self::display_configuration_page(); return; } //the user can choose to auto connect their API key by clicking a button on the akismet done page //if jetpack, get verified api key by using connected wpcom user id //if no jetpack, get verified api key by using an akismet token $akismet_user = false; if ( isset( $_GET['token'] ) && preg_match('/^(\d+)-[0-9a-f]{20}$/', $_GET['token'] ) ) $akismet_user = self::verify_wpcom_key( '', '', array( 'token' => $_GET['token'] ) ); elseif ( $jetpack_user = self::get_jetpack_user() ) $akismet_user = self::verify_wpcom_key( $jetpack_user['api_key'], $jetpack_user['user_id'] ); if ( isset( $_GET['action'] ) ) { if ( $_GET['action'] == 'save-key' ) { if ( is_object( $akismet_user ) ) { self::save_key( $akismet_user->api_key ); self::display_configuration_page(); return; } } } Akismet::view( 'start', compact( 'akismet_user' ) ); /* // To see all variants when testing. $akismet_user->status = 'no-sub'; Akismet::view( 'start', compact( 'akismet_user' ) ); $akismet_user->status = 'cancelled'; Akismet::view( 'start', compact( 'akismet_user' ) ); $akismet_user->status = 'suspended'; Akismet::view( 'start', compact( 'akismet_user' ) ); $akismet_user->status = 'other'; Akismet::view( 'start', compact( 'akismet_user' ) ); $akismet_user = false; */ } public static function display_stats_page() { Akismet::view( 'stats' ); } public static function display_configuration_page() { $api_key = Akismet::get_api_key(); $akismet_user = self::get_akismet_user( $api_key ); if ( ! $akismet_user ) { // This could happen if the user's key became invalid after it was previously valid and successfully set up. self::$notices['status'] = 'existing-key-invalid'; self::display_start_page(); return; } $stat_totals = self::get_stats( $api_key ); // If unset, create the new strictness option using the old discard option to determine its default. // If the old option wasn't set, default to discarding the blatant spam. if ( get_option( 'akismet_strictness' ) === false ) { add_option( 'akismet_strictness', ( get_option( 'akismet_discard_month' ) === 'false' ? '0' : '1' ) ); } // Sync the local "Total spam blocked" count with the authoritative count from the server. if ( isset( $stat_totals['all'], $stat_totals['all']->spam ) ) { update_option( 'akismet_spam_count', $stat_totals['all']->spam ); } $notices = array(); if ( empty( self::$notices ) ) { if ( ! empty( $stat_totals['all'] ) && isset( $stat_totals['all']->time_saved ) && $akismet_user->status == 'active' && $akismet_user->account_type == 'free-api-key' ) { $time_saved = false; if ( $stat_totals['all']->time_saved > 1800 ) { $total_in_minutes = round( $stat_totals['all']->time_saved / 60 ); $total_in_hours = round( $total_in_minutes / 60 ); $total_in_days = round( $total_in_hours / 8 ); $cleaning_up = __( 'Cleaning up spam takes time.' , 'akismet'); if ( $total_in_days > 1 ) $time_saved = $cleaning_up . ' ' . sprintf( _n( 'Akismet has saved you %s day!', 'Akismet has saved you %s days!', $total_in_days, 'akismet' ), number_format_i18n( $total_in_days ) ); elseif ( $total_in_hours > 1 ) $time_saved = $cleaning_up . ' ' . sprintf( _n( 'Akismet has saved you %d hour!', 'Akismet has saved you %d hours!', $total_in_hours, 'akismet' ), $total_in_hours ); elseif ( $total_in_minutes >= 30 ) $time_saved = $cleaning_up . ' ' . sprintf( _n( 'Akismet has saved you %d minute!', 'Akismet has saved you %d minutes!', $total_in_minutes, 'akismet' ), $total_in_minutes ); } $notices[] = array( 'type' => 'active-notice', 'time_saved' => $time_saved ); } if ( !empty( $akismet_user->limit_reached ) && in_array( $akismet_user->limit_reached, array( 'yellow', 'red' ) ) ) { $notices[] = array( 'type' => 'limit-reached', 'level' => $akismet_user->limit_reached ); } } if ( !isset( self::$notices['status'] ) && in_array( $akismet_user->status, array( 'cancelled', 'suspended', 'missing', 'no-sub' ) ) ) { $notices[] = array( 'type' => $akismet_user->status ); } $alert_code = get_option( 'akismet_alert_code' ); if ( isset( Akismet::$limit_notices[ $alert_code ] ) ) { $notices[] = self::get_usage_limit_alert_data(); } /* // To see all variants when testing. $notices[] = array( 'type' => 'active-notice', 'time_saved' => 'Cleaning up spam takes time. Akismet has saved you 1 minute!' ); $notices[] = array( 'type' => 'plugin' ); $notices[] = array( 'type' => 'spam-check', 'link_text' => 'Link text.' ); $notices[] = array( 'type' => 'notice', 'notice_header' => 'This is the notice header.', 'notice_text' => 'This is the notice text.' ); $notices[] = array( 'type' => 'missing-functions' ); $notices[] = array( 'type' => 'servers-be-down' ); $notices[] = array( 'type' => 'active-dunning' ); $notices[] = array( 'type' => 'cancelled' ); $notices[] = array( 'type' => 'suspended' ); $notices[] = array( 'type' => 'missing' ); $notices[] = array( 'type' => 'no-sub' ); $notices[] = array( 'type' => 'new-key-valid' ); $notices[] = array( 'type' => 'new-key-invalid' ); $notices[] = array( 'type' => 'existing-key-invalid' ); $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/' ); $notices[] = array( 'type' => 'spam-check-cron-disabled' ); */ Akismet::log( compact( 'stat_totals', 'akismet_user' ) ); Akismet::view( 'config', compact( 'api_key', 'akismet_user', 'stat_totals', 'notices' ) ); } public static function display_notice() { global $hook_suffix; if ( in_array( $hook_suffix, array( 'jetpack_page_akismet-key-config', 'settings_page_akismet-key-config' ) ) ) { // This page manages the notices and puts them inline where they make sense. return; } 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 $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 ( ( '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(); } 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 awaiting moderation.', 'akismet' ); } else { $message = sprintf( _n( 'Akismet checked %s comment.', 'Akismet checked %s comments.', $recheck_count, 'akismet' ), number_format( $recheck_count ) ); $message .= ' '; if ( $spam_count === 0 ) { $message .= __( 'No comments were caught as spam.', 'akismet' ); } else { $message .= sprintf( _n( '%s comment was caught as spam.', '%s comments were caught as spam.', $spam_count, 'akismet' ), number_format( $spam_count ) ); } } echo '' . esc_html( $message ) . '
' . esc_html( __( 'Akismet could not recheck your comments for spam.', 'akismet' ) ) . '