2 add_action( 'admin_menu', 'akismet_config_page' );
3 add_action( 'admin_menu', 'akismet_stats_page' );
4 akismet_admin_warnings();
6 function akismet_admin_init() {
9 // all admin functions are disabled in old versions
10 if ( !function_exists('is_multisite') && version_compare( $wp_version, '3.0', '<' ) ) {
12 function akismet_version_warning() {
14 <div id='akismet-warning' class='updated fade'><p><strong>".sprintf(__('Akismet %s requires WordPress 3.0 or higher.'), AKISMET_VERSION) ."</strong> ".sprintf(__('Please <a href="%s">upgrade WordPress</a> to a current version, or <a href="%s">downgrade to version 2.4 of the Akismet plugin</a>.'), 'http://codex.wordpress.org/Upgrading_WordPress', 'http://wordpress.org/extend/plugins/akismet/download/'). "</p></div>
17 add_action('admin_notices', 'akismet_version_warning');
22 if ( function_exists( 'get_plugin_page_hook' ) )
23 $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
25 $hook = 'dashboard_page_akismet-stats-display';
26 add_action('admin_head-'.$hook, 'akismet_stats_script');
27 add_meta_box('akismet-status', __('Comment History'), 'akismet_comment_status_meta_box', 'comment', 'normal');
28 wp_register_style('akismet.css', AKISMET_PLUGIN_URL . 'akismet.css');
29 wp_enqueue_style('akismet.css');
30 wp_register_script('akismet.js', AKISMET_PLUGIN_URL . 'akismet.js', array('jquery'));
31 wp_enqueue_script('akismet.js');
33 add_action('admin_init', 'akismet_admin_init');
35 function akismet_nonce_field($action = -1) { return wp_nonce_field($action); }
36 $akismet_nonce = 'akismet-update-key';
38 function akismet_config_page() {
39 if ( function_exists('add_submenu_page') )
40 add_submenu_page('plugins.php', __('Akismet Configuration'), __('Akismet Configuration'), 'manage_options', 'akismet-key-config', 'akismet_conf');
43 function akismet_plugin_action_links( $links, $file ) {
44 if ( $file == plugin_basename( dirname(__FILE__).'/akismet.php' ) ) {
45 $links[] = '<a href="plugins.php?page=akismet-key-config">'.__('Settings').'</a>';
51 add_filter( 'plugin_action_links', 'akismet_plugin_action_links', 10, 2 );
53 function akismet_conf() {
54 global $akismet_nonce, $wpcom_api_key;
56 if ( isset($_POST['submit']) ) {
57 if ( function_exists('current_user_can') && !current_user_can('manage_options') )
58 die(__('Cheatin’ uh?'));
60 check_admin_referer( $akismet_nonce );
61 $key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
62 $home_url = parse_url( get_bloginfo('url') );
65 $key_status = 'empty';
66 $ms[] = 'new_key_empty';
67 delete_option('wordpress_api_key');
68 } elseif ( empty($home_url['host']) ) {
69 $key_status = 'empty';
70 $ms[] = 'bad_home_url';
72 $key_status = akismet_verify_key( $key );
75 if ( $key_status == 'valid' ) {
76 update_option('wordpress_api_key', $key);
77 $ms[] = 'new_key_valid';
78 } else if ( $key_status == 'invalid' ) {
79 $ms[] = 'new_key_invalid';
80 } else if ( $key_status == 'failed' ) {
81 $ms[] = 'new_key_failed';
84 if ( isset( $_POST['akismet_discard_month'] ) )
85 update_option( 'akismet_discard_month', 'true' );
87 update_option( 'akismet_discard_month', 'false' );
89 if ( isset( $_POST['akismet_show_user_comments_approved'] ) )
90 update_option( 'akismet_show_user_comments_approved', 'true' );
92 update_option( 'akismet_show_user_comments_approved', 'false' );
94 } elseif ( isset($_POST['check']) ) {
95 akismet_get_server_connectivity(0);
98 if ( empty( $key_status) || $key_status != 'valid' ) {
99 $key = get_option('wordpress_api_key');
100 if ( empty( $key ) ) {
101 if ( empty( $key_status ) || $key_status != 'failed' ) {
102 if ( akismet_verify_key( '1234567890ab' ) == 'failed' )
103 $ms[] = 'no_connection';
107 $key_status = 'empty';
109 $key_status = akismet_verify_key( $key );
111 if ( $key_status == 'valid' ) {
113 } else if ( $key_status == 'invalid' ) {
114 delete_option('wordpress_api_key');
116 } else if ( !empty($key) && $key_status == 'failed' ) {
117 $ms[] = 'key_failed';
122 'new_key_empty' => array('color' => 'aa0', 'text' => __('Your key has been cleared.')),
123 'new_key_valid' => array('color' => '4AB915', 'text' => __('Your key has been verified. Happy blogging!')),
124 'new_key_invalid' => array('color' => '888', 'text' => __('The key you entered is invalid. Please double-check it.')),
125 'new_key_failed' => array('color' => '888', 'text' => __('The key you entered could not be verified because a connection to akismet.com could not be established. Please check your server configuration.')),
126 'no_connection' => array('color' => '888', 'text' => __('There was a problem connecting to the Akismet server. Please check your server configuration.')),
127 '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/')),
128 'key_valid' => array('color' => '4AB915', 'text' => __('This key is valid.')),
129 '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.')),
130 'bad_home_url' => array('color' => '888', 'text' => sprintf( __('Your WordPress home URL %s is invalid. Please fix the <a href="%s">home option</a>.'), esc_html( get_bloginfo('url') ), admin_url('options.php#home') ) ),
133 <?php if ( !empty($_POST['submit'] ) ) : ?>
134 <div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
137 <h2><?php _e('Akismet Configuration'); ?></h2>
138 <?php if (isset($_GET['message']) && $_GET['message'] == 'success') { ?>
139 <div class="updated below-h2" id="message"><p><?php _e( '<strong>Sign up success!</strong> Please check your email for your Akismet API Key and enter it below.' ); ?></p></div>
142 <form action="" method="post" id="akismet-conf" style="margin: auto; width: 400px; ">
143 <?php if ( !$wpcom_api_key ) { ?>
144 <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>
146 <h3><label for="key"><?php _e('Akismet API Key'); ?></label></h3>
147 <?php foreach ( $ms as $m ) : ?>
148 <p style="padding: .5em; background-color: #<?php echo $messages[$m]['color']; ?>; color: #fff; font-weight: bold;"><?php echo $messages[$m]['text']; ?></p>
150 <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>
151 <?php if ( isset( $invalid_key) && $invalid_key ) { ?>
152 <h3><?php _e('Why might my key be invalid?'); ?></h3>
153 <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>
156 <?php akismet_nonce_field($akismet_nonce) ?>
157 <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('Auto-delete spam submitted on posts more than a month old.'); ?></label></p>
158 <p><label><input name="akismet_show_user_comments_approved" id="akismet_show_user_comments_approved" value="true" type="checkbox" <?php if ( get_option('akismet_show_user_comments_approved') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Show the number of comments you\'ve approved beside each comment author.'); ?></label></p>
159 <p class="submit"><input type="submit" name="submit" value="<?php _e('Update options »'); ?>" /></p>
162 <form action="" method="post" id="akismet-connectivity" style="margin: auto; width: 400px; ">
164 <h3><?php _e('Server Connectivity'); ?></h3>
166 if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) {
168 <p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Network functions are disabled.'); ?></p>
169 <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>
172 $servers = akismet_get_server_connectivity();
173 $fail_count = count($servers) - count( array_filter($servers) );
174 if ( is_array($servers) && count($servers) > 0 ) {
175 // some connections work, some fail
176 if ( $fail_count > 0 && $fail_count < count($servers) ) { ?>
177 <p style="padding: .5em; background-color: #aa0; color: #fff; font-weight:bold;"><?php _e('Unable to reach some Akismet servers.'); ?></p>
178 <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>
180 // all connections fail
181 } elseif ( $fail_count > 0 ) { ?>
182 <p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Unable to reach any Akismet servers.'); ?></p>
183 <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>
185 // all connections work
187 <p style="padding: .5em; background-color: #4AB915; color: #fff; font-weight:bold;"><?php _e('All Akismet servers are available.'); ?></p>
188 <p><?php _e('Akismet is working correctly. All servers are accessible.'); ?></p>
193 <p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Unable to find Akismet servers.'); ?></p>
194 <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>
199 if ( !empty($servers) ) {
201 <table style="width: 100%;">
202 <thead><th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th></thead>
206 foreach ( $servers as $ip => $status ) {
207 $color = ( $status ? '#4AB915' : '#888');
210 <td><?php echo htmlspecialchars($ip); ?></td>
211 <td style="padding: 0 .5em; font-weight:bold; color: #fff; background-color: <?php echo $color; ?>"><?php echo ($status ? __('Accessible') : __('Re-trying') ); ?></td>
219 <p><?php if ( get_option('akismet_connectivity_time') ) echo sprintf( __('Last checked %s ago.'), human_time_diff( get_option('akismet_connectivity_time') ) ); ?></p>
220 <p class="submit"><input type="submit" name="check" value="<?php _e('Check network status »'); ?>" /></p>
221 <p><?php printf( __('<a href="%s" target="_blank">Click here</a> to confirm that <a href="%s" target="_blank">Akismet.com is up</a>.'), 'http://status.automattic.com/9931/136079/Akismet-API', 'http://status.automattic.com/9931/136079/Akismet-API' ); ?></p>
229 function akismet_stats_page() {
230 if ( function_exists('add_submenu_page') )
231 add_submenu_page('index.php', __('Akismet Stats'), __('Akismet Stats'), 'manage_options', 'akismet-stats-display', 'akismet_stats_display');
235 function akismet_stats_script() {
237 <script type="text/javascript">
238 function resizeIframe() {
240 document.getElementById('akismet-stats-frame').style.height = "2500px";
243 function resizeIframeInit() {
244 document.getElementById('akismet-stats-frame').onload = resizeIframe;
245 window.onresize = resizeIframe;
247 addLoadEvent(resizeIframeInit);
252 function akismet_stats_display() {
253 global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
254 $blog = urlencode( get_bloginfo('url') );
260 $url .= 'akismet.com/web/1.0/user-stats.php';
261 $url .= "?blog={$blog}&api_key=" . akismet_get_key();
264 <iframe src="<?php echo $url; ?>" width="100%" height="100%" frameborder="0" id="akismet-stats-frame"></iframe>
269 function akismet_stats() {
270 if ( !function_exists('did_action') || did_action( 'rightnow_end' ) ) // We already displayed this info in the "Right Now" section
272 if ( !$count = get_option('akismet_spam_count') )
274 $path = plugin_basename(__FILE__);
275 echo '<h3>' . _x( 'Spam', 'comments' ) . '</h3>';
277 if ( isset( $submenu['edit-comments.php'] ) )
278 $link = 'edit-comments.php';
281 echo '<p>'.sprintf( _n( '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', $count ), 'http://akismet.com/', clean_url("$link?page=akismet-admin"), number_format_i18n($count) ).'</p>';
283 add_action('activity_box_end', 'akismet_stats');
285 function akismet_admin_warnings() {
286 global $wpcom_api_key;
287 if ( !get_option('wordpress_api_key') && !$wpcom_api_key && !isset($_POST['submit']) ) {
288 function akismet_warning() {
290 <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>
293 add_action('admin_notices', 'akismet_warning');
295 } elseif ( ( empty($_SERVER['SCRIPT_FILENAME']) || basename($_SERVER['SCRIPT_FILENAME']) == 'edit-comments.php' ) && wp_next_scheduled('akismet_schedule_cron_recheck') ) {
296 function akismet_warning() {
298 $waiting = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->commentmeta WHERE meta_key = 'akismet_error'" ) );
299 $next_check = human_time_diff( wp_next_scheduled('akismet_schedule_cron_recheck') );
302 <div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet has detected a problem.')."</strong> ".sprintf(_n('A server or network problem prevented Akismet from checking %d comment. It has been temporarily held for moderation and will be automatically re-checked in %s.', 'A server or network problem prevented Akismet from checking %d comments. They have been temporarily held for moderation and will be automatically re-checked in %s.', $waiting), number_format_i18n( $waiting ), $next_check)."</p></div>
305 add_action('admin_notices', 'akismet_warning');
312 function akismet_comment_row_action( $a, $comment ) {
314 // failsafe for old WP versions
315 if ( !function_exists('add_comment_meta') )
318 $akismet_result = get_comment_meta( $comment->comment_ID, 'akismet_result', true );
319 $user_result = get_comment_meta( $comment->comment_ID, 'akismet_user_result', true);
320 $comment_status = wp_get_comment_status( $comment->comment_ID );
322 if ( !$user_result || $user_result == $akismet_result ) {
323 // Show the original Akismet result if the user hasn't overridden it, or if their decision was the same
324 if ( $akismet_result == 'true' && $comment_status != 'spam' && $comment_status != 'trash' )
325 $desc = __( 'Flagged as spam by Akismet' );
326 elseif ( $akismet_result == 'false' && $comment_status == 'spam' )
327 $desc = __( 'Cleared by Akismet' );
329 $who = get_comment_meta( $comment->comment_ID, 'akismet_user', true );
330 if ( $user_result == 'true' )
331 $desc = sprintf( __('Flagged as spam by %s'), $who );
333 $desc = sprintf( __('Un-spammed by %s'), $who );
336 // add a History item to the hover links, just after Edit
337 if ( $akismet_result ) {
339 foreach ( $a as $k => $item ) {
342 $b['history'] = '<a href="comment.php?action=editcomment&c='.$comment->comment_ID.'#akismet-status" title="'. esc_attr__( 'View comment history' ) . '"> '. __('History') . '</a>';
349 echo '<span class="akismet-status" commentid="'.$comment->comment_ID.'"><a href="comment.php?action=editcomment&c='.$comment->comment_ID.'#akismet-status" title="' . esc_attr__( 'View comment history' ) . '">'.htmlspecialchars($desc).'</a></span>';
351 if ( apply_filters( 'akismet_show_user_comments_approved', get_option('akismet_show_user_comments_approved') ) == 'true' ) {
352 $comment_count = akismet_get_user_comments_approved( $comment->user_id, $comment->comment_author_email, $comment->comment_author, $comment->comment_author_url );
353 $comment_count = intval( $comment_count );
354 echo '<span class="akismet-user-comment-count" commentid="'.$comment->comment_ID.'" style="display:none;"><br><span class="akismet-user-comment-counts">'.sprintf( _n( '%s approved', '%s approved', $comment_count ), number_format_i18n( $comment_count ) ) . '</span></span>';
360 add_filter( 'comment_row_actions', 'akismet_comment_row_action', 10, 2 );
362 function akismet_comment_status_meta_box($comment) {
363 $history = akismet_get_comment_history( $comment->comment_ID );
366 echo '<div class="akismet-history" style="margin: 13px;">';
367 foreach ( $history as $row ) {
368 $time = date( 'D d M Y @ h:i:m a', $row['time'] ) . ' GMT';
369 echo '<div style="margin-bottom: 13px;"><span style="color: #999;" alt="' . $time . '" title="' . $time . '">' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '</span> - ';
370 echo htmlspecialchars( $row['message'] ) . '</div>';
379 // add an extra column header to the comments screen
380 function akismet_comments_columns( $columns ) {
381 $columns[ 'akismet' ] = __( 'Akismet' );
385 #add_filter( 'manage_edit-comments_columns', 'akismet_comments_columns' );
387 // Show stuff in the extra column
388 function akismet_comment_column_row( $column, $comment_id ) {
389 if ( $column != 'akismet' )
392 $history = akismet_get_comment_history( $comment_id );
395 echo '<dl class="akismet-history">';
396 foreach ( $history as $row ) {
397 echo '<dt>' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '</dt>';
398 echo '<dd>' . htmlspecialchars( $row['message'] ) . '</dd>';
405 #add_action( 'manage_comments_custom_column', 'akismet_comment_column_row', 10, 2 );
409 // call out URLS in comments
410 function akismet_text_add_link_callback( $m ) {
413 if ( $m[4] == $m[2] )
414 return '<a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a>';
416 return '<span title="'.$m[2].'" class="comment-link"><a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a></span>';
419 function akismet_text_add_link_class( $comment_text ) {
421 return preg_replace_callback( '#<a ([^>]*)href="([^"]+)"([^>]*)>(.*?)</a>#i', 'akismet_text_add_link_callback', $comment_text );
424 add_filter('comment_text', 'akismet_text_add_link_class');
428 function akismet_rightnow() {
429 global $submenu, $wp_db_version;
431 // clean_url was deprecated in WP 3.0
432 $esc_url = 'clean_url';
433 if ( function_exists( 'esc_url' ) )
434 $esc_url = 'esc_url';
436 if ( 8645 < $wp_db_version ) // 2.7
437 $link = 'edit-comments.php?comment_status=spam';
438 elseif ( isset( $submenu['edit-comments.php'] ) )
439 $link = 'edit-comments.php?page=akismet-admin';
441 $link = 'edit.php?page=akismet-admin';
443 if ( $count = get_option('akismet_spam_count') ) {
444 $intro = sprintf( _n(
445 '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comment already. ',
446 '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comments already. ',
448 ), 'http://akismet.com/', number_format_i18n( $count ) );
450 $intro = sprintf( __('<a href="%1$s">Akismet</a> blocks spam from getting to your blog. '), 'http://akismet.com/' );
453 if ( $queue_count = akismet_spam_count() ) {
454 $queue_text = sprintf( _n(
455 'There\'s <a href="%2$s">%1$s comment</a> in your spam queue right now.',
456 'There are <a href="%2$s">%1$s comments</a> in your spam queue right now.',
458 ), number_format_i18n( $queue_count ), $esc_url($link) );
460 $queue_text = sprintf( __( "There's nothing in your <a href='%1\$s'>spam queue</a> at the moment." ), $esc_url($link) );
463 $text = $intro . '<br />' . $queue_text;
464 echo "<p class='akismet-right-now'>$text</p>\n";
467 add_action('rightnow_end', 'akismet_rightnow');
471 function akismet_check_for_spam_button($comment_status) {
472 if ( 'approved' == $comment_status )
474 if ( function_exists('plugins_url') )
475 $link = 'admin.php?action=akismet_recheck_queue';
477 $link = 'edit-comments.php?page=akismet-admin&recheckqueue=true&noheader=true';
478 echo "</div><div class='alignleft'><a class='button-secondary checkforspam' href='$link'>" . __('Check for Spam') . "</a>";
480 add_action('manage_comments_nav', 'akismet_check_for_spam_button');
482 function akismet_submit_nonspam_comment ( $comment_id ) {
483 global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
484 $comment_id = (int) $comment_id;
486 $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
487 if ( !$comment ) // it was deleted
490 // use the original version stored in comment_meta if available
491 $as_submitted = get_comment_meta( $comment_id, 'akismet_as_submitted', true);
492 if ( $as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content']) ) {
493 $comment = (object) array_merge( (array)$comment, $as_submitted );
496 $comment->blog = get_bloginfo('url');
497 $comment->blog_lang = get_locale();
498 $comment->blog_charset = get_option('blog_charset');
499 $comment->permalink = get_permalink($comment->comment_post_ID);
500 $comment->reporter_ip = $_SERVER['REMOTE_ADDR'];
501 if ( is_object($current_user) ) {
502 $comment->reporter = $current_user->user_login;
504 if ( is_object($current_site) ) {
505 $comment->site_domain = $current_site->domain;
508 $comment->user_role = '';
509 if ( isset( $comment->user_ID ) )
510 $comment->user_role = akismet_get_user_roles($comment->user_ID);
512 if ( akismet_test_mode() )
513 $comment->is_test = 'true';
516 foreach ( $comment as $key => $data )
517 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
519 $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-ham", $akismet_api_port);
520 if ( $comment->reporter ) {
521 akismet_update_comment_history( $comment_id, sprintf( __('%s reported this comment as not spam'), $comment->reporter ), 'report-ham' );
522 update_comment_meta( $comment_id, 'akismet_user_result', 'false' );
523 update_comment_meta( $comment_id, 'akismet_user', $comment->reporter );
526 do_action('akismet_submit_nonspam_comment', $comment_id, $response[1]);
529 function akismet_submit_spam_comment ( $comment_id ) {
530 global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
531 $comment_id = (int) $comment_id;
533 $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
534 if ( !$comment ) // it was deleted
536 if ( 'spam' != $comment->comment_approved )
539 // use the original version stored in comment_meta if available
540 $as_submitted = get_comment_meta( $comment_id, 'akismet_as_submitted', true);
541 if ( $as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content']) ) {
542 $comment = (object) array_merge( (array)$comment, $as_submitted );
545 $comment->blog = get_bloginfo('url');
546 $comment->blog_lang = get_locale();
547 $comment->blog_charset = get_option('blog_charset');
548 $comment->permalink = get_permalink($comment->comment_post_ID);
549 $comment->reporter_ip = $_SERVER['REMOTE_ADDR'];
550 if ( is_object($current_user) ) {
551 $comment->reporter = $current_user->user_login;
553 if ( is_object($current_site) ) {
554 $comment->site_domain = $current_site->domain;
557 $comment->user_role = '';
558 if ( isset( $comment->user_ID ) )
559 $comment->user_role = akismet_get_user_roles($comment->user_ID);
561 if ( akismet_test_mode() )
562 $comment->is_test = 'true';
565 foreach ( $comment as $key => $data )
566 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
568 $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-spam", $akismet_api_port);
569 if ( $comment->reporter ) {
570 akismet_update_comment_history( $comment_id, sprintf( __('%s reported this comment as spam'), $comment->reporter ), 'report-spam' );
571 update_comment_meta( $comment_id, 'akismet_user_result', 'true' );
572 update_comment_meta( $comment_id, 'akismet_user', $comment->reporter );
574 do_action('akismet_submit_spam_comment', $comment_id, $response[1]);
578 function akismet_transition_comment_status( $new_status, $old_status, $comment ) {
579 if ( $new_status == $old_status )
582 # we don't need to record a history item for deleted comments
583 if ( $new_status == 'delete' )
589 if ( !current_user_can( 'edit_post', $comment->comment_post_ID ) && !current_user_can( 'moderate_comments' ) )
592 if ( defined('WP_IMPORTING') && WP_IMPORTING == true )
595 global $current_user;
597 if ( is_object( $current_user ) )
598 $reporter = $current_user->user_login;
601 // We want to submit comments to Akismet only when a moderator explicitly spams or approves it - not if the status
602 // is changed automatically by another plugin. Unfortunately WordPress doesn't provide an unambiguous way to
603 // determine why the transition_comment_status action was triggered. And there are several different ways by which
604 // to spam and unspam comments: bulk actions, ajax, links in moderation emails, the dashboard, and perhaps others.
605 // We'll assume that this is an explicit user action if POST or GET has an 'action' key.
606 if ( isset($_POST['action']) || isset($_GET['action']) ) {
607 if ( $new_status == 'spam' && ( $old_status == 'approved' || $old_status == 'unapproved' || !$old_status ) ) {
608 return akismet_submit_spam_comment( $comment->comment_ID );
609 } elseif ( $old_status == 'spam' && ( $new_status == 'approved' || $new_status == 'unapproved' ) ) {
610 return akismet_submit_nonspam_comment( $comment->comment_ID );
614 if ( !get_comment_meta( $comment->comment_ID, 'akismet_rechecking' ) )
615 akismet_update_comment_history( $comment->comment_ID, sprintf( __('%s changed the comment status to %s'), $reporter, $new_status ), 'status-' . $new_status );
618 add_action( 'transition_comment_status', 'akismet_transition_comment_status', 10, 3 );
620 // Total spam in queue
621 // get_option( 'akismet_spam_count' ) is the total caught ever
622 function akismet_spam_count( $type = false ) {
625 if ( !$type ) { // total
626 $count = wp_cache_get( 'akismet_spam_count', 'widget' );
627 if ( false === $count ) {
628 if ( function_exists('wp_count_comments') ) {
629 $count = wp_count_comments();
630 $count = $count->spam;
632 $count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'");
634 wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
637 } elseif ( 'comments' == $type || 'comment' == $type ) { // comments
639 } else { // pingback, trackback, ...
640 $type = $wpdb->escape( $type );
643 return (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type'");
647 function akismet_recheck_queue() {
648 global $wpdb, $akismet_api_host, $akismet_api_port;
650 if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
653 $moderation = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = '0'", ARRAY_A );
654 foreach ( (array) $moderation as $c ) {
655 $c['user_ip'] = $c['comment_author_IP'];
656 $c['user_agent'] = $c['comment_agent'];
658 $c['blog'] = get_bloginfo('url');
659 $c['blog_lang'] = get_locale();
660 $c['blog_charset'] = get_option('blog_charset');
661 $c['permalink'] = get_permalink($c['comment_post_ID']);
663 $c['user_role'] = '';
664 if ( isset( $c['user_ID'] ) )
665 $c['user_role'] = akismet_get_user_roles($c['user_ID']);
667 if ( akismet_test_mode() )
668 $c['is_test'] = 'true';
670 $id = (int) $c['comment_ID'];
673 foreach ( $c as $key => $data )
674 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
676 $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
677 if ( 'true' == $response[1] ) {
678 wp_set_comment_status($c['comment_ID'], 'spam');
679 update_comment_meta( $c['comment_ID'], 'akismet_result', 'true' );
680 akismet_update_comment_history( $c['comment_ID'], __('Akismet re-checked and caught this comment as spam'), 'check-spam' );
682 } elseif ( 'false' == $response[1] ) {
683 update_comment_meta( $c['comment_ID'], 'akismet_result', 'false' );
684 akismet_update_comment_history( $c['comment_ID'], __('Akismet re-checked and cleared this comment'), 'check-ham' );
685 // abnormal result: error
687 update_comment_meta( $c['comment_ID'], 'akismet_result', 'error' );
688 akismet_update_comment_history( $c['comment_ID'], sprintf( __('Akismet was unable to re-check this comment (response: %s)'), $response[1]), 'check-error' );
692 wp_redirect( $_SERVER['HTTP_REFERER'] );
696 add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
698 // Check connectivity between the WordPress blog and Akismet's servers.
699 // 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).
700 function akismet_check_server_connectivity() {
701 global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
703 $test_host = 'rest.akismet.com';
705 // Some web hosts may disable one or both functions
706 if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') )
709 $ips = gethostbynamel($test_host);
710 if ( !$ips || !is_array($ips) || !count($ips) )
714 foreach ( $ips as $ip ) {
715 $response = akismet_verify_key( akismet_get_key(), $ip );
716 // even if the key is invalid, at least we know we have connectivity
717 if ( $response == 'valid' || $response == 'invalid' )
718 $servers[$ip] = true;
720 $servers[$ip] = false;
726 // Check the server connectivity and store the results in an option.
727 // Cached results will be used if not older than the specified timeout in seconds; use $cache_timeout = 0 to force an update.
728 // Returns the same associative array as akismet_check_server_connectivity()
729 function akismet_get_server_connectivity( $cache_timeout = 86400 ) {
730 $servers = get_option('akismet_available_servers');
731 if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false )
734 // There's a race condition here but the effect is harmless.
735 $servers = akismet_check_server_connectivity();
736 update_option('akismet_available_servers', $servers);
737 update_option('akismet_connectivity_time', time());
741 // Returns true if server connectivity was OK at the last check, false if there was a problem that needs to be fixed.
742 function akismet_server_connectivity_ok() {
743 // skip the check on WPMU because the status page is hidden
744 global $wpcom_api_key;
745 if ( $wpcom_api_key )
747 $servers = akismet_get_server_connectivity();
748 return !( empty($servers) || !count($servers) || count( array_filter($servers) ) < count($servers) );