7 Plugin URI: http://akismet.com/
8 Description: Akismet checks your comments against the Akismet web service to see if they look like spam or not. You need an <a href="http://akismet.com/get/">API key</a> to use it. You can review the spam it catches under "Comments." To show off your Akismet stats just put <code><?php akismet_counter(); ?></code> in your template. See also: <a href="http://wordpress.org/extend/plugins/stats/">WP Stats plugin</a>.
11 Author URI: http://automattic.com/wordpress-plugins/
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; version 2 of the License.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 define('AKISMET_VERSION', '2.4.0');
32 /** If you hardcode a WP.com API key here, all key config screens will be hidden */
33 if ( defined('WPCOM_API_KEY') )
34 $wpcom_api_key = constant('WPCOM_API_KEY');
38 // Make sure we don't expose any info if called directly
39 if ( !function_exists( 'add_action' ) ) {
40 echo "Hi there! I'm just a plugin, not much I can do when called directly.";
44 if ( $wp_db_version <= 9872 )
45 include_once( dirname(__FILE__) . '/legacy.php' );
47 function akismet_init() {
48 global $wpcom_api_key, $akismet_api_host, $akismet_api_port;
51 $akismet_api_host = $wpcom_api_key . '.rest.akismet.com';
53 $akismet_api_host = get_option('wordpress_api_key') . '.rest.akismet.com';
55 $akismet_api_port = 80;
56 add_action('admin_menu', 'akismet_config_page');
57 add_action('admin_menu', 'akismet_stats_page');
58 akismet_admin_warnings();
60 add_action('init', 'akismet_init');
62 function akismet_admin_init() {
63 if ( function_exists( 'get_plugin_page_hook' ) )
64 $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
66 $hook = 'dashboard_page_akismet-stats-display';
67 add_action('admin_head-'.$hook, 'akismet_stats_script');
69 add_action('admin_init', 'akismet_admin_init');
71 if ( !function_exists('wp_nonce_field') ) {
72 function akismet_nonce_field($action = -1) { return; }
75 function akismet_nonce_field($action = -1) { return wp_nonce_field($action); }
76 $akismet_nonce = 'akismet-update-key';
79 if ( !function_exists('number_format_i18n') ) {
80 function number_format_i18n( $number, $decimals = null ) { return number_format( $number, $decimals ); }
83 function akismet_config_page() {
84 if ( function_exists('add_submenu_page') )
85 add_submenu_page('plugins.php', __('Akismet Configuration'), __('Akismet Configuration'), 'manage_options', 'akismet-key-config', 'akismet_conf');
89 function akismet_conf() {
90 global $akismet_nonce, $wpcom_api_key;
92 if ( isset($_POST['submit']) ) {
93 if ( function_exists('current_user_can') && !current_user_can('manage_options') )
94 die(__('Cheatin’ uh?'));
96 check_admin_referer( $akismet_nonce );
97 $key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
100 $key_status = 'empty';
101 $ms[] = 'new_key_empty';
102 delete_option('wordpress_api_key');
104 $key_status = akismet_verify_key( $key );
107 if ( $key_status == 'valid' ) {
108 update_option('wordpress_api_key', $key);
109 $ms[] = 'new_key_valid';
110 } else if ( $key_status == 'invalid' ) {
111 $ms[] = 'new_key_invalid';
112 } else if ( $key_status == 'failed' ) {
113 $ms[] = 'new_key_failed';
116 if ( isset( $_POST['akismet_discard_month'] ) )
117 update_option( 'akismet_discard_month', 'true' );
119 update_option( 'akismet_discard_month', 'false' );
120 } elseif ( isset($_POST['check']) ) {
121 akismet_get_server_connectivity(0);
124 if ( empty( $key_status) || $key_status != 'valid' ) {
125 $key = get_option('wordpress_api_key');
126 if ( empty( $key ) ) {
127 if ( empty( $key_status ) || $key_status != 'failed' ) {
128 if ( akismet_verify_key( '1234567890ab' ) == 'failed' )
129 $ms[] = 'no_connection';
133 $key_status = 'empty';
135 $key_status = akismet_verify_key( $key );
137 if ( $key_status == 'valid' ) {
139 } else if ( $key_status == 'invalid' ) {
140 delete_option('wordpress_api_key');
142 } else if ( !empty($key) && $key_status == 'failed' ) {
143 $ms[] = 'key_failed';
148 'new_key_empty' => array('color' => 'aa0', 'text' => __('Your key has been cleared.')),
149 'new_key_valid' => array('color' => '2d2', 'text' => __('Your key has been verified. Happy blogging!')),
150 'new_key_invalid' => array('color' => 'd22', 'text' => __('The key you entered is invalid. Please double-check it.')),
151 'new_key_failed' => array('color' => 'd22', 'text' => __('The key you entered could not be verified because a connection to akismet.com could not be established. Please check your server configuration.')),
152 'no_connection' => array('color' => 'd22', 'text' => __('There was a problem connecting to the Akismet server. Please check your server configuration.')),
153 'key_empty' => array('color' => 'aa0', 'text' => sprintf(__('Please enter an API key. (<a href="%s" style="color:#fff">Get your key.</a>)'), 'http://akismet.com/get/')),
154 'key_valid' => array('color' => '2d2', 'text' => __('This key is valid.')),
155 'key_failed' => array('color' => 'aa0', 'text' => __('The key below was previously validated but a connection to akismet.com can not be established at this time. Please check your server configuration.')));
157 <?php if ( !empty($_POST['submit'] ) ) : ?>
158 <div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
161 <h2><?php _e('Akismet Configuration'); ?></h2>
163 <form action="" method="post" id="akismet-conf" style="margin: auto; width: 400px; ">
164 <?php if ( !$wpcom_api_key ) { ?>
165 <p><?php printf(__('For many people, <a href="%1$s">Akismet</a> will greatly reduce or even completely eliminate the comment and trackback spam you get on your site. If one does happen to get through, simply mark it as "spam" on the moderation screen and Akismet will learn from the mistakes. If you don\'t have an API key yet, you can get one at <a href="%2$s">Akismet.com</a>.'), 'http://akismet.com/', 'http://akismet.com/get/'); ?></p>
167 <h3><label for="key"><?php _e('Akismet API Key'); ?></label></h3>
168 <?php foreach ( $ms as $m ) : ?>
169 <p style="padding: .5em; background-color: #<?php echo $messages[$m]['color']; ?>; color: #fff; font-weight: bold;"><?php echo $messages[$m]['text']; ?></p>
171 <p><input id="key" name="key" type="text" size="15" maxlength="12" value="<?php echo get_option('wordpress_api_key'); ?>" style="font-family: 'Courier New', Courier, mono; font-size: 1.5em;" /> (<?php _e('<a href="http://akismet.com/get/">What is this?</a>'); ?>)</p>
172 <?php if ( isset( $invalid_key) && $invalid_key ) { ?>
173 <h3><?php _e('Why might my key be invalid?'); ?></h3>
174 <p><?php _e('This can mean one of two things, either you copied the key wrong or that the plugin is unable to reach the Akismet servers, which is most often caused by an issue with your web host around firewalls or similar.'); ?></p>
177 <?php akismet_nonce_field($akismet_nonce) ?>
178 <p><label><input name="akismet_discard_month" id="akismet_discard_month" value="true" type="checkbox" <?php if ( get_option('akismet_discard_month') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Automatically discard spam comments on posts older than a month.'); ?></label></p>
179 <p class="submit"><input type="submit" name="submit" value="<?php _e('Update options »'); ?>" /></p>
182 <form action="" method="post" id="akismet-connectivity" style="margin: auto; width: 400px; ">
184 <h3><?php _e('Server Connectivity'); ?></h3>
186 if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) {
188 <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Network functions are disabled.'); ?></p>
189 <p><?php echo sprintf( __('Your web host or server administrator has disabled PHP\'s <code>fsockopen</code> or <code>gethostbynamel</code> functions. <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>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
192 $servers = akismet_get_server_connectivity();
193 $fail_count = count($servers) - count( array_filter($servers) );
194 if ( is_array($servers) && count($servers) > 0 ) {
195 // some connections work, some fail
196 if ( $fail_count > 0 && $fail_count < count($servers) ) { ?>
197 <p style="padding: .5em; background-color: #aa0; color: #fff; font-weight:bold;"><?php _e('Unable to reach some Akismet servers.'); ?></p>
198 <p><?php echo sprintf( __('A network problem or firewall is blocking some connections from your web server to Akismet.com. Akismet is working but this may cause problems during times of network congestion. Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
200 // all connections fail
201 } elseif ( $fail_count > 0 ) { ?>
202 <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Unable to reach any Akismet servers.'); ?></p>
203 <p><?php echo sprintf( __('A network problem or firewall is blocking all connections from your web server to Akismet.com. <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 and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
205 // all connections work
207 <p style="padding: .5em; background-color: #2d2; color: #fff; font-weight:bold;"><?php _e('All Akismet servers are available.'); ?></p>
208 <p><?php _e('Akismet is working correctly. All servers are accessible.'); ?></p>
213 <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Unable to find Akismet servers.'); ?></p>
214 <p><?php echo sprintf( __('A DNS problem or firewall is preventing all access from your web server to Akismet.com. <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 and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
219 if ( !empty($servers) ) {
221 <table style="width: 100%;">
222 <thead><th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th></thead>
226 foreach ( $servers as $ip => $status ) {
227 $color = ( $status ? '#2d2' : '#d22');
230 <td><?php echo htmlspecialchars($ip); ?></td>
231 <td style="padding: 0 .5em; font-weight:bold; color: #fff; background-color: <?php echo $color; ?>"><?php echo ($status ? __('No problems') : __('Obstructed') ); ?></td>
239 <p><?php if ( get_option('akismet_connectivity_time') ) echo sprintf( __('Last checked %s ago.'), human_time_diff( get_option('akismet_connectivity_time') ) ); ?></p>
240 <p class="submit"><input type="submit" name="check" value="<?php _e('Check network status »'); ?>" /></p>
248 function akismet_stats_page() {
249 if ( function_exists('add_submenu_page') )
250 add_submenu_page('index.php', __('Akismet Stats'), __('Akismet Stats'), 'manage_options', 'akismet-stats-display', 'akismet_stats_display');
254 function akismet_stats_script() {
256 <script type="text/javascript">
257 function resizeIframe() {
258 var height = document.documentElement.clientHeight;
259 height -= document.getElementById('akismet-stats-frame').offsetTop;
260 height += 100; // magic padding
262 document.getElementById('akismet-stats-frame').style.height = height +"px";
265 function resizeIframeInit() {
266 document.getElementById('akismet-stats-frame').onload = resizeIframe;
267 window.onresize = resizeIframe;
269 addLoadEvent(resizeIframeInit);
274 function akismet_stats_display() {
275 global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
276 $blog = urlencode( get_option('home') );
277 $url = "http://".akismet_get_key().".web.akismet.com/1.0/user-stats.php?blog={$blog}";
280 <iframe src="<?php echo $url; ?>" width="100%" height="100%" frameborder="0" id="akismet-stats-frame"></iframe>
285 function akismet_stats() {
286 if ( !function_exists('did_action') || did_action( 'rightnow_end' ) ) // We already displayed this info in the "Right Now" section
288 if ( !$count = get_option('akismet_spam_count') )
290 $path = plugin_basename(__FILE__);
291 echo '<h3>'.__('Spam').'</h3>';
293 if ( isset( $submenu['edit-comments.php'] ) )
294 $link = 'edit-comments.php';
297 echo '<p>'.sprintf(__('<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.'), 'http://akismet.com/', clean_url("$link?page=akismet-admin"), number_format_i18n($count) ).'</p>';
299 add_action('activity_box_end', 'akismet_stats');
301 function akismet_get_key() {
302 global $wpcom_api_key;
303 if ( !empty($wpcom_api_key) )
304 return $wpcom_api_key;
305 return get_option('wordpress_api_key');
308 function akismet_verify_key( $key, $ip = null ) {
309 global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
310 $blog = urlencode( get_option('home') );
311 if ( $wpcom_api_key )
312 $key = $wpcom_api_key;
313 $response = akismet_http_post("key=$key&blog=$blog", 'rest.akismet.com', '/1.1/verify-key', $akismet_api_port, $ip);
314 if ( !is_array($response) || !isset($response[1]) || $response[1] != 'valid' && $response[1] != 'invalid' )
319 // Check connectivity between the WordPress blog and Akismet's servers.
320 // 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).
321 function akismet_check_server_connectivity() {
322 global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
324 $test_host = 'rest.akismet.com';
326 // Some web hosts may disable one or both functions
327 if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') )
330 $ips = gethostbynamel($test_host);
331 if ( !$ips || !is_array($ips) || !count($ips) )
335 foreach ( $ips as $ip ) {
336 $response = akismet_verify_key( akismet_get_key(), $ip );
337 // even if the key is invalid, at least we know we have connectivity
338 if ( $response == 'valid' || $response == 'invalid' )
339 $servers[$ip] = true;
341 $servers[$ip] = false;
347 // Check the server connectivity and store the results in an option.
348 // Cached results will be used if not older than the specified timeout in seconds; use $cache_timeout = 0 to force an update.
349 // Returns the same associative array as akismet_check_server_connectivity()
350 function akismet_get_server_connectivity( $cache_timeout = 86400 ) {
351 $servers = get_option('akismet_available_servers');
352 if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false )
355 // There's a race condition here but the effect is harmless.
356 $servers = akismet_check_server_connectivity();
357 update_option('akismet_available_servers', $servers);
358 update_option('akismet_connectivity_time', time());
362 // Returns true if server connectivity was OK at the last check, false if there was a problem that needs to be fixed.
363 function akismet_server_connectivity_ok() {
364 // skip the check on WPMU because the status page is hidden
365 global $wpcom_api_key;
366 if ( $wpcom_api_key )
368 $servers = akismet_get_server_connectivity();
369 return !( empty($servers) || !count($servers) || count( array_filter($servers) ) < count($servers) );
372 function akismet_admin_warnings() {
373 global $wpcom_api_key;
374 if ( !get_option('wordpress_api_key') && !$wpcom_api_key && !isset($_POST['submit']) ) {
375 function akismet_warning() {
377 <div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet is almost ready.')."</strong> ".sprintf(__('You must <a href="%1$s">enter your Akismet API key</a> for it to work.'), "plugins.php?page=akismet-key-config")."</p></div>
380 add_action('admin_notices', 'akismet_warning');
382 } elseif ( get_option('akismet_connectivity_time') && empty($_POST) && is_admin() && !akismet_server_connectivity_ok() ) {
383 function akismet_warning() {
385 <div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet has detected a problem.')."</strong> ".sprintf(__('A server or network problem is preventing Akismet from working correctly. <a href="%1$s">Click here for more information</a> about how to fix the problem.'), "plugins.php?page=akismet-key-config")."</p></div>
388 add_action('admin_notices', 'akismet_warning');
393 function akismet_get_host($host) {
394 // if all servers are accessible, just return the host name.
395 // if not, return an IP that was known to be accessible at the last check.
396 if ( akismet_server_connectivity_ok() ) {
399 $ips = akismet_get_server_connectivity();
400 // a firewall may be blocking access to some Akismet IPs
401 if ( count($ips) > 0 && count(array_filter($ips)) < count($ips) ) {
402 // use DNS to get current IPs, but exclude any known to be unreachable
403 $dns = (array)gethostbynamel( rtrim($host, '.') . '.' );
404 $dns = array_filter($dns);
405 foreach ( $dns as $ip ) {
406 if ( array_key_exists( $ip, $ips ) && empty( $ips[$ip] ) )
409 // return a random IP from those available
411 return $dns[ array_rand($dns) ];
415 // if all else fails try the host name
419 // return a comma-separated list of role names for the given user
420 function akismet_get_user_roles($user_id ) {
423 if ( !class_exists('WP_User') )
426 if ( $user_id > 0 ) {
427 $comment_user = new WP_User($user_id);
428 if ( isset($comment_user->roles) )
429 $roles = join(',', $comment_user->roles);
435 // Returns array with headers in $response[0] and body in $response[1]
436 function akismet_http_post($request, $host, $path, $port = 80, $ip=null) {
439 $akismet_version = constant('AKISMET_VERSION');
441 $http_request = "POST $path HTTP/1.0\r\n";
442 $http_request .= "Host: $host\r\n";
443 $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=" . get_option('blog_charset') . "\r\n";
444 $http_request .= "Content-Length: " . strlen($request) . "\r\n";
445 $http_request .= "User-Agent: WordPress/$wp_version | Akismet/$akismet_version\r\n";
446 $http_request .= "\r\n";
447 $http_request .= $request;
450 // use a specific IP if provided - needed by akismet_check_server_connectivity()
451 if ( $ip && long2ip(ip2long($ip)) ) {
454 $http_host = akismet_get_host($host);
458 if( false != ( $fs = @fsockopen($http_host, $port, $errno, $errstr, 10) ) ) {
459 fwrite($fs, $http_request);
462 $response .= fgets($fs, 1160); // One TCP-IP packet
464 $response = explode("\r\n\r\n", $response, 2);
469 // filter handler used to return a spam result to pre_comment_approved
470 function akismet_result_spam( $approved ) {
471 // bump the counter here instead of when the filter is added to reduce the possibility of overcounting
472 if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
473 update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
477 function akismet_auto_check_comment( $commentdata ) {
478 global $akismet_api_host, $akismet_api_port;
480 $comment = $commentdata;
481 $comment['user_ip'] = $_SERVER['REMOTE_ADDR'];
482 $comment['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
483 $comment['referrer'] = $_SERVER['HTTP_REFERER'];
484 $comment['blog'] = get_option('home');
485 $comment['blog_lang'] = get_locale();
486 $comment['blog_charset'] = get_option('blog_charset');
487 $comment['permalink'] = get_permalink($comment['comment_post_ID']);
489 $comment['user_role'] = akismet_get_user_roles($comment['user_ID']);
491 $ignore = array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW' );
493 foreach ( $_SERVER as $key => $value )
494 if ( !in_array( $key, $ignore ) && is_string($value) )
495 $comment["$key"] = $value;
497 $comment["$key"] = '';
500 foreach ( $comment as $key => $data )
501 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
503 $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
504 $commentdata['akismet_result'] = $response[1];
505 if ( 'true' == $response[1] ) {
506 // akismet_spam_count will be incremented later by akismet_result_spam()
507 add_filter('pre_comment_approved', 'akismet_result_spam');
509 do_action( 'akismet_spam_caught' );
511 $post = get_post( $comment['comment_post_ID'] );
512 $last_updated = strtotime( $post->post_modified_gmt );
513 $diff = time() - $last_updated;
514 $diff = $diff / 86400;
516 if ( $post->post_type == 'post' && $diff > 30 && get_option( 'akismet_discard_month' ) == 'true' && empty($comment['user_ID']) ) {
517 // akismet_result_spam() won't be called so bump the counter here
518 if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
519 update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
524 if ( function_exists('wp_next_scheduled') && function_exists('wp_schedule_event') ) {
525 // WP 2.1+: delete old comments daily
526 if ( !wp_next_scheduled('akismet_scheduled_delete') )
527 wp_schedule_event(time(), 'daily', 'akismet_scheduled_delete');
528 } elseif ( (mt_rand(1, 10) == 3) ) {
529 // WP 2.0: run this one time in ten
530 akismet_delete_old();
535 function akismet_delete_old() {
537 $now_gmt = current_time('mysql', 1);
538 $comment_ids = $wpdb->get_col("SELECT comment_id FROM $wpdb->comments WHERE DATE_SUB('$now_gmt', INTERVAL 15 DAY) > comment_date_gmt AND comment_approved = 'spam'");
539 if ( empty( $comment_ids ) )
542 do_action( 'delete_comment', $comment_ids );
543 $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_id IN ( " . implode( ', ', $comment_ids ) . " )");
544 $n = mt_rand(1, 5000);
545 if ( apply_filters('akismet_optimize_table', ($n == 11)) ) // lucky number
546 $wpdb->query("OPTIMIZE TABLE $wpdb->comments");
550 add_action('akismet_scheduled_delete', 'akismet_delete_old');
552 function akismet_submit_nonspam_comment ( $comment_id ) {
553 global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
554 $comment_id = (int) $comment_id;
556 $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
557 if ( !$comment ) // it was deleted
559 $comment->blog = get_option('home');
560 $comment->blog_lang = get_locale();
561 $comment->blog_charset = get_option('blog_charset');
562 $comment->permalink = get_permalink($comment->comment_post_ID);
563 if ( is_object($current_user) ) {
564 $comment->reporter = $current_user->user_login;
566 if ( is_object($current_site) ) {
567 $comment->site_domain = $current_site->domain;
570 $comment->user_role = '';
571 if ( isset( $comment->user_ID ) )
572 $comment->user_role = akismet_get_user_roles($comment->user_ID);
575 foreach ( $comment as $key => $data )
576 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
578 $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-ham", $akismet_api_port);
579 do_action('akismet_submit_nonspam_comment', $comment_id, $response[1]);
582 function akismet_submit_spam_comment ( $comment_id ) {
583 global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
584 $comment_id = (int) $comment_id;
586 $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
587 if ( !$comment ) // it was deleted
589 if ( 'spam' != $comment->comment_approved )
591 $comment->blog = get_option('home');
592 $comment->blog_lang = get_locale();
593 $comment->blog_charset = get_option('blog_charset');
594 $comment->permalink = get_permalink($comment->comment_post_ID);
595 if ( is_object($current_user) ) {
596 $comment->reporter = $current_user->user_login;
598 if ( is_object($current_site) ) {
599 $comment->site_domain = $current_site->domain;
602 $comment->user_role = '';
603 if ( !isset( $comment->user_id ) )
604 $comment->user_role = akismet_get_user_roles($comment->user_ID);
607 foreach ( $comment as $key => $data )
608 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
610 $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-spam", $akismet_api_port);
611 do_action('akismet_submit_spam_comment', $comment_id, $response[1]);
614 add_action('preprocess_comment', 'akismet_auto_check_comment', 1);
616 // For old versions of WP only
617 function akismet_set_comment_status( $comment_id, $status ) {
618 if ( $status == 'spam' ) {
619 akismet_submit_spam_comment( $comment_id );
620 } elseif ( $status == 'approve' ) {
621 akismet_submit_nonspam_comment( $comment_id );
626 function akismet_transition_comment_status( $new_status, $old_status, $comment ) {
627 if ( $new_status == $old_status )
630 if ( $new_status == 'spam' ) {
631 akismet_submit_spam_comment( $comment->comment_ID );
632 } elseif ( $old_status == 'spam' && ( $new_status == 'approved' || $new_status == 'unapproved' ) ) {
633 akismet_submit_nonspam_comment( $comment->comment_ID );
637 function akismet_spamtoham( $comment ) { akismet_submit_nonspam_comment( $comment->comment_ID ); }
639 if ( function_exists( 'wp_transition_comment_status' ) ) {
640 add_action( 'transition_comment_status', 'akismet_transition_comment_status', 10, 3 );
642 add_action('wp_set_comment_status', 'akismet_set_comment_status', 10, 2);
643 add_action('edit_comment', 'akismet_submit_spam_comment');
644 add_filter( 'comment_spam_to_approved', 'akismet_spamtoham' );
645 add_filter( 'comment_spam_to_unapproved', 'akismet_spamtoham' );
647 // Total spam in queue
648 // get_option( 'akismet_spam_count' ) is the total caught ever
649 function akismet_spam_count( $type = false ) {
652 if ( !$type ) { // total
653 $count = wp_cache_get( 'akismet_spam_count', 'widget' );
654 if ( false === $count ) {
655 if ( function_exists('wp_count_comments') ) {
656 $count = wp_count_comments();
657 $count = $count->spam;
659 $count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'");
661 wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
664 } elseif ( 'comments' == $type || 'comment' == $type ) { // comments
666 } else { // pingback, trackback, ...
667 $type = $wpdb->escape( $type );
670 return (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type'");
675 function akismet_rightnow() {
676 global $submenu, $wp_db_version;
678 // clean_url was deprecated in WP 3.0
679 $esc_url = 'clean_url';
680 if ( function_exists( 'esc_url' ) )
681 $esc_url = 'esc_url';
683 if ( 8645 < $wp_db_version ) // 2.7
684 $link = 'edit-comments.php?comment_status=spam';
685 elseif ( isset( $submenu['edit-comments.php'] ) )
686 $link = 'edit-comments.php?page=akismet-admin';
688 $link = 'edit.php?page=akismet-admin';
690 if ( $count = get_option('akismet_spam_count') ) {
691 $intro = sprintf( __ngettext(
692 '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comment already,',
693 '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comments already,',
695 ), 'http://akismet.com/', number_format_i18n( $count ) );
697 $intro = sprintf( __('<a href="%1$s">Akismet</a> blocks spam from getting to your blog,'), 'http://akismet.com/' );
700 if ( $queue_count = akismet_spam_count() ) {
701 $queue_text = sprintf( __ngettext(
702 'and there\'s <a href="%2$s">%1$s comment</a> in your spam queue right now.',
703 'and there are <a href="%2$s">%1$s comments</a> in your spam queue right now.',
705 ), number_format_i18n( $queue_count ), clean_url($link) );
707 $queue_text = sprintf( __( "but there's nothing in your <a href='%1\$s'>spam queue</a> at the moment." ), $esc_url($link) );
710 // _c was deprecated in WP 2.9.0
711 if ( function_exists( '_x' ) )
712 $text = sprintf( _x( '%1$s %2$s', 'akismet_rightnow' ), $intro, $queue_text );
714 $text = sprintf( _c( '%1$s %2$s|akismet_rightnow' ), $intro, $queue_text );
716 echo "<p class='akismet-right-now'>$text</p>\n";
719 add_action('rightnow_end', 'akismet_rightnow');
723 function akismet_check_for_spam_button($comment_status) {
724 if ( 'approved' == $comment_status )
726 if ( function_exists('plugins_url') )
727 $link = 'admin.php?action=akismet_recheck_queue';
729 $link = 'edit-comments.php?page=akismet-admin&recheckqueue=true&noheader=true';
730 echo "</div><div class='alignleft'><a class='button-secondary checkforspam' href='$link'>" . __('Check for Spam') . "</a>";
732 add_action('manage_comments_nav', 'akismet_check_for_spam_button');
734 function akismet_recheck_queue() {
735 global $wpdb, $akismet_api_host, $akismet_api_port;
737 if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
740 $moderation = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = '0'", ARRAY_A );
741 foreach ( (array) $moderation as $c ) {
742 $c['user_ip'] = $c['comment_author_IP'];
743 $c['user_agent'] = $c['comment_agent'];
745 $c['blog'] = get_option('home');
746 $c['blog_lang'] = get_locale();
747 $c['blog_charset'] = get_option('blog_charset');
748 $c['permalink'] = get_permalink($c['comment_post_ID']);
750 $c['user_role'] = '';
751 if ( isset( $c['user_ID'] ) )
752 $c['user_role'] = akismet_get_user_roles($c['user_ID']);
754 $id = (int) $c['comment_ID'];
757 foreach ( $c as $key => $data )
758 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
760 $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
761 if ( 'true' == $response[1] ) {
762 if ( function_exists('wp_set_comment_status') )
763 wp_set_comment_status($id, 'spam');
765 $wpdb->query("UPDATE $wpdb->comments SET comment_approved = 'spam' WHERE comment_ID = $id");
769 wp_redirect( $_SERVER['HTTP_REFERER'] );
773 add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
775 function akismet_check_db_comment( $id ) {
776 global $wpdb, $akismet_api_host, $akismet_api_port;
779 $c = $wpdb->get_row( "SELECT * FROM $wpdb->comments WHERE comment_ID = '$id'", ARRAY_A );
783 $c['user_ip'] = $c['comment_author_IP'];
784 $c['user_agent'] = $c['comment_agent'];
786 $c['blog'] = get_option('home');
787 $c['blog_lang'] = get_locale();
788 $c['blog_charset'] = get_option('blog_charset');
789 $c['permalink'] = get_permalink($c['comment_post_ID']);
790 $id = $c['comment_ID'];
793 foreach ( $c as $key => $data )
794 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
796 $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
801 function widget_akismet_register() {
802 if ( function_exists('register_sidebar_widget') ) :
803 function widget_akismet($args) {
805 $options = get_option('widget_akismet');
806 $count = number_format_i18n(get_option('akismet_spam_count'));
808 <?php echo $before_widget; ?>
809 <?php echo $before_title . $options['title'] . $after_title; ?>
810 <div id="akismetwrap"><div id="akismetstats"><a id="aka" href="http://akismet.com" title=""><?php printf( __( '%1$s %2$sspam comments%3$s %4$sblocked by%5$s<br />%6$sAkismet%7$s' ), '<span id="akismet1"><span id="akismetcount">' . $count . '</span>', '<span id="akismetsc">', '</span></span>', '<span id="akismet2"><span id="akismetbb">', '</span>', '<span id="akismeta">', '</span></span>' ); ?></a></div></div>
811 <?php echo $after_widget; ?>
815 function widget_akismet_style() {
816 $plugin_dir = '/wp-content/plugins';
817 if ( defined( 'PLUGINDIR' ) )
818 $plugin_dir = '/' . PLUGINDIR;
821 <style type="text/css">
822 #aka,#aka:link,#aka:hover,#aka:visited,#aka:active{color:#fff;text-decoration:none}
823 #aka:hover{border:none;text-decoration:none}
824 #aka:hover #akismet1{display:none}
825 #aka:hover #akismet2,#akismet1{display:block}
826 #akismet2{display:none;padding-top:2px}
827 #akismeta{font-size:16px;font-weight:bold;line-height:18px;text-decoration:none}
828 #akismetcount{display:block;font:15px Verdana,Arial,Sans-Serif;font-weight:bold;text-decoration:none}
829 #akismetwrap #akismetstats{background:url(<?php echo get_option('siteurl'), $plugin_dir; ?>/akismet/akismet.gif) no-repeat top left;border:none;color:#fff;font:11px 'Trebuchet MS','Myriad Pro',sans-serif;height:40px;line-height:100%;overflow:hidden;padding:8px 0 0;text-align:center;width:120px}
834 function widget_akismet_control() {
835 $options = $newoptions = get_option('widget_akismet');
836 if ( isset( $_POST['akismet-submit'] ) && $_POST["akismet-submit"] ) {
837 $newoptions['title'] = strip_tags(stripslashes($_POST["akismet-title"]));
838 if ( empty($newoptions['title']) ) $newoptions['title'] = __('Spam Blocked');
840 if ( $options != $newoptions ) {
841 $options = $newoptions;
842 update_option('widget_akismet', $options);
844 $title = htmlspecialchars($options['title'], ENT_QUOTES);
846 <p><label for="akismet-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="akismet-title" name="akismet-title" type="text" value="<?php echo $title; ?>" /></label></p>
847 <input type="hidden" id="akismet-submit" name="akismet-submit" value="1" />
851 if ( function_exists( 'wp_register_sidebar_widget' ) ) {
852 wp_register_sidebar_widget( 'akismet', 'Akismet', 'widget_akismet', null, 'akismet');
853 wp_register_widget_control( 'akismet', 'Akismet', 'widget_akismet_control', null, 75, 'akismet');
855 register_sidebar_widget('Akismet', 'widget_akismet', null, 'akismet');
856 register_widget_control('Akismet', 'widget_akismet_control', null, 75, 'akismet');
858 if ( is_active_widget('widget_akismet') )
859 add_action('wp_head', 'widget_akismet_style');
863 add_action('init', 'widget_akismet_register');
865 // Counter for non-widget users
866 function akismet_counter() {
867 $plugin_dir = '/wp-content/plugins';
868 if ( defined( 'PLUGINDIR' ) )
869 $plugin_dir = '/' . PLUGINDIR;
872 <style type="text/css">
873 #akismetwrap #aka,#aka:link,#aka:hover,#aka:visited,#aka:active{color:#fff;text-decoration:none}
874 #aka:hover{border:none;text-decoration:none}
875 #aka:hover #akismet1{display:none}
876 #aka:hover #akismet2,#akismet1{display:block}
877 #akismet2{display:none;padding-top:2px}
878 #akismeta{font-size:16px;font-weight:bold;line-height:18px;text-decoration:none}
879 #akismetcount{display:block;font:15px Verdana,Arial,Sans-Serif;font-weight:bold;text-decoration:none}
880 #akismetwrap #akismetstats{background:url(<?php echo get_option('siteurl'), $plugin_dir; ?>/akismet/akismet.gif) no-repeat top left;border:none;color:#fff;font:11px 'Trebuchet MS','Myriad Pro',sans-serif;height:40px;line-height:100%;overflow:hidden;padding:8px 0 0;text-align:center;width:120px}
883 $count = number_format_i18n(get_option('akismet_spam_count'));
885 <div id="akismetwrap"><div id="akismetstats"><a id="aka" href="http://akismet.com" title=""><div id="akismet1"><span id="akismetcount"><?php echo $count; ?></span> <span id="akismetsc"><?php _e('spam comments') ?></span></div> <div id="akismet2"><span id="akismetbb"><?php _e('blocked by') ?></span><br /><span id="akismeta">Akismet</span></div></a></div></div>