Upgrade WordPress's Akismet plug-in to the latest version.
[WebKit-https.git] / Websites / webkit.org / blog / wp-content / plugins / akismet / admin.php
1 <?php
2 add_action( 'admin_menu', 'akismet_config_page' );
3 add_action( 'admin_menu', 'akismet_stats_page' );
4 akismet_admin_warnings();
5
6 function akismet_admin_init() {
7     global $wp_version;
8     
9     // all admin functions are disabled in old versions
10     if ( !function_exists('is_multisite') && version_compare( $wp_version, '3.0', '<' ) ) {
11         
12         function akismet_version_warning() {
13             echo "
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>
15             ";
16         }
17         add_action('admin_notices', 'akismet_version_warning'); 
18         
19         return; 
20     }
21
22     if ( function_exists( 'get_plugin_page_hook' ) )
23         $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
24     else
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');
32 }
33 add_action('admin_init', 'akismet_admin_init');
34
35 function akismet_nonce_field($action = -1) { return wp_nonce_field($action); }
36 $akismet_nonce = 'akismet-update-key';
37
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');
41 }
42
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>';
46         }
47
48         return $links;
49 }
50
51 add_filter( 'plugin_action_links', 'akismet_plugin_action_links', 10, 2 );
52
53 function akismet_conf() {
54         global $akismet_nonce, $wpcom_api_key;
55
56         if ( isset($_POST['submit']) ) {
57                 if ( function_exists('current_user_can') && !current_user_can('manage_options') )
58                         die(__('Cheatin&#8217; uh?'));
59
60                 check_admin_referer( $akismet_nonce );
61                 $key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
62                 $home_url = parse_url( get_bloginfo('url') );
63
64                 if ( empty($key) ) {
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';
71                 } else {
72                         $key_status = akismet_verify_key( $key );
73                 }
74
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';
82                 }
83
84                 if ( isset( $_POST['akismet_discard_month'] ) )
85                         update_option( 'akismet_discard_month', 'true' );
86                 else
87                         update_option( 'akismet_discard_month', 'false' );
88
89                 if ( isset( $_POST['akismet_show_user_comments_approved'] ) )
90                         update_option( 'akismet_show_user_comments_approved', 'true' );
91                 else
92                         update_option( 'akismet_show_user_comments_approved', 'false' );
93
94         } elseif ( isset($_POST['check']) ) {
95                 akismet_get_server_connectivity(0);
96         }
97
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';
104                                 else
105                                         $ms[] = 'key_empty';
106                         }
107                         $key_status = 'empty';
108                 } else {
109                         $key_status = akismet_verify_key( $key );
110                 }
111                 if ( $key_status == 'valid' ) {
112                         $ms[] = 'key_valid';
113                 } else if ( $key_status == 'invalid' ) {
114                         delete_option('wordpress_api_key');
115                         $ms[] = 'key_empty';
116                 } else if ( !empty($key) && $key_status == 'failed' ) {
117                         $ms[] = 'key_failed';
118                 }
119         }
120
121         $messages = array(
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') ) ),
131         );
132 ?>
133 <?php if ( !empty($_POST['submit'] ) ) : ?>
134 <div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
135 <?php endif; ?>
136 <div class="wrap">
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>
140 <?php } ?>
141 <div class="narrow">
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>
145
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>
149 <?php endforeach; ?>
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>
154 <?php } ?>
155 <?php } ?>
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 &raquo;'); ?>" /></p>
160 </form>
161
162 <form action="" method="post" id="akismet-connectivity" style="margin: auto; width: 400px; ">
163
164 <h3><?php _e('Server Connectivity'); ?></h3>
165 <?php
166         if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) {
167                 ?>
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>
170                 <?php
171         } else {
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>
179                         <?php
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>
184                         <?php
185                         // all connections work
186                         } else { ?>
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>
189                         <?php
190                         }
191                 } else {
192                         ?>
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>
195                         <?php
196                 }
197         }
198         
199         if ( !empty($servers) ) {
200 ?>
201 <table style="width: 100%;">
202 <thead><th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th></thead>
203 <tbody>
204 <?php
205                 asort($servers);
206                 foreach ( $servers as $ip => $status ) {
207                         $color = ( $status ? '#4AB915' : '#888');
208         ?>
209                 <tr>
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>
212                 
213         <?php
214                 }
215         }
216 ?>
217 </tbody>
218 </table>
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 &raquo;'); ?>" /></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>
222 </form>
223
224 </div>
225 </div>
226 <?php
227 }
228
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');
232
233 }
234
235 function akismet_stats_script() {
236         ?>
237 <script type="text/javascript">
238 function resizeIframe() {
239   
240     document.getElementById('akismet-stats-frame').style.height = "2500px";
241     
242 };
243 function resizeIframeInit() {
244         document.getElementById('akismet-stats-frame').onload = resizeIframe;
245         window.onresize = resizeIframe;
246 }
247 addLoadEvent(resizeIframeInit);
248 </script><?php
249 }
250
251
252 function akismet_stats_display() {
253         global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
254         $blog = urlencode( get_bloginfo('url') );
255
256         $url = 'http://';
257         if ( is_ssl() )
258                 $url = 'https://';
259
260         $url .= 'akismet.com/web/1.0/user-stats.php';
261         $url .= "?blog={$blog}&api_key=" . akismet_get_key();
262         ?>
263         <div class="wrap">
264         <iframe src="<?php echo $url; ?>" width="100%" height="100%" frameborder="0" id="akismet-stats-frame"></iframe>
265         </div>
266         <?php
267 }
268
269 function akismet_stats() {
270         if ( !function_exists('did_action') || did_action( 'rightnow_end' ) ) // We already displayed this info in the "Right Now" section
271                 return;
272         if ( !$count = get_option('akismet_spam_count') )
273                 return;
274         $path = plugin_basename(__FILE__);
275         echo '<h3>' . _x( 'Spam', 'comments' ) . '</h3>';
276         global $submenu;
277         if ( isset( $submenu['edit-comments.php'] ) )
278                 $link = 'edit-comments.php';
279         else
280                 $link = 'edit.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>';
282 }
283 add_action('activity_box_end', 'akismet_stats');
284
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() {
289                         echo "
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>
291                         ";
292                 }
293                 add_action('admin_notices', 'akismet_warning');
294                 return;
295         } elseif ( ( empty($_SERVER['SCRIPT_FILENAME']) || basename($_SERVER['SCRIPT_FILENAME']) == 'edit-comments.php' ) &&  wp_next_scheduled('akismet_schedule_cron_recheck') ) {
296                 function akismet_warning() {
297                         global $wpdb;
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') );
300                                 if ( $waiting > 0 )
301                                         echo "
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>
303                         ";
304                 }
305                 add_action('admin_notices', 'akismet_warning');
306                 return;
307         }
308 }
309
310 // FIXME placeholder
311
312 function akismet_comment_row_action( $a, $comment ) {
313
314         // failsafe for old WP versions
315         if ( !function_exists('add_comment_meta') )
316                 return $a;
317
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 );
321         $desc = null;
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' );
328         } else {
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 );
332                 else
333                         $desc = sprintf( __('Un-spammed by %s'), $who );
334         }
335
336         // add a History item to the hover links, just after Edit
337         if ( $akismet_result ) {
338                 $b = array();
339                 foreach ( $a as $k => $item ) {
340                         $b[ $k ] = $item;
341                         if ( $k == 'edit' )
342                                 $b['history'] = '<a href="comment.php?action=editcomment&amp;c='.$comment->comment_ID.'#akismet-status" title="'. esc_attr__( 'View comment history' ) . '"> '. __('History') . '</a>';
343                 }
344                 
345                 $a = $b;
346         }
347                 
348         if ( $desc )
349                 echo '<span class="akismet-status" commentid="'.$comment->comment_ID.'"><a href="comment.php?action=editcomment&amp;c='.$comment->comment_ID.'#akismet-status" title="' . esc_attr__( 'View comment history' ) . '">'.htmlspecialchars($desc).'</a></span>';
350                 
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>';
355         }
356         
357         return $a;
358 }
359
360 add_filter( 'comment_row_actions', 'akismet_comment_row_action', 10, 2 );
361
362 function akismet_comment_status_meta_box($comment) {
363         $history = akismet_get_comment_history( $comment->comment_ID );
364
365         if ( $history ) {
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>';
371                 }
372                 
373                 echo '</div>';
374
375         }
376 }
377
378
379 // add an extra column header to the comments screen
380 function akismet_comments_columns( $columns ) {
381         $columns[ 'akismet' ] = __( 'Akismet' );
382         return $columns;
383 }
384
385 #add_filter( 'manage_edit-comments_columns', 'akismet_comments_columns' );
386
387 // Show stuff in the extra column
388 function akismet_comment_column_row( $column, $comment_id ) {
389         if ( $column != 'akismet' )
390                 return;
391                 
392         $history = akismet_get_comment_history( $comment_id );
393         
394         if ( $history ) {
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>';
399                 }
400                 
401                 echo '</dl>';
402         }
403 }
404
405 #add_action( 'manage_comments_custom_column', 'akismet_comment_column_row', 10, 2 );
406
407 // END FIXME
408
409 // call out URLS in comments
410 function akismet_text_add_link_callback( $m ) {
411         
412                 // bare link?
413         if ( $m[4] == $m[2] )
414                 return '<a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a>';
415         else
416                 return '<span title="'.$m[2].'" class="comment-link"><a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a></span>';
417 }
418
419 function akismet_text_add_link_class( $comment_text ) {
420
421         return preg_replace_callback( '#<a ([^>]*)href="([^"]+)"([^>]*)>(.*?)</a>#i', 'akismet_text_add_link_callback', $comment_text );
422 }
423
424 add_filter('comment_text', 'akismet_text_add_link_class');
425
426
427 // WP 2.5+
428 function akismet_rightnow() {
429         global $submenu, $wp_db_version;
430
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';
435
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';
440         else
441                 $link = 'edit.php?page=akismet-admin';
442
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. ',
447                         $count
448                 ), 'http://akismet.com/', number_format_i18n( $count ) );
449         } else {
450                 $intro = sprintf( __('<a href="%1$s">Akismet</a> blocks spam from getting to your blog. '), 'http://akismet.com/' );
451         }
452
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.',
457                         $queue_count
458                 ), number_format_i18n( $queue_count ), $esc_url($link) );
459         } else {
460                 $queue_text = sprintf( __( "There's nothing in your <a href='%1\$s'>spam queue</a> at the moment." ), $esc_url($link) );
461         }
462
463         $text = $intro . '<br />' . $queue_text;
464         echo "<p class='akismet-right-now'>$text</p>\n";
465 }
466         
467 add_action('rightnow_end', 'akismet_rightnow');
468
469
470 // For WP >= 2.5
471 function akismet_check_for_spam_button($comment_status) {
472         if ( 'approved' == $comment_status )
473                 return;
474         if ( function_exists('plugins_url') )
475                 $link = 'admin.php?action=akismet_recheck_queue';
476         else
477                 $link = 'edit-comments.php?page=akismet-admin&amp;recheckqueue=true&amp;noheader=true';
478         echo "</div><div class='alignleft'><a class='button-secondary checkforspam' href='$link'>" . __('Check for Spam') . "</a>";
479 }
480 add_action('manage_comments_nav', 'akismet_check_for_spam_button');
481
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;
485
486         $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
487         if ( !$comment ) // it was deleted
488                 return;
489                 
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 );
494         }
495         
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;
503         }
504         if ( is_object($current_site) ) {
505                 $comment->site_domain = $current_site->domain;
506         }
507
508         $comment->user_role = '';
509         if ( isset( $comment->user_ID ) )
510                 $comment->user_role = akismet_get_user_roles($comment->user_ID);
511
512         if ( akismet_test_mode() )
513                 $comment->is_test = 'true';
514
515         $query_string = '';
516         foreach ( $comment as $key => $data )
517                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
518
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 );
524         }
525         
526         do_action('akismet_submit_nonspam_comment', $comment_id, $response[1]);
527 }
528
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;
532
533         $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
534         if ( !$comment ) // it was deleted
535                 return;
536         if ( 'spam' != $comment->comment_approved )
537                 return;
538         
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 );
543         }
544         
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;
552         }
553         if ( is_object($current_site) ) {
554                 $comment->site_domain = $current_site->domain;
555         }
556
557         $comment->user_role = '';
558         if ( isset( $comment->user_ID ) )
559                 $comment->user_role = akismet_get_user_roles($comment->user_ID);
560
561         if ( akismet_test_mode() )
562                 $comment->is_test = 'true';
563
564         $query_string = '';
565         foreach ( $comment as $key => $data )
566                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
567
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 );
573         }
574         do_action('akismet_submit_spam_comment', $comment_id, $response[1]);
575 }
576
577 // For WP 2.7+
578 function akismet_transition_comment_status( $new_status, $old_status, $comment ) {
579         if ( $new_status == $old_status )
580                 return;
581
582         # we don't need to record a history item for deleted comments
583         if ( $new_status == 'delete' )
584                 return;
585                 
586         if ( !is_admin() )
587                 return;
588                 
589         if ( !current_user_can( 'edit_post', $comment->comment_post_ID ) && !current_user_can( 'moderate_comments' ) )
590                 return;
591
592         if ( defined('WP_IMPORTING') && WP_IMPORTING == true )
593                 return;
594                 
595         global $current_user;
596         $reporter = '';
597         if ( is_object( $current_user ) )
598                 $reporter = $current_user->user_login;
599         
600         // Assumption alert:
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 );
611                 }
612         }
613         
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 );
616 }
617
618 add_action( 'transition_comment_status', 'akismet_transition_comment_status', 10, 3 );
619
620 // Total spam in queue
621 // get_option( 'akismet_spam_count' ) is the total caught ever
622 function akismet_spam_count( $type = false ) {
623         global $wpdb;
624
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;
631                         } else {
632                                 $count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'");
633                         }
634                         wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
635                 }
636                 return $count;
637         } elseif ( 'comments' == $type || 'comment' == $type ) { // comments
638                 $type = '';
639         } else { // pingback, trackback, ...
640                 $type  = $wpdb->escape( $type );
641         }
642
643         return (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type'");
644 }
645
646
647 function akismet_recheck_queue() {
648         global $wpdb, $akismet_api_host, $akismet_api_port;
649
650         if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
651                 return;
652                 
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'];
657                 $c['referrer']   = '';
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']);
662
663                 $c['user_role'] = '';
664                 if ( isset( $c['user_ID'] ) )
665                         $c['user_role']  = akismet_get_user_roles($c['user_ID']);
666
667                 if ( akismet_test_mode() )
668                         $c['is_test'] = 'true';
669
670                 $id = (int) $c['comment_ID'];
671
672                 $query_string = '';
673                 foreach ( $c as $key => $data )
674                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
675
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' );
681                 
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
686                 } else {
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' );
689                 }
690
691         }
692         wp_redirect( $_SERVER['HTTP_REFERER'] );
693         exit;
694 }
695
696 add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
697
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;
702         
703         $test_host = 'rest.akismet.com';
704         
705         // Some web hosts may disable one or both functions
706         if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') )
707                 return array();
708         
709         $ips = gethostbynamel($test_host);
710         if ( !$ips || !is_array($ips) || !count($ips) )
711                 return array();
712                 
713         $servers = array();
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;
719                 else
720                         $servers[$ip] = false;
721         }
722
723         return $servers;
724 }
725
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 )
732                 return $servers;
733         
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());
738         return $servers;
739 }
740
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 )
746                 return true;
747         $servers = akismet_get_server_connectivity();
748         return !( empty($servers) || !count($servers) || count( array_filter($servers) ) < count($servers) );
749 }
750