]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-content/plugins/akismet/akismet.php
89c061f59bc75440d6cfcdd8dabed2c92956641c
[autoinstalls/wordpress.git] / wp-content / plugins / akismet / akismet.php
1 <?php
2 /*
3 Plugin Name: Akismet
4 Plugin URI: http://akismet.com/
5 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>&lt;?php akismet_counter(); ?&gt;</code> in your template. See also: <a href="http://wordpress.org/extend/plugins/stats/">WP Stats plugin</a>.
6 Version: 2.3.0
7 Author: Automattic
8 Author URI: http://automattic.com/wordpress-plugins/
9 */
10
11 define('AKISMET_VERSION', '2.3.0');
12
13 // If you hardcode a WP.com API key here, all key config screens will be hidden
14 if ( defined('WPCOM_API_KEY') )
15         $wpcom_api_key = constant('WPCOM_API_KEY');
16 else
17         $wpcom_api_key = '';
18
19 function akismet_init() {
20         global $wpcom_api_key, $akismet_api_host, $akismet_api_port;
21
22         if ( $wpcom_api_key )
23                 $akismet_api_host = $wpcom_api_key . '.rest.akismet.com';
24         else
25                 $akismet_api_host = get_option('wordpress_api_key') . '.rest.akismet.com';
26
27         $akismet_api_port = 80;
28         add_action('admin_menu', 'akismet_config_page');
29         add_action('admin_menu', 'akismet_stats_page');
30         akismet_admin_warnings();
31 }
32 add_action('init', 'akismet_init');
33
34 function akismet_admin_init() {
35         if ( function_exists( 'get_plugin_page_hook' ) )
36                 $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
37         else
38                 $hook = 'dashboard_page_akismet-stats-display';
39         add_action('admin_head-'.$hook, 'akismet_stats_script');
40 }
41 add_action('admin_init', 'akismet_admin_init');
42
43 if ( !function_exists('wp_nonce_field') ) {
44         function akismet_nonce_field($action = -1) { return; }
45         $akismet_nonce = -1;
46 } else {
47         function akismet_nonce_field($action = -1) { return wp_nonce_field($action); }
48         $akismet_nonce = 'akismet-update-key';
49 }
50
51 if ( !function_exists('number_format_i18n') ) {
52         function number_format_i18n( $number, $decimals = null ) { return number_format( $number, $decimals ); }
53 }
54
55 function akismet_config_page() {
56         if ( function_exists('add_submenu_page') )
57                 add_submenu_page('plugins.php', __('Akismet Configuration'), __('Akismet Configuration'), 'manage_options', 'akismet-key-config', 'akismet_conf');
58
59 }
60
61 function akismet_conf() {
62         global $akismet_nonce, $wpcom_api_key;
63
64         if ( isset($_POST['submit']) ) {
65                 if ( function_exists('current_user_can') && !current_user_can('manage_options') )
66                         die(__('Cheatin&#8217; uh?'));
67
68                 check_admin_referer( $akismet_nonce );
69                 $key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
70
71                 if ( empty($key) ) {
72                         $key_status = 'empty';
73                         $ms[] = 'new_key_empty';
74                         delete_option('wordpress_api_key');
75                 } else {
76                         $key_status = akismet_verify_key( $key );
77                 }
78
79                 if ( $key_status == 'valid' ) {
80                         update_option('wordpress_api_key', $key);
81                         $ms[] = 'new_key_valid';
82                 } else if ( $key_status == 'invalid' ) {
83                         $ms[] = 'new_key_invalid';
84                 } else if ( $key_status == 'failed' ) {
85                         $ms[] = 'new_key_failed';
86                 }
87
88                 if ( isset( $_POST['akismet_discard_month'] ) )
89                         update_option( 'akismet_discard_month', 'true' );
90                 else
91                         update_option( 'akismet_discard_month', 'false' );
92         } elseif ( isset($_POST['check']) ) {
93                 akismet_get_server_connectivity(0);
94         }
95
96         if ( $key_status != 'valid' ) {
97                 $key = get_option('wordpress_api_key');
98                 if ( empty( $key ) ) {
99                         if ( $key_status != 'failed' ) {
100                                 if ( akismet_verify_key( '1234567890ab' ) == 'failed' )
101                                         $ms[] = 'no_connection';
102                                 else
103                                         $ms[] = 'key_empty';
104                         }
105                         $key_status = 'empty';
106                 } else {
107                         $key_status = akismet_verify_key( $key );
108                 }
109                 if ( $key_status == 'valid' ) {
110                         $ms[] = 'key_valid';
111                 } else if ( $key_status == 'invalid' ) {
112                         delete_option('wordpress_api_key');
113                         $ms[] = 'key_empty';
114                 } else if ( !empty($key) && $key_status == 'failed' ) {
115                         $ms[] = 'key_failed';
116                 }
117         }
118
119         $messages = array(
120                 'new_key_empty' => array('color' => 'aa0', 'text' => __('Your key has been cleared.')),
121                 'new_key_valid' => array('color' => '2d2', 'text' => __('Your key has been verified. Happy blogging!')),
122                 'new_key_invalid' => array('color' => 'd22', 'text' => __('The key you entered is invalid. Please double-check it.')),
123                 '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.')),
124                 'no_connection' => array('color' => 'd22', 'text' => __('There was a problem connecting to the Akismet server. Please check your server configuration.')),
125                 '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/')),
126                 'key_valid' => array('color' => '2d2', 'text' => __('This key is valid.')),
127                 '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.')));
128 ?>
129 <?php if ( !empty($_POST['submit'] ) ) : ?>
130 <div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
131 <?php endif; ?>
132 <div class="wrap">
133 <h2><?php _e('Akismet Configuration'); ?></h2>
134 <div class="narrow">
135 <form action="" method="post" id="akismet-conf" style="margin: auto; width: 400px; ">
136 <?php if ( !$wpcom_api_key ) { ?>
137         <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>
138
139 <h3><label for="key"><?php _e('Akismet API Key'); ?></label></h3>
140 <?php foreach ( $ms as $m ) : ?>
141         <p style="padding: .5em; background-color: #<?php echo $messages[$m]['color']; ?>; color: #fff; font-weight: bold;"><?php echo $messages[$m]['text']; ?></p>
142 <?php endforeach; ?>
143 <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>
144 <?php if ( $invalid_key ) { ?>
145 <h3><?php _e('Why might my key be invalid?'); ?></h3>
146 <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>
147 <?php } ?>
148 <?php } ?>
149 <?php akismet_nonce_field($akismet_nonce) ?>
150 <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>
151         <p class="submit"><input type="submit" name="submit" value="<?php _e('Update options &raquo;'); ?>" /></p>
152 </form>
153
154 <form action="" method="post" id="akismet-connectivity" style="margin: auto; width: 400px; ">
155
156 <h3><?php _e('Server Connectivity'); ?></h3>
157 <?php
158         if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) {
159                 ?>
160                         <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Network functions are disabled.'); ?></p>
161                         <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>
162                 <?php
163         } else {
164                 $servers = akismet_get_server_connectivity();
165                 $fail_count = count($servers) - count( array_filter($servers) );
166                 if ( is_array($servers) && count($servers) > 0 ) {
167                         // some connections work, some fail
168                         if ( $fail_count > 0 && $fail_count < count($servers) ) { ?>
169                                 <p style="padding: .5em; background-color: #aa0; color: #fff; font-weight:bold;"><?php _e('Unable to reach some Akismet servers.'); ?></p>
170                                 <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>
171                         <?php
172                         // all connections fail
173                         } elseif ( $fail_count > 0 ) { ?>
174                                 <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Unable to reach any Akismet servers.'); ?></p>
175                                 <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>
176                         <?php
177                         // all connections work
178                         } else { ?>
179                                 <p style="padding: .5em; background-color: #2d2; color: #fff; font-weight:bold;"><?php  _e('All Akismet servers are available.'); ?></p>
180                                 <p><?php _e('Akismet is working correctly.  All servers are accessible.'); ?></p>
181                         <?php
182                         }
183                 } else {
184                         ?>
185                                 <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Unable to find Akismet servers.'); ?></p>
186                                 <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>
187                         <?php
188                 }
189         }
190         
191         if ( !empty($servers) ) {
192 ?>
193 <table style="width: 100%;">
194 <thead><th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th></thead>
195 <tbody>
196 <?php
197                 asort($servers);
198                 foreach ( $servers as $ip => $status ) {
199                         $color = ( $status ? '#2d2' : '#d22');
200         ?>
201                 <tr>
202                 <td><?php echo htmlspecialchars($ip); ?></td>
203                 <td style="padding: 0 .5em; font-weight:bold; color: #fff; background-color: <?php echo $color; ?>"><?php echo ($status ? __('No problems') : __('Obstructed') ); ?></td>
204                 
205         <?php
206                 }
207         }
208 ?>
209 </tbody>
210 </table>
211         <p><?php if ( get_option('akismet_connectivity_time') ) echo sprintf( __('Last checked %s ago.'), human_time_diff( get_option('akismet_connectivity_time') ) ); ?></p>
212         <p class="submit"><input type="submit" name="check" value="<?php _e('Check network status &raquo;'); ?>" /></p>
213 </form>
214
215 </div>
216 </div>
217 <?php
218 }
219
220 function akismet_stats_page() {
221         if ( function_exists('add_submenu_page') )
222                 add_submenu_page('index.php', __('Akismet Stats'), __('Akismet Stats'), 'manage_options', 'akismet-stats-display', 'akismet_stats_display');
223
224 }
225
226 function akismet_stats_script() {
227         ?>
228 <script type="text/javascript">
229 function resizeIframe() {
230     var height = document.documentElement.clientHeight;
231     height -= document.getElementById('akismet-stats-frame').offsetTop;
232     height += 100; // magic padding
233     
234     document.getElementById('akismet-stats-frame').style.height = height +"px";
235     
236 };
237 function resizeIframeInit() {
238         document.getElementById('akismet-stats-frame').onload = resizeIframe;
239         window.onresize = resizeIframe;
240 }
241 addLoadEvent(resizeIframeInit);
242 </script><?php
243 }
244
245
246 function akismet_stats_display() {
247         global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
248         $blog = urlencode( get_option('home') );
249         $url = "http://".akismet_get_key().".web.akismet.com/1.0/user-stats.php?blog={$blog}";
250         ?>
251         <div class="wrap">
252         <iframe src="<?php echo $url; ?>" width="100%" height="100%" frameborder="0" id="akismet-stats-frame"></iframe>
253         </div>
254         <?php
255 }
256
257 function akismet_get_key() {
258         global $wpcom_api_key;
259         if ( !empty($wpcom_api_key) )
260                 return $wpcom_api_key;
261         return get_option('wordpress_api_key');
262 }
263
264 function akismet_verify_key( $key, $ip = null ) {
265         global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
266         $blog = urlencode( get_option('home') );
267         if ( $wpcom_api_key )
268                 $key = $wpcom_api_key;
269         $response = akismet_http_post("key=$key&blog=$blog", 'rest.akismet.com', '/1.1/verify-key', $akismet_api_port, $ip);
270         if ( !is_array($response) || !isset($response[1]) || $response[1] != 'valid' && $response[1] != 'invalid' )
271                 return 'failed';
272         return $response[1];
273 }
274
275 // Check connectivity between the WordPress blog and Akismet's servers.
276 // 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).
277 function akismet_check_server_connectivity() {
278         global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
279         
280         $test_host = 'rest.akismet.com';
281         
282         // Some web hosts may disable one or both functions
283         if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') )
284                 return array();
285         
286         $ips = gethostbynamel($test_host);
287         if ( !$ips || !is_array($ips) || !count($ips) )
288                 return array();
289                 
290         $servers = array();
291         foreach ( $ips as $ip ) {
292                 $response = akismet_verify_key( akismet_get_key(), $ip );
293                 // even if the key is invalid, at least we know we have connectivity
294                 if ( $response == 'valid' || $response == 'invalid' )
295                         $servers[$ip] = true;
296                 else
297                         $servers[$ip] = false;
298         }
299
300         return $servers;
301 }
302
303 // Check the server connectivity and store the results in an option.
304 // Cached results will be used if not older than the specified timeout in seconds; use $cache_timeout = 0 to force an update.
305 // Returns the same associative array as akismet_check_server_connectivity()
306 function akismet_get_server_connectivity( $cache_timeout = 86400 ) {
307         $servers = get_option('akismet_available_servers');
308         if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false )
309                 return $servers;
310         
311         // There's a race condition here but the effect is harmless.
312         $servers = akismet_check_server_connectivity();
313         update_option('akismet_available_servers', $servers);
314         update_option('akismet_connectivity_time', time());
315         return $servers;
316 }
317
318 // Returns true if server connectivity was OK at the last check, false if there was a problem that needs to be fixed.
319 function akismet_server_connectivity_ok() {
320         // skip the check on WPMU because the status page is hidden
321         global $wpcom_api_key;
322         if ( $wpcom_api_key )
323                 return true;
324         $servers = akismet_get_server_connectivity();
325         return !( empty($servers) || !count($servers) || count( array_filter($servers) ) < count($servers) );
326 }
327
328 function akismet_admin_warnings() {
329         global $wpcom_api_key;
330         if ( !get_option('wordpress_api_key') && !$wpcom_api_key && !isset($_POST['submit']) ) {
331                 function akismet_warning() {
332                         echo "
333                         <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>
334                         ";
335                 }
336                 add_action('admin_notices', 'akismet_warning');
337                 return;
338         } elseif ( get_option('akismet_connectivity_time') && empty($_POST) && is_admin() && !akismet_server_connectivity_ok() ) {
339                 function akismet_warning() {
340                         echo "
341                         <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>
342                         ";
343                 }
344                 add_action('admin_notices', 'akismet_warning');
345                 return;
346         }
347 }
348
349 function akismet_get_host($host) {
350         // if all servers are accessible, just return the host name.
351         // if not, return an IP that was known to be accessible at the last check.
352         if ( akismet_server_connectivity_ok() ) {
353                 return $host;
354         } else {
355                 $ips = akismet_get_server_connectivity();
356                 // a firewall may be blocking access to some Akismet IPs
357                 if ( count($ips) > 0 && count(array_filter($ips)) < count($ips) ) {
358                         // use DNS to get current IPs, but exclude any known to be unreachable
359                         $dns = (array)gethostbynamel( rtrim($host, '.') . '.' );
360                         $dns = array_filter($dns);
361                         foreach ( $dns as $ip ) {
362                                 if ( array_key_exists( $ip, $ips ) && empty( $ips[$ip] ) )
363                                         unset($dns[$ip]);
364                         }
365                         // return a random IP from those available
366                         if ( count($dns) )
367                                 return $dns[ array_rand($dns) ];
368                         
369                 }
370         }
371         // if all else fails try the host name
372         return $host;
373 }
374
375 // return a comma-separated list of role names for the given user
376 function akismet_get_user_roles($user_id ) {
377         $roles = false;
378         
379         if ( !class_exists('WP_User') )
380                 return false;
381         
382         if ( $user_id > 0 ) {
383                 $comment_user = new WP_User($user_id);
384                 if ( isset($comment_user->roles) )
385                         $roles = join(',', $comment_user->roles);
386         }
387         
388         return $roles;
389 }
390
391 // Returns array with headers in $response[0] and body in $response[1]
392 function akismet_http_post($request, $host, $path, $port = 80, $ip=null) {
393         global $wp_version;
394         
395         $akismet_version = constant('AKISMET_VERSION');
396
397         $http_request  = "POST $path HTTP/1.0\r\n";
398         $http_request .= "Host: $host\r\n";
399         $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=" . get_option('blog_charset') . "\r\n";
400         $http_request .= "Content-Length: " . strlen($request) . "\r\n";
401         $http_request .= "User-Agent: WordPress/$wp_version | Akismet/$akismet_version\r\n";
402         $http_request .= "\r\n";
403         $http_request .= $request;
404         
405         $http_host = $host;
406         // use a specific IP if provided - needed by akismet_check_server_connectivity()
407         if ( $ip && long2ip(ip2long($ip)) ) {
408                 $http_host = $ip;
409         } else {
410                 $http_host = akismet_get_host($host);
411         }
412
413         $response = '';
414         if( false != ( $fs = @fsockopen($http_host, $port, $errno, $errstr, 10) ) ) {
415                 fwrite($fs, $http_request);
416
417                 while ( !feof($fs) )
418                         $response .= fgets($fs, 1160); // One TCP-IP packet
419                 fclose($fs);
420                 $response = explode("\r\n\r\n", $response, 2);
421         }
422         return $response;
423 }
424
425 // filter handler used to return a spam result to pre_comment_approved
426 function akismet_result_spam( $approved ) {
427         // bump the counter here instead of when the filter is added to reduce the possibility of overcounting
428         if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
429                 update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
430         return 'spam';
431 }
432
433 function akismet_auto_check_comment( $comment ) {
434         global $akismet_api_host, $akismet_api_port;
435
436         $comment['user_ip']    = $_SERVER['REMOTE_ADDR'];
437         $comment['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
438         $comment['referrer']   = $_SERVER['HTTP_REFERER'];
439         $comment['blog']       = get_option('home');
440         $comment['blog_lang']  = get_locale();
441         $comment['blog_charset'] = get_option('blog_charset');
442         $comment['permalink']  = get_permalink($comment['comment_post_ID']);
443         
444         $comment['user_role'] = akismet_get_user_roles($comment['user_ID']);
445
446         $ignore = array( 'HTTP_COOKIE' );
447
448         foreach ( $_SERVER as $key => $value )
449                 if ( !in_array( $key, $ignore ) && is_string($value) )
450                         $comment["$key"] = $value;
451
452         $query_string = '';
453         foreach ( $comment as $key => $data )
454                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
455
456         $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
457         if ( 'true' == $response[1] ) {
458                 // akismet_spam_count will be incremented later by akismet_result_spam()
459                 add_filter('pre_comment_approved', 'akismet_result_spam');
460
461                 do_action( 'akismet_spam_caught' );
462
463                 $post = get_post( $comment['comment_post_ID'] );
464                 $last_updated = strtotime( $post->post_modified_gmt );
465                 $diff = time() - $last_updated;
466                 $diff = $diff / 86400;
467                 
468                 if ( $post->post_type == 'post' && $diff > 30 && get_option( 'akismet_discard_month' ) == 'true' && empty($comment['user_ID']) ) {
469                         // akismet_result_spam() won't be called so bump the counter here
470                         if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
471                                 update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
472                         die;
473                 }
474         }
475         
476         if ( function_exists('wp_next_scheduled') && function_exists('wp_schedule_event') ) {
477                 // WP 2.1+: delete old comments daily
478                 if ( !wp_next_scheduled('akismet_scheduled_delete') )
479                         wp_schedule_event(time(), 'daily', 'akismet_scheduled_delete');
480         } elseif ( (mt_rand(1, 10) == 3) ) {
481                 // WP 2.0: run this one time in ten
482                 akismet_delete_old();
483         }
484         return $comment;
485 }
486
487 function akismet_delete_old() {
488         global $wpdb;
489         $now_gmt = current_time('mysql', 1);
490         $wpdb->query("DELETE FROM $wpdb->comments WHERE DATE_SUB('$now_gmt', INTERVAL 15 DAY) > comment_date_gmt AND comment_approved = 'spam'");
491         $n = mt_rand(1, 5000);
492         if ( apply_filters('akismet_optimize_table', ($n == 11)) ) // lucky number
493                 $wpdb->query("OPTIMIZE TABLE $wpdb->comments");
494 }
495
496 add_action('akismet_scheduled_delete', 'akismet_delete_old');
497
498 function akismet_submit_nonspam_comment ( $comment_id ) {
499         global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
500         $comment_id = (int) $comment_id;
501
502         $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
503         if ( !$comment ) // it was deleted
504                 return;
505         $comment->blog = get_option('home');
506         $comment->blog_lang = get_locale();
507         $comment->blog_charset = get_option('blog_charset');
508         $comment->permalink = get_permalink($comment->comment_post_ID);
509         if ( is_object($current_user) ) {
510             $comment->reporter = $current_user->user_login;
511         }
512         if ( is_object($current_site) ) {
513                 $comment->site_domain = $current_site->domain;
514         }
515         $comment->user_role = akismet_get_user_roles($comment->user_ID);
516
517         $query_string = '';
518         foreach ( $comment as $key => $data )
519                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
520
521         $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-ham", $akismet_api_port);
522 }
523
524 function akismet_submit_spam_comment ( $comment_id ) {
525         global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
526         $comment_id = (int) $comment_id;
527
528         $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
529         if ( !$comment ) // it was deleted
530                 return;
531         if ( 'spam' != $comment->comment_approved )
532                 return;
533         $comment->blog = get_option('home');
534         $comment->blog_lang = get_locale();
535         $comment->blog_charset = get_option('blog_charset');
536         $comment->permalink = get_permalink($comment->comment_post_ID);
537         if ( is_object($current_user) ) {
538             $comment->reporter = $current_user->user_login;
539         }
540         if ( is_object($current_site) ) {
541                 $comment->site_domain = $current_site->domain;
542         }
543         $comment->user_role = akismet_get_user_roles($comment->user_ID);
544         $query_string = '';
545         foreach ( $comment as $key => $data )
546                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
547
548         $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-spam", $akismet_api_port);
549 }
550
551 add_action('preprocess_comment', 'akismet_auto_check_comment', 1);
552
553 // For old versions of WP only
554 function akismet_set_comment_status( $comment_id, $status ) {
555         if ( $status == 'spam' ) {
556                 akismet_submit_spam_comment( $comment_id );
557         } elseif ( $status == 'approve' ) {
558                 akismet_submit_nonspam_comment( $comment_id );
559         }
560 }
561
562 // For WP 2.7+
563 function akismet_transition_comment_status( $new_status, $old_status, $comment ) {
564         if ( $new_status == $old_status )
565                 return;
566
567         if ( $new_status == 'spam' ) {
568                 akismet_submit_spam_comment( $comment->comment_ID );
569         } elseif ( $old_status == 'spam' && ( $new_status == 'approved' || $new_status == 'unapproved' ) ) {
570                 akismet_submit_nonspam_comment( $comment->comment_ID );
571         }
572 }
573
574 function akismet_spamtoham( $comment ) { akismet_submit_nonspam_comment( $comment->comment_ID ); }
575
576 if ( function_exists( 'wp_transition_comment_status' ) ) {
577         add_action( 'transition_comment_status', 'akismet_transition_comment_status', 10, 3 );
578 } else {
579         add_action('wp_set_comment_status', 'akismet_set_comment_status', 10, 2);
580         add_action('edit_comment', 'akismet_submit_spam_comment');
581         add_filter( 'comment_spam_to_approved', 'akismet_spamtoham' );
582         add_filter( 'comment_spam_to_unapproved', 'akismet_spamtoham' );
583 }
584 // Total spam in queue
585 // get_option( 'akismet_spam_count' ) is the total caught ever
586 function akismet_spam_count( $type = false ) {
587         global $wpdb;
588
589         if ( !$type ) { // total
590                 $count = wp_cache_get( 'akismet_spam_count', 'widget' );
591                 if ( false === $count ) {
592                         if ( function_exists('wp_count_comments') ) {
593                                 $count = wp_count_comments();
594                                 $count = $count->spam;
595                         } else {
596                                 $count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'");
597                         }
598                         wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
599                 }
600                 return $count;
601         } elseif ( 'comments' == $type || 'comment' == $type ) { // comments
602                 $type = '';
603         } else { // pingback, trackback, ...
604                 $type  = $wpdb->escape( $type );
605         }
606
607         return (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type'");
608 }
609
610 function akismet_spam_comments( $type = false, $page = 1, $per_page = 50 ) {
611         global $wpdb;
612
613         $page = (int) $page;
614         if ( $page < 2 )
615                 $page = 1;
616
617         $per_page = (int) $per_page;
618         if ( $per_page < 1 )
619                 $per_page = 50;
620
621         $start = ( $page - 1 ) * $per_page;
622         $end = $start + $per_page;
623
624         if ( $type ) {
625                 if ( 'comments' == $type || 'comment' == $type )
626                         $type = '';
627                 else
628                         $type = $wpdb->escape( $type );
629                 return $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type' ORDER BY comment_date DESC LIMIT $start, $end");
630         }
631
632         // All
633         return $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' ORDER BY comment_date DESC LIMIT $start, $end");
634 }
635
636 // Totals for each comment type
637 // returns array( type => count, ... )
638 function akismet_spam_totals() {
639         global $wpdb;
640         $totals = $wpdb->get_results( "SELECT comment_type, COUNT(*) AS cc FROM $wpdb->comments WHERE comment_approved = 'spam' GROUP BY comment_type" );
641         $return = array();
642         foreach ( $totals as $total )
643                 $return[$total->comment_type ? $total->comment_type : 'comment'] = $total->cc;
644         return $return;
645 }
646
647 function akismet_manage_page() {
648         global $wpdb, $submenu, $wp_db_version;
649
650         // WP 2.7 has its own spam management page
651         if ( 8645 <= $wp_db_version )
652                 return;
653
654         $count = sprintf(__('Akismet Spam (%s)'), akismet_spam_count());
655         if ( isset( $submenu['edit-comments.php'] ) )
656                 add_submenu_page('edit-comments.php', __('Akismet Spam'), $count, 'moderate_comments', 'akismet-admin', 'akismet_caught' );
657         elseif ( function_exists('add_management_page') )
658                 add_management_page(__('Akismet Spam'), $count, 'moderate_comments', 'akismet-admin', 'akismet_caught');
659 }
660
661 function akismet_caught() {
662         global $wpdb, $comment, $akismet_caught, $akismet_nonce;
663
664         akismet_recheck_queue();
665         if (isset($_POST['submit']) && 'recover' == $_POST['action'] && ! empty($_POST['not_spam'])) {
666                 check_admin_referer( $akismet_nonce );
667                 if ( function_exists('current_user_can') && !current_user_can('moderate_comments') )
668                         die(__('You do not have sufficient permission to moderate comments.'));
669
670                 $i = 0;
671                 foreach ($_POST['not_spam'] as $comment):
672                         $comment = (int) $comment;
673                         if ( function_exists('wp_set_comment_status') )
674                                 wp_set_comment_status($comment, 'approve');
675                         else
676                                 $wpdb->query("UPDATE $wpdb->comments SET comment_approved = '1' WHERE comment_ID = '$comment'");
677                         akismet_submit_nonspam_comment($comment);
678                         ++$i;
679                 endforeach;
680                 $to = add_query_arg( 'recovered', $i, $_SERVER['HTTP_REFERER'] );
681                 wp_redirect( $to );
682                 exit;
683         }
684         if ('delete' == $_POST['action']) {
685                 check_admin_referer( $akismet_nonce );
686                 if ( function_exists('current_user_can') && !current_user_can('moderate_comments') )
687                         die(__('You do not have sufficient permission to moderate comments.'));
688
689                 $delete_time = $wpdb->escape( $_POST['display_time'] );
690                 $nuked = $wpdb->query( "DELETE FROM $wpdb->comments WHERE comment_approved = 'spam' AND '$delete_time' > comment_date_gmt" );
691                 wp_cache_delete( 'akismet_spam_count', 'widget' );
692                 $to = add_query_arg( 'deleted', 'all', $_SERVER['HTTP_REFERER'] );
693                 wp_redirect( $to );
694                 exit;
695         }
696
697 if ( isset( $_GET['recovered'] ) ) {
698         $i = (int) $_GET['recovered'];
699         echo '<div class="updated"><p>' . sprintf(__('%1$s comments recovered.'), $i) . "</p></div>";
700 }
701
702 if (isset( $_GET['deleted'] ) )
703         echo '<div class="updated"><p>' . __('All spam deleted.') . '</p></div>';
704
705 if ( isset( $GLOBALS['submenu']['edit-comments.php'] ) )
706         $link = 'edit-comments.php';
707 else
708         $link = 'edit.php';
709 ?>
710 <style type="text/css">
711 .akismet-tabs {
712         list-style: none;
713         margin: 0;
714         padding: 0;
715         clear: both;
716         border-bottom: 1px solid #ccc;
717         height: 31px;
718         margin-bottom: 20px;
719         background: #ddd;
720         border-top: 1px solid #bdbdbd;
721 }
722 .akismet-tabs li {
723         float: left;
724         margin: 5px 0 0 20px;
725 }
726 .akismet-tabs a {
727         display: block;
728         padding: 4px .5em 3px;
729         border-bottom: none;
730         color: #036;
731 }
732 .akismet-tabs .active a {
733         background: #fff;
734         border: 1px solid #ccc;
735         border-bottom: none;
736         color: #000;
737         font-weight: bold;
738         padding-bottom: 4px;
739 }
740 #akismetsearch {
741         float: right;
742         margin-top: -.5em;
743 }
744
745 #akismetsearch p {
746         margin: 0;
747         padding: 0;
748 }
749 </style>
750 <div class="wrap">
751 <h2><?php _e('Caught Spam') ?></h2>
752 <?php
753 $count = get_option( 'akismet_spam_count' );
754 if ( $count ) {
755 ?>
756 <p><?php printf(__('Akismet has caught <strong>%1$s spam</strong> for you since you first installed it.'), number_format_i18n($count) ); ?></p>
757 <?php
758 }
759
760 $spam_count = akismet_spam_count();
761
762 if ( 0 == $spam_count ) {
763         echo '<p>'.__('You have no spam currently in the queue. Must be your lucky day. :)').'</p>';
764         echo '</div>';
765 } else {
766         echo '<p>'.__('You can delete all of the spam from your database with a single click. This operation cannot be undone, so you may wish to check to ensure that no legitimate comments got through first. Spam is automatically deleted after 15 days, so don&#8217;t sweat it.').'</p>';
767 ?>
768 <?php if ( !isset( $_POST['s'] ) ) { ?>
769 <form method="post" action="<?php echo attribute_escape( add_query_arg( 'noheader', 'true' ) ); ?>">
770 <?php akismet_nonce_field($akismet_nonce) ?>
771 <input type="hidden" name="action" value="delete" />
772 <?php printf(__('There are currently %1$s comments identified as spam.'), $spam_count); ?>&nbsp; &nbsp; <input type="submit" class="button delete" name="Submit" value="<?php _e('Delete all'); ?>" />
773 <input type="hidden" name="display_time" value="<?php echo current_time('mysql', 1); ?>" />
774 </form>
775 <?php } ?>
776 </div>
777 <div class="wrap">
778 <?php if ( isset( $_POST['s'] ) ) { ?>
779 <h2><?php _e('Search'); ?></h2>
780 <?php } else { ?>
781 <?php echo '<p>'.__('These are the latest comments identified as spam by Akismet. If you see any mistakes, simply mark the comment as "not spam" and Akismet will learn from the submission. If you wish to recover a comment from spam, simply select the comment, and click Not Spam. After 15 days we clean out the junk for you.').'</p>'; ?>
782 <?php } ?>
783 <?php
784 if ( isset( $_POST['s'] ) ) {
785         $s = $wpdb->escape($_POST['s']);
786         $comments = $wpdb->get_results("SELECT * FROM $wpdb->comments  WHERE
787                 (comment_author LIKE '%$s%' OR
788                 comment_author_email LIKE '%$s%' OR
789                 comment_author_url LIKE ('%$s%') OR
790                 comment_author_IP LIKE ('%$s%') OR
791                 comment_content LIKE ('%$s%') ) AND
792                 comment_approved = 'spam'
793                 ORDER BY comment_date DESC");
794 } else {
795         if ( isset( $_GET['apage'] ) )
796                 $page = (int) $_GET['apage'];
797         else
798                 $page = 1;
799
800         if ( $page < 2 )
801                 $page = 1;
802
803         $current_type = false;
804         if ( isset( $_GET['ctype'] ) )
805                 $current_type = preg_replace( '|[^a-z]|', '', $_GET['ctype'] );
806
807         $comments = akismet_spam_comments( $current_type, $page );
808         $total = akismet_spam_count( $current_type );
809         $totals = akismet_spam_totals();
810 ?>
811 <ul class="akismet-tabs">
812 <li <?php if ( !isset( $_GET['ctype'] ) ) echo ' class="active"'; ?>><a href="edit-comments.php?page=akismet-admin"><?php _e('All'); ?></a></li>
813 <?php
814 foreach ( $totals as $type => $type_count ) {
815         if ( 'comment' == $type ) {
816                 $type = 'comments';
817                 $show = __('Comments');
818         } else {
819                 $show = ucwords( $type );
820         }
821         $type_count = number_format_i18n( $type_count );
822         $extra = $current_type === $type ? ' class="active"' : '';
823         echo "<li $extra><a href='edit-comments.php?page=akismet-admin&amp;ctype=$type'>$show ($type_count)</a></li>";
824 }
825 do_action( 'akismet_tabs' ); // so plugins can add more tabs easily
826 ?>
827 </ul>
828 <?php
829 }
830
831 if ($comments) {
832 ?>
833 <form method="post" action="<?php echo attribute_escape("$link?page=akismet-admin"); ?>" id="akismetsearch">
834 <p>  <input type="text" name="s" value="<?php if (isset($_POST['s'])) echo attribute_escape($_POST['s']); ?>" size="17" />
835   <input type="submit" class="button" name="submit" value="<?php echo attribute_escape(__('Search Spam &raquo;')) ?>"  />  </p>
836 </form>
837 <?php if ( $total > 50 ) {
838 $total_pages = ceil( $total / 50 );
839 $r = '';
840 if ( 1 < $page ) {
841         $args['apage'] = ( 1 == $page - 1 ) ? '' : $page - 1;
842         $r .=  '<a class="prev" href="' . clean_url(add_query_arg( $args )) . '">'. __('&laquo; Previous Page') .'</a>' . "\n";
843 }
844 if ( ( $total_pages = ceil( $total / 50 ) ) > 1 ) {
845         for ( $page_num = 1; $page_num <= $total_pages; $page_num++ ) :
846                 if ( $page == $page_num ) :
847                         $r .=  "<strong>$page_num</strong>\n";
848                 else :
849                         $p = false;
850                         if ( $page_num < 3 || ( $page_num >= $page - 3 && $page_num <= $page + 3 ) || $page_num > $total_pages - 3 ) :
851                                 $args['apage'] = ( 1 == $page_num ) ? '' : $page_num;
852                                 $r .= '<a class="page-numbers" href="' . clean_url(add_query_arg($args)) . '">' . ( $page_num ) . "</a>\n";
853                                 $in = true;
854                         elseif ( $in == true ) :
855                                 $r .= "...\n";
856                                 $in = false;
857                         endif;
858                 endif;
859         endfor;
860 }
861 if ( ( $page ) * 50 < $total || -1 == $total ) {
862         $args['apage'] = $page + 1;
863         $r .=  '<a class="next" href="' . clean_url(add_query_arg($args)) . '">'. __('Next Page &raquo;') .'</a>' . "\n";
864 }
865 echo "<p>$r</p>";
866 ?>
867
868 <?php } ?>
869 <form style="clear: both;" method="post" action="<?php echo attribute_escape( add_query_arg( 'noheader', 'true' ) ); ?>">
870 <?php akismet_nonce_field($akismet_nonce) ?>
871 <input type="hidden" name="action" value="recover" />
872 <ul id="spam-list" class="commentlist" style="list-style: none; margin: 0; padding: 0;">
873 <?php
874 $i = 0;
875 foreach($comments as $comment) {
876         $i++;
877         $comment_date = mysql2date(get_option("date_format") . " @ " . get_option("time_format"), $comment->comment_date);
878         $post = get_post($comment->comment_post_ID);
879         $post_title = $post->post_title;
880         if ($i % 2) $class = 'class="alternate"';
881         else $class = '';
882         echo "\n\t<li id='comment-$comment->comment_ID' $class>";
883         ?>
884
885 <p><strong><?php comment_author() ?></strong> <?php if ($comment->comment_author_email) { ?>| <?php comment_author_email_link() ?> <?php } if ($comment->comment_author_url && 'http://' != $comment->comment_author_url) { ?> | <?php comment_author_url_link() ?> <?php } ?>| <?php _e('IP:') ?> <a href="http://ws.arin.net/cgi-bin/whois.pl?queryinput=<?php comment_author_IP() ?>"><?php comment_author_IP() ?></a></p>
886
887 <?php comment_text() ?>
888
889 <p><label for="spam-<?php echo $comment->comment_ID; ?>">
890 <input type="checkbox" id="spam-<?php echo $comment->comment_ID; ?>" name="not_spam[]" value="<?php echo $comment->comment_ID; ?>" />
891 <?php _e('Not Spam') ?></label> &#8212; <?php comment_date('M j, g:i A');  ?> &#8212; [
892 <?php
893 $post = get_post($comment->comment_post_ID);
894 $post_title = wp_specialchars( $post->post_title, 'double' );
895 $post_title = ('' == $post_title) ? "# $comment->comment_post_ID" : $post_title;
896 ?>
897  <a href="<?php echo get_permalink($comment->comment_post_ID); ?>" title="<?php echo $post_title; ?>"><?php _e('View Post') ?></a> ] </p>
898
899
900 <?php
901 }
902 ?>
903 </ul>
904 <?php if ( $total > 50 ) {
905 $total_pages = ceil( $total / 50 );
906 $r = '';
907 if ( 1 < $page ) {
908         $args['apage'] = ( 1 == $page - 1 ) ? '' : $page - 1;
909         $r .=  '<a class="prev" href="' . clean_url(add_query_arg( $args )) . '">'. __('&laquo; Previous Page') .'</a>' . "\n";
910 }
911 if ( ( $total_pages = ceil( $total / 50 ) ) > 1 ) {
912         for ( $page_num = 1; $page_num <= $total_pages; $page_num++ ) :
913                 if ( $page == $page_num ) :
914                         $r .=  "<strong>$page_num</strong>\n";
915                 else :
916                         $p = false;
917                         if ( $page_num < 3 || ( $page_num >= $page - 3 && $page_num <= $page + 3 ) || $page_num > $total_pages - 3 ) :
918                                 $args['apage'] = ( 1 == $page_num ) ? '' : $page_num;
919                                 $r .= '<a class="page-numbers" href="' . clean_url(add_query_arg($args)) . '">' . ( $page_num ) . "</a>\n";
920                                 $in = true;
921                         elseif ( $in == true ) :
922                                 $r .= "...\n";
923                                 $in = false;
924                         endif;
925                 endif;
926         endfor;
927 }
928 if ( ( $page ) * 50 < $total || -1 == $total ) {
929         $args['apage'] = $page + 1;
930         $r .=  '<a class="next" href="' . clean_url(add_query_arg($args)) . '">'. __('Next Page &raquo;') .'</a>' . "\n";
931 }
932 echo "<p>$r</p>";
933 }
934 ?>
935 <p class="submit">
936 <input type="submit" name="submit" value="<?php echo attribute_escape(__('De-spam marked comments &raquo;')); ?>" />
937 </p>
938 <p><?php _e('Comments you de-spam will be submitted to Akismet as mistakes so it can learn and get better.'); ?></p>
939 </form>
940 <?php
941 } else {
942 ?>
943 <p><?php _e('No results found.'); ?></p>
944 <?php } ?>
945
946 <?php if ( !isset( $_POST['s'] ) ) { ?>
947 <form method="post" action="<?php echo attribute_escape( add_query_arg( 'noheader', 'true' ) ); ?>">
948 <?php akismet_nonce_field($akismet_nonce) ?>
949 <p><input type="hidden" name="action" value="delete" />
950 <?php printf(__('There are currently %1$s comments identified as spam.'), $spam_count); ?>&nbsp; &nbsp; <input type="submit" name="Submit" class="button" value="<?php echo attribute_escape(__('Delete all')); ?>" />
951 <input type="hidden" name="display_time" value="<?php echo current_time('mysql', 1); ?>" /></p>
952 </form>
953 <?php } ?>
954 </div>
955 <?php
956         }
957 }
958
959 add_action('admin_menu', 'akismet_manage_page');
960
961 // WP < 2.5
962 function akismet_stats() {
963         if ( !function_exists('did_action') || did_action( 'rightnow_end' ) ) // We already displayed this info in the "Right Now" section
964                 return;
965         if ( !$count = get_option('akismet_spam_count') )
966                 return;
967         $path = plugin_basename(__FILE__);
968         echo '<h3>'.__('Spam').'</h3>';
969         global $submenu;
970         if ( isset( $submenu['edit-comments.php'] ) )
971                 $link = 'edit-comments.php';
972         else
973                 $link = 'edit.php';
974         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>';
975 }
976
977 add_action('activity_box_end', 'akismet_stats');
978
979 // WP 2.5+
980 function akismet_rightnow() {
981         global $submenu, $wp_db_version;
982
983         if ( 8645 < $wp_db_version  ) // 2.7
984                 $link = 'edit-comments.php?comment_status=spam';
985         elseif ( isset( $submenu['edit-comments.php'] ) )
986                 $link = 'edit-comments.php?page=akismet-admin';
987         else
988                 $link = 'edit.php?page=akismet-admin';
989
990         if ( $count = get_option('akismet_spam_count') ) {
991                 $intro = sprintf( __ngettext(
992                         '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comment already,',
993                         '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comments already,',
994                         $count
995                 ), 'http://akismet.com/', number_format_i18n( $count ) );
996         } else {
997                 $intro = sprintf( __('<a href="%1$s">Akismet</a> blocks spam from getting to your blog,'), 'http://akismet.com/' );
998         }
999
1000         if ( $queue_count = akismet_spam_count() ) {
1001                 $queue_text = sprintf( __ngettext(
1002                         'and there\'s <a href="%2$s">%1$s comment</a> in your spam queue right now.',
1003                         'and there are <a href="%2$s">%1$s comments</a> in your spam queue right now.',
1004                         $queue_count
1005                 ), number_format_i18n( $queue_count ), clean_url($link) );
1006         } else {
1007                 $queue_text = sprintf( __( "but there's nothing in your <a href='%1\$s'>spam queue</a> at the moment." ), clean_url($link) );
1008         }
1009
1010         $text = sprintf( _c( '%1$s %2$s|akismet_rightnow' ), $intro, $queue_text );
1011
1012         echo "<p class='akismet-right-now'>$text</p>\n";
1013 }
1014         
1015 add_action('rightnow_end', 'akismet_rightnow');
1016
1017 // For WP <= 2.3.x
1018 global $pagenow;
1019
1020 if ( 'moderation.php' == $pagenow ) {
1021         function akismet_recheck_button( $page ) {
1022                 global $submenu;
1023                 if ( isset( $submenu['edit-comments.php'] ) )
1024                         $link = 'edit-comments.php';
1025                 else
1026                         $link = 'edit.php';
1027                 $button = "<a href='$link?page=akismet-admin&amp;recheckqueue=true&amp;noheader=true' style='display: block; width: 100px; position: absolute; right: 7%; padding: 5px; font-size: 14px; text-decoration: underline; background: #fff; border: 1px solid #ccc;'>" . __('Recheck Queue for Spam') . "</a>";
1028                 $page = str_replace( '<div class="wrap">', '<div class="wrap">' . $button, $page );
1029                 return $page;
1030         }
1031
1032         if ( $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = '0'" ) )
1033                 ob_start( 'akismet_recheck_button' );
1034 }
1035
1036 // For WP >= 2.5
1037 function akismet_check_for_spam_button($comment_status) {
1038         if ( 'approved' == $comment_status )
1039                 return;
1040         if ( function_exists('plugins_url') )
1041                 $link = 'admin.php?action=akismet_recheck_queue';
1042         else
1043                 $link = 'edit-comments.php?page=akismet-admin&amp;recheckqueue=true&amp;noheader=true';
1044         echo "</div><div class='alignleft'><a class='button-secondary checkforspam' href='$link'>" . __('Check for Spam') . "</a>";
1045 }
1046 add_action('manage_comments_nav', 'akismet_check_for_spam_button');
1047
1048 function akismet_recheck_queue() {
1049         global $wpdb, $akismet_api_host, $akismet_api_port;
1050
1051         if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
1052                 return;
1053
1054         $moderation = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = '0'", ARRAY_A );
1055         foreach ( (array) $moderation as $c ) {
1056                 $c['user_ip']    = $c['comment_author_IP'];
1057                 $c['user_agent'] = $c['comment_agent'];
1058                 $c['referrer']   = '';
1059                 $c['blog']       = get_option('home');
1060                 $c['blog_lang']  = get_locale();
1061                 $c['blog_charset'] = get_option('blog_charset');
1062                 $c['permalink']  = get_permalink($c['comment_post_ID']);
1063                 $c['user_role']  = akismet_get_user_roles($c['user_ID']);
1064                 $id = (int) $c['comment_ID'];
1065
1066                 $query_string = '';
1067                 foreach ( $c as $key => $data )
1068                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
1069
1070                 $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
1071                 if ( 'true' == $response[1] ) {
1072                         $wpdb->query( "UPDATE $wpdb->comments SET comment_approved = 'spam' WHERE comment_ID = $id" );
1073                 }
1074         }
1075         wp_redirect( $_SERVER['HTTP_REFERER'] );
1076         exit;
1077 }
1078
1079 add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
1080
1081 function akismet_check_db_comment( $id ) {
1082         global $wpdb, $akismet_api_host, $akismet_api_port;
1083
1084         $id = (int) $id;
1085         $c = $wpdb->get_row( "SELECT * FROM $wpdb->comments WHERE comment_ID = '$id'", ARRAY_A );
1086         if ( !$c )
1087                 return;
1088
1089         $c['user_ip']    = $c['comment_author_IP'];
1090         $c['user_agent'] = $c['comment_agent'];
1091         $c['referrer']   = '';
1092         $c['blog']       = get_option('home');
1093         $c['blog_lang']  = get_locale();
1094         $c['blog_charset'] = get_option('blog_charset');
1095         $c['permalink']  = get_permalink($c['comment_post_ID']);
1096         $id = $c['comment_ID'];
1097
1098         $query_string = '';
1099         foreach ( $c as $key => $data )
1100         $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
1101
1102         $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
1103         return $response[1];
1104 }
1105
1106 // This option causes tons of FPs, was removed in 2.1
1107 function akismet_kill_proxy_check( $option ) { return 0; }
1108 add_filter('option_open_proxy_check', 'akismet_kill_proxy_check');
1109
1110 // Widget stuff
1111 function widget_akismet_register() {
1112         if ( function_exists('register_sidebar_widget') ) :
1113         function widget_akismet($args) {
1114                 extract($args);
1115                 $options = get_option('widget_akismet');
1116                 $count = number_format_i18n(get_option('akismet_spam_count'));
1117                 ?>
1118                         <?php echo $before_widget; ?>
1119                                 <?php echo $before_title . $options['title'] . $after_title; ?>
1120                                 <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>
1121                         <?php echo $after_widget; ?>
1122         <?php
1123         }
1124
1125         function widget_akismet_style() {
1126                 ?>
1127 <style type="text/css">
1128 #aka,#aka:link,#aka:hover,#aka:visited,#aka:active{color:#fff;text-decoration:none}
1129 #aka:hover{border:none;text-decoration:none}
1130 #aka:hover #akismet1{display:none}
1131 #aka:hover #akismet2,#akismet1{display:block}
1132 #akismet2{display:none;padding-top:2px}
1133 #akismeta{font-size:16px;font-weight:bold;line-height:18px;text-decoration:none}
1134 #akismetcount{display:block;font:15px Verdana,Arial,Sans-Serif;font-weight:bold;text-decoration:none}
1135 #akismetwrap #akismetstats{background:url(<?php echo get_option('siteurl'); ?>/wp-content/plugins/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}
1136 </style>
1137                 <?php
1138         }
1139
1140         function widget_akismet_control() {
1141                 $options = $newoptions = get_option('widget_akismet');
1142                 if ( $_POST["akismet-submit"] ) {
1143                         $newoptions['title'] = strip_tags(stripslashes($_POST["akismet-title"]));
1144                         if ( empty($newoptions['title']) ) $newoptions['title'] = __('Spam Blocked');
1145                 }
1146                 if ( $options != $newoptions ) {
1147                         $options = $newoptions;
1148                         update_option('widget_akismet', $options);
1149                 }
1150                 $title = htmlspecialchars($options['title'], ENT_QUOTES);
1151         ?>
1152                                 <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>
1153                                 <input type="hidden" id="akismet-submit" name="akismet-submit" value="1" />
1154         <?php
1155         }
1156
1157         register_sidebar_widget('Akismet', 'widget_akismet', null, 'akismet');
1158         register_widget_control('Akismet', 'widget_akismet_control', null, 75, 'akismet');
1159         if ( is_active_widget('widget_akismet') )
1160                 add_action('wp_head', 'widget_akismet_style');
1161         endif;
1162 }
1163
1164 add_action('init', 'widget_akismet_register');
1165
1166 // Counter for non-widget users
1167 function akismet_counter() {
1168 ?>
1169 <style type="text/css">
1170 #akismetwrap #aka,#aka:link,#aka:hover,#aka:visited,#aka:active{color:#fff;text-decoration:none}
1171 #aka:hover{border:none;text-decoration:none}
1172 #aka:hover #akismet1{display:none}
1173 #aka:hover #akismet2,#akismet1{display:block}
1174 #akismet2{display:none;padding-top:2px}
1175 #akismeta{font-size:16px;font-weight:bold;line-height:18px;text-decoration:none}
1176 #akismetcount{display:block;font:15px Verdana,Arial,Sans-Serif;font-weight:bold;text-decoration:none}
1177 #akismetwrap #akismetstats{background:url(<?php echo get_option('siteurl'); ?>/wp-content/plugins/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}
1178 </style>
1179 <?php
1180 $count = number_format_i18n(get_option('akismet_spam_count'));
1181 ?>
1182 <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>
1183 <?php
1184 }
1185
1186 ?>