]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-content/plugins/akismet/akismet.php
Wordpress 3.0.4-scripts
[autoinstalls/wordpress.git] / wp-content / plugins / akismet / akismet.php
1 <?php
2 /**
3  * @package Akismet
4  */
5 /*
6 Plugin Name: Akismet
7 Plugin URI: http://akismet.com/
8 Description: Akismet checks your comments against the Akismet web service to see if they look like spam or not. You need an <a href="http://akismet.com/get/">API key</a> to use it. You can review the spam it catches under "Comments." To show off your Akismet stats just put <code>&lt;?php akismet_counter(); ?&gt;</code> in your template. See also: <a href="http://wordpress.org/extend/plugins/stats/">WP Stats plugin</a>.
9 Version: 2.4.0
10 Author: Automattic
11 Author URI: http://automattic.com/wordpress-plugins/
12 License: GPLv2
13 */
14
15 /*
16 This program is free software; you can redistribute it and/or modify 
17 it under the terms of the GNU General Public License as published by 
18 the Free Software Foundation; version 2 of the License.
19
20 This program is distributed in the hope that it will be useful, 
21 but WITHOUT ANY WARRANTY; without even the implied warranty of 
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
23 GNU General Public License for more details. 
24
25 You should have received a copy of the GNU General Public License 
26 along with this program; if not, write to the Free Software 
27 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
28 */
29
30 define('AKISMET_VERSION', '2.4.0');
31
32 /** If you hardcode a WP.com API key here, all key config screens will be hidden */
33 if ( defined('WPCOM_API_KEY') )
34         $wpcom_api_key = constant('WPCOM_API_KEY');
35 else
36         $wpcom_api_key = '';
37
38 // Make sure we don't expose any info if called directly
39 if ( !function_exists( 'add_action' ) ) {
40         echo "Hi there!  I'm just a plugin, not much I can do when called directly.";
41         exit;
42 }
43
44 if ( $wp_db_version <= 9872 )
45         include_once( dirname(__FILE__) . '/legacy.php' );
46
47 function akismet_init() {
48         global $wpcom_api_key, $akismet_api_host, $akismet_api_port;
49
50         if ( $wpcom_api_key )
51                 $akismet_api_host = $wpcom_api_key . '.rest.akismet.com';
52         else
53                 $akismet_api_host = get_option('wordpress_api_key') . '.rest.akismet.com';
54
55         $akismet_api_port = 80;
56         add_action('admin_menu', 'akismet_config_page');
57         add_action('admin_menu', 'akismet_stats_page');
58         akismet_admin_warnings();
59 }
60 add_action('init', 'akismet_init');
61
62 function akismet_admin_init() {
63         if ( function_exists( 'get_plugin_page_hook' ) )
64                 $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
65         else
66                 $hook = 'dashboard_page_akismet-stats-display';
67         add_action('admin_head-'.$hook, 'akismet_stats_script');
68 }
69 add_action('admin_init', 'akismet_admin_init');
70
71 if ( !function_exists('wp_nonce_field') ) {
72         function akismet_nonce_field($action = -1) { return; }
73         $akismet_nonce = -1;
74 } else {
75         function akismet_nonce_field($action = -1) { return wp_nonce_field($action); }
76         $akismet_nonce = 'akismet-update-key';
77 }
78
79 if ( !function_exists('number_format_i18n') ) {
80         function number_format_i18n( $number, $decimals = null ) { return number_format( $number, $decimals ); }
81 }
82
83 function akismet_config_page() {
84         if ( function_exists('add_submenu_page') )
85                 add_submenu_page('plugins.php', __('Akismet Configuration'), __('Akismet Configuration'), 'manage_options', 'akismet-key-config', 'akismet_conf');
86
87 }
88
89 function akismet_conf() {
90         global $akismet_nonce, $wpcom_api_key;
91
92         if ( isset($_POST['submit']) ) {
93                 if ( function_exists('current_user_can') && !current_user_can('manage_options') )
94                         die(__('Cheatin&#8217; uh?'));
95
96                 check_admin_referer( $akismet_nonce );
97                 $key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
98
99                 if ( empty($key) ) {
100                         $key_status = 'empty';
101                         $ms[] = 'new_key_empty';
102                         delete_option('wordpress_api_key');
103                 } else {
104                         $key_status = akismet_verify_key( $key );
105                 }
106
107                 if ( $key_status == 'valid' ) {
108                         update_option('wordpress_api_key', $key);
109                         $ms[] = 'new_key_valid';
110                 } else if ( $key_status == 'invalid' ) {
111                         $ms[] = 'new_key_invalid';
112                 } else if ( $key_status == 'failed' ) {
113                         $ms[] = 'new_key_failed';
114                 }
115
116                 if ( isset( $_POST['akismet_discard_month'] ) )
117                         update_option( 'akismet_discard_month', 'true' );
118                 else
119                         update_option( 'akismet_discard_month', 'false' );
120         } elseif ( isset($_POST['check']) ) {
121                 akismet_get_server_connectivity(0);
122         }
123
124         if ( empty( $key_status) ||  $key_status != 'valid' ) {
125                 $key = get_option('wordpress_api_key');
126                 if ( empty( $key ) ) {
127                         if ( empty( $key_status ) || $key_status != 'failed' ) {
128                                 if ( akismet_verify_key( '1234567890ab' ) == 'failed' )
129                                         $ms[] = 'no_connection';
130                                 else
131                                         $ms[] = 'key_empty';
132                         }
133                         $key_status = 'empty';
134                 } else {
135                         $key_status = akismet_verify_key( $key );
136                 }
137                 if ( $key_status == 'valid' ) {
138                         $ms[] = 'key_valid';
139                 } else if ( $key_status == 'invalid' ) {
140                         delete_option('wordpress_api_key');
141                         $ms[] = 'key_empty';
142                 } else if ( !empty($key) && $key_status == 'failed' ) {
143                         $ms[] = 'key_failed';
144                 }
145         }
146
147         $messages = array(
148                 'new_key_empty' => array('color' => 'aa0', 'text' => __('Your key has been cleared.')),
149                 'new_key_valid' => array('color' => '2d2', 'text' => __('Your key has been verified. Happy blogging!')),
150                 'new_key_invalid' => array('color' => 'd22', 'text' => __('The key you entered is invalid. Please double-check it.')),
151                 'new_key_failed' => array('color' => 'd22', 'text' => __('The key you entered could not be verified because a connection to akismet.com could not be established. Please check your server configuration.')),
152                 'no_connection' => array('color' => 'd22', 'text' => __('There was a problem connecting to the Akismet server. Please check your server configuration.')),
153                 'key_empty' => array('color' => 'aa0', 'text' => sprintf(__('Please enter an API key. (<a href="%s" style="color:#fff">Get your key.</a>)'), 'http://akismet.com/get/')),
154                 'key_valid' => array('color' => '2d2', 'text' => __('This key is valid.')),
155                 'key_failed' => array('color' => 'aa0', 'text' => __('The key below was previously validated but a connection to akismet.com can not be established at this time. Please check your server configuration.')));
156 ?>
157 <?php if ( !empty($_POST['submit'] ) ) : ?>
158 <div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
159 <?php endif; ?>
160 <div class="wrap">
161 <h2><?php _e('Akismet Configuration'); ?></h2>
162 <div class="narrow">
163 <form action="" method="post" id="akismet-conf" style="margin: auto; width: 400px; ">
164 <?php if ( !$wpcom_api_key ) { ?>
165         <p><?php printf(__('For many people, <a href="%1$s">Akismet</a> will greatly reduce or even completely eliminate the comment and trackback spam you get on your site. If one does happen to get through, simply mark it as "spam" on the moderation screen and Akismet will learn from the mistakes. If you don\'t have an API key yet, you can get one at <a href="%2$s">Akismet.com</a>.'), 'http://akismet.com/', 'http://akismet.com/get/'); ?></p>
166
167 <h3><label for="key"><?php _e('Akismet API Key'); ?></label></h3>
168 <?php foreach ( $ms as $m ) : ?>
169         <p style="padding: .5em; background-color: #<?php echo $messages[$m]['color']; ?>; color: #fff; font-weight: bold;"><?php echo $messages[$m]['text']; ?></p>
170 <?php endforeach; ?>
171 <p><input id="key" name="key" type="text" size="15" maxlength="12" value="<?php echo get_option('wordpress_api_key'); ?>" style="font-family: 'Courier New', Courier, mono; font-size: 1.5em;" /> (<?php _e('<a href="http://akismet.com/get/">What is this?</a>'); ?>)</p>
172 <?php if ( isset( $invalid_key) && $invalid_key ) { ?>
173 <h3><?php _e('Why might my key be invalid?'); ?></h3>
174 <p><?php _e('This can mean one of two things, either you copied the key wrong or that the plugin is unable to reach the Akismet servers, which is most often caused by an issue with your web host around firewalls or similar.'); ?></p>
175 <?php } ?>
176 <?php } ?>
177 <?php akismet_nonce_field($akismet_nonce) ?>
178 <p><label><input name="akismet_discard_month" id="akismet_discard_month" value="true" type="checkbox" <?php if ( get_option('akismet_discard_month') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Automatically discard spam comments on posts older than a month.'); ?></label></p>
179         <p class="submit"><input type="submit" name="submit" value="<?php _e('Update options &raquo;'); ?>" /></p>
180 </form>
181
182 <form action="" method="post" id="akismet-connectivity" style="margin: auto; width: 400px; ">
183
184 <h3><?php _e('Server Connectivity'); ?></h3>
185 <?php
186         if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) {
187                 ?>
188                         <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Network functions are disabled.'); ?></p>
189                         <p><?php echo sprintf( __('Your web host or server administrator has disabled PHP\'s <code>fsockopen</code> or <code>gethostbynamel</code> functions.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet\'s system requirements</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
190                 <?php
191         } else {
192                 $servers = akismet_get_server_connectivity();
193                 $fail_count = count($servers) - count( array_filter($servers) );
194                 if ( is_array($servers) && count($servers) > 0 ) {
195                         // some connections work, some fail
196                         if ( $fail_count > 0 && $fail_count < count($servers) ) { ?>
197                                 <p style="padding: .5em; background-color: #aa0; color: #fff; font-weight:bold;"><?php _e('Unable to reach some Akismet servers.'); ?></p>
198                                 <p><?php echo sprintf( __('A network problem or firewall is blocking some connections from your web server to Akismet.com.  Akismet is working but this may cause problems during times of network congestion.  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
199                         <?php
200                         // all connections fail
201                         } elseif ( $fail_count > 0 ) { ?>
202                                 <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Unable to reach any Akismet servers.'); ?></p>
203                                 <p><?php echo sprintf( __('A network problem or firewall is blocking all connections from your web server to Akismet.com.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
204                         <?php
205                         // all connections work
206                         } else { ?>
207                                 <p style="padding: .5em; background-color: #2d2; color: #fff; font-weight:bold;"><?php  _e('All Akismet servers are available.'); ?></p>
208                                 <p><?php _e('Akismet is working correctly.  All servers are accessible.'); ?></p>
209                         <?php
210                         }
211                 } else {
212                         ?>
213                                 <p style="padding: .5em; background-color: #d22; color: #fff; font-weight:bold;"><?php _e('Unable to find Akismet servers.'); ?></p>
214                                 <p><?php echo sprintf( __('A DNS problem or firewall is preventing all access from your web server to Akismet.com.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
215                         <?php
216                 }
217         }
218         
219         if ( !empty($servers) ) {
220 ?>
221 <table style="width: 100%;">
222 <thead><th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th></thead>
223 <tbody>
224 <?php
225                 asort($servers);
226                 foreach ( $servers as $ip => $status ) {
227                         $color = ( $status ? '#2d2' : '#d22');
228         ?>
229                 <tr>
230                 <td><?php echo htmlspecialchars($ip); ?></td>
231                 <td style="padding: 0 .5em; font-weight:bold; color: #fff; background-color: <?php echo $color; ?>"><?php echo ($status ? __('No problems') : __('Obstructed') ); ?></td>
232                 
233         <?php
234                 }
235         }
236 ?>
237 </tbody>
238 </table>
239         <p><?php if ( get_option('akismet_connectivity_time') ) echo sprintf( __('Last checked %s ago.'), human_time_diff( get_option('akismet_connectivity_time') ) ); ?></p>
240         <p class="submit"><input type="submit" name="check" value="<?php _e('Check network status &raquo;'); ?>" /></p>
241 </form>
242
243 </div>
244 </div>
245 <?php
246 }
247
248 function akismet_stats_page() {
249         if ( function_exists('add_submenu_page') )
250                 add_submenu_page('index.php', __('Akismet Stats'), __('Akismet Stats'), 'manage_options', 'akismet-stats-display', 'akismet_stats_display');
251
252 }
253
254 function akismet_stats_script() {
255         ?>
256 <script type="text/javascript">
257 function resizeIframe() {
258     var height = document.documentElement.clientHeight;
259     height -= document.getElementById('akismet-stats-frame').offsetTop;
260     height += 100; // magic padding
261     
262     document.getElementById('akismet-stats-frame').style.height = height +"px";
263     
264 };
265 function resizeIframeInit() {
266         document.getElementById('akismet-stats-frame').onload = resizeIframe;
267         window.onresize = resizeIframe;
268 }
269 addLoadEvent(resizeIframeInit);
270 </script><?php
271 }
272
273
274 function akismet_stats_display() {
275         global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
276         $blog = urlencode( get_option('home') );
277         $url = "http://".akismet_get_key().".web.akismet.com/1.0/user-stats.php?blog={$blog}";
278         ?>
279         <div class="wrap">
280         <iframe src="<?php echo $url; ?>" width="100%" height="100%" frameborder="0" id="akismet-stats-frame"></iframe>
281         </div>
282         <?php
283 }
284
285 function akismet_stats() {
286         if ( !function_exists('did_action') || did_action( 'rightnow_end' ) ) // We already displayed this info in the "Right Now" section
287                 return;
288         if ( !$count = get_option('akismet_spam_count') )
289                 return;
290         $path = plugin_basename(__FILE__);
291         echo '<h3>'.__('Spam').'</h3>';
292         global $submenu;
293         if ( isset( $submenu['edit-comments.php'] ) )
294                 $link = 'edit-comments.php';
295         else
296                 $link = 'edit.php';
297         echo '<p>'.sprintf(__('<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.'), 'http://akismet.com/', clean_url("$link?page=akismet-admin"), number_format_i18n($count) ).'</p>';
298 }
299 add_action('activity_box_end', 'akismet_stats');
300
301 function akismet_get_key() {
302         global $wpcom_api_key;
303         if ( !empty($wpcom_api_key) )
304                 return $wpcom_api_key;
305         return get_option('wordpress_api_key');
306 }
307
308 function akismet_verify_key( $key, $ip = null ) {
309         global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
310         $blog = urlencode( get_option('home') );
311         if ( $wpcom_api_key )
312                 $key = $wpcom_api_key;
313         $response = akismet_http_post("key=$key&blog=$blog", 'rest.akismet.com', '/1.1/verify-key', $akismet_api_port, $ip);
314         if ( !is_array($response) || !isset($response[1]) || $response[1] != 'valid' && $response[1] != 'invalid' )
315                 return 'failed';
316         return $response[1];
317 }
318
319 // Check connectivity between the WordPress blog and Akismet's servers.
320 // Returns an associative array of server IP addresses, where the key is the IP address, and value is true (available) or false (unable to connect).
321 function akismet_check_server_connectivity() {
322         global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
323         
324         $test_host = 'rest.akismet.com';
325         
326         // Some web hosts may disable one or both functions
327         if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') )
328                 return array();
329         
330         $ips = gethostbynamel($test_host);
331         if ( !$ips || !is_array($ips) || !count($ips) )
332                 return array();
333                 
334         $servers = array();
335         foreach ( $ips as $ip ) {
336                 $response = akismet_verify_key( akismet_get_key(), $ip );
337                 // even if the key is invalid, at least we know we have connectivity
338                 if ( $response == 'valid' || $response == 'invalid' )
339                         $servers[$ip] = true;
340                 else
341                         $servers[$ip] = false;
342         }
343
344         return $servers;
345 }
346
347 // Check the server connectivity and store the results in an option.
348 // Cached results will be used if not older than the specified timeout in seconds; use $cache_timeout = 0 to force an update.
349 // Returns the same associative array as akismet_check_server_connectivity()
350 function akismet_get_server_connectivity( $cache_timeout = 86400 ) {
351         $servers = get_option('akismet_available_servers');
352         if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false )
353                 return $servers;
354         
355         // There's a race condition here but the effect is harmless.
356         $servers = akismet_check_server_connectivity();
357         update_option('akismet_available_servers', $servers);
358         update_option('akismet_connectivity_time', time());
359         return $servers;
360 }
361
362 // Returns true if server connectivity was OK at the last check, false if there was a problem that needs to be fixed.
363 function akismet_server_connectivity_ok() {
364         // skip the check on WPMU because the status page is hidden
365         global $wpcom_api_key;
366         if ( $wpcom_api_key )
367                 return true;
368         $servers = akismet_get_server_connectivity();
369         return !( empty($servers) || !count($servers) || count( array_filter($servers) ) < count($servers) );
370 }
371
372 function akismet_admin_warnings() {
373         global $wpcom_api_key;
374         if ( !get_option('wordpress_api_key') && !$wpcom_api_key && !isset($_POST['submit']) ) {
375                 function akismet_warning() {
376                         echo "
377                         <div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet is almost ready.')."</strong> ".sprintf(__('You must <a href="%1$s">enter your Akismet API key</a> for it to work.'), "plugins.php?page=akismet-key-config")."</p></div>
378                         ";
379                 }
380                 add_action('admin_notices', 'akismet_warning');
381                 return;
382         } elseif ( get_option('akismet_connectivity_time') && empty($_POST) && is_admin() && !akismet_server_connectivity_ok() ) {
383                 function akismet_warning() {
384                         echo "
385                         <div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet has detected a problem.')."</strong> ".sprintf(__('A server or network problem is preventing Akismet from working correctly.  <a href="%1$s">Click here for more information</a> about how to fix the problem.'), "plugins.php?page=akismet-key-config")."</p></div>
386                         ";
387                 }
388                 add_action('admin_notices', 'akismet_warning');
389                 return;
390         }
391 }
392
393 function akismet_get_host($host) {
394         // if all servers are accessible, just return the host name.
395         // if not, return an IP that was known to be accessible at the last check.
396         if ( akismet_server_connectivity_ok() ) {
397                 return $host;
398         } else {
399                 $ips = akismet_get_server_connectivity();
400                 // a firewall may be blocking access to some Akismet IPs
401                 if ( count($ips) > 0 && count(array_filter($ips)) < count($ips) ) {
402                         // use DNS to get current IPs, but exclude any known to be unreachable
403                         $dns = (array)gethostbynamel( rtrim($host, '.') . '.' );
404                         $dns = array_filter($dns);
405                         foreach ( $dns as $ip ) {
406                                 if ( array_key_exists( $ip, $ips ) && empty( $ips[$ip] ) )
407                                         unset($dns[$ip]);
408                         }
409                         // return a random IP from those available
410                         if ( count($dns) )
411                                 return $dns[ array_rand($dns) ];
412                         
413                 }
414         }
415         // if all else fails try the host name
416         return $host;
417 }
418
419 // return a comma-separated list of role names for the given user
420 function akismet_get_user_roles($user_id ) {
421         $roles = false;
422         
423         if ( !class_exists('WP_User') )
424                 return false;
425         
426         if ( $user_id > 0 ) {
427                 $comment_user = new WP_User($user_id);
428                 if ( isset($comment_user->roles) )
429                         $roles = join(',', $comment_user->roles);
430         }
431         
432         return $roles;
433 }
434
435 // Returns array with headers in $response[0] and body in $response[1]
436 function akismet_http_post($request, $host, $path, $port = 80, $ip=null) {
437         global $wp_version;
438         
439         $akismet_version = constant('AKISMET_VERSION');
440
441         $http_request  = "POST $path HTTP/1.0\r\n";
442         $http_request .= "Host: $host\r\n";
443         $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=" . get_option('blog_charset') . "\r\n";
444         $http_request .= "Content-Length: " . strlen($request) . "\r\n";
445         $http_request .= "User-Agent: WordPress/$wp_version | Akismet/$akismet_version\r\n";
446         $http_request .= "\r\n";
447         $http_request .= $request;
448         
449         $http_host = $host;
450         // use a specific IP if provided - needed by akismet_check_server_connectivity()
451         if ( $ip && long2ip(ip2long($ip)) ) {
452                 $http_host = $ip;
453         } else {
454                 $http_host = akismet_get_host($host);
455         }
456
457         $response = '';
458         if( false != ( $fs = @fsockopen($http_host, $port, $errno, $errstr, 10) ) ) {
459                 fwrite($fs, $http_request);
460
461                 while ( !feof($fs) )
462                         $response .= fgets($fs, 1160); // One TCP-IP packet
463                 fclose($fs);
464                 $response = explode("\r\n\r\n", $response, 2);
465         }
466         return $response;
467 }
468
469 // filter handler used to return a spam result to pre_comment_approved
470 function akismet_result_spam( $approved ) {
471         // bump the counter here instead of when the filter is added to reduce the possibility of overcounting
472         if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
473                 update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
474         return 'spam';
475 }
476
477 function akismet_auto_check_comment( $commentdata ) {
478         global $akismet_api_host, $akismet_api_port;
479
480         $comment = $commentdata;
481         $comment['user_ip']    = $_SERVER['REMOTE_ADDR'];
482         $comment['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
483         $comment['referrer']   = $_SERVER['HTTP_REFERER'];
484         $comment['blog']       = get_option('home');
485         $comment['blog_lang']  = get_locale();
486         $comment['blog_charset'] = get_option('blog_charset');
487         $comment['permalink']  = get_permalink($comment['comment_post_ID']);
488         
489         $comment['user_role'] = akismet_get_user_roles($comment['user_ID']);
490
491         $ignore = array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW' );
492
493         foreach ( $_SERVER as $key => $value )
494                 if ( !in_array( $key, $ignore ) && is_string($value) )
495                         $comment["$key"] = $value;
496                 else
497                         $comment["$key"] = '';
498
499         $query_string = '';
500         foreach ( $comment as $key => $data )
501                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
502
503         $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
504         $commentdata['akismet_result'] = $response[1];
505         if ( 'true' == $response[1] ) {
506                 // akismet_spam_count will be incremented later by akismet_result_spam()
507                 add_filter('pre_comment_approved', 'akismet_result_spam');
508
509                 do_action( 'akismet_spam_caught' );
510
511                 $post = get_post( $comment['comment_post_ID'] );
512                 $last_updated = strtotime( $post->post_modified_gmt );
513                 $diff = time() - $last_updated;
514                 $diff = $diff / 86400;
515                 
516                 if ( $post->post_type == 'post' && $diff > 30 && get_option( 'akismet_discard_month' ) == 'true' && empty($comment['user_ID']) ) {
517                         // akismet_result_spam() won't be called so bump the counter here
518                         if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
519                                 update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
520                         die;
521                 }
522         }
523         
524         if ( function_exists('wp_next_scheduled') && function_exists('wp_schedule_event') ) {
525                 // WP 2.1+: delete old comments daily
526                 if ( !wp_next_scheduled('akismet_scheduled_delete') )
527                         wp_schedule_event(time(), 'daily', 'akismet_scheduled_delete');
528         } elseif ( (mt_rand(1, 10) == 3) ) {
529                 // WP 2.0: run this one time in ten
530                 akismet_delete_old();
531         }
532         return $commentdata;
533 }
534
535 function akismet_delete_old() {
536         global $wpdb;
537         $now_gmt = current_time('mysql', 1);
538         $comment_ids = $wpdb->get_col("SELECT comment_id FROM $wpdb->comments WHERE DATE_SUB('$now_gmt', INTERVAL 15 DAY) > comment_date_gmt AND comment_approved = 'spam'");
539         if ( empty( $comment_ids ) )
540                 return;
541
542         do_action( 'delete_comment', $comment_ids );
543         $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_id IN ( " . implode( ', ', $comment_ids ) . " )");
544         $n = mt_rand(1, 5000);
545         if ( apply_filters('akismet_optimize_table', ($n == 11)) ) // lucky number
546                 $wpdb->query("OPTIMIZE TABLE $wpdb->comments");
547
548 }
549
550 add_action('akismet_scheduled_delete', 'akismet_delete_old');
551
552 function akismet_submit_nonspam_comment ( $comment_id ) {
553         global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
554         $comment_id = (int) $comment_id;
555
556         $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
557         if ( !$comment ) // it was deleted
558                 return;
559         $comment->blog = get_option('home');
560         $comment->blog_lang = get_locale();
561         $comment->blog_charset = get_option('blog_charset');
562         $comment->permalink = get_permalink($comment->comment_post_ID);
563         if ( is_object($current_user) ) {
564             $comment->reporter = $current_user->user_login;
565         }
566         if ( is_object($current_site) ) {
567                 $comment->site_domain = $current_site->domain;
568         }
569
570         $comment->user_role = '';
571         if ( isset( $comment->user_ID ) )
572                 $comment->user_role = akismet_get_user_roles($comment->user_ID);
573
574         $query_string = '';
575         foreach ( $comment as $key => $data )
576                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
577
578         $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-ham", $akismet_api_port);
579         do_action('akismet_submit_nonspam_comment', $comment_id, $response[1]);
580 }
581
582 function akismet_submit_spam_comment ( $comment_id ) {
583         global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
584         $comment_id = (int) $comment_id;
585
586         $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
587         if ( !$comment ) // it was deleted
588                 return;
589         if ( 'spam' != $comment->comment_approved )
590                 return;
591         $comment->blog = get_option('home');
592         $comment->blog_lang = get_locale();
593         $comment->blog_charset = get_option('blog_charset');
594         $comment->permalink = get_permalink($comment->comment_post_ID);
595         if ( is_object($current_user) ) {
596             $comment->reporter = $current_user->user_login;
597         }
598         if ( is_object($current_site) ) {
599                 $comment->site_domain = $current_site->domain;
600         }
601
602         $comment->user_role = '';
603         if ( !isset( $comment->user_id ) )
604                 $comment->user_role = akismet_get_user_roles($comment->user_ID);
605
606         $query_string = '';
607         foreach ( $comment as $key => $data )
608                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
609
610         $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-spam", $akismet_api_port);
611         do_action('akismet_submit_spam_comment', $comment_id, $response[1]);
612 }
613
614 add_action('preprocess_comment', 'akismet_auto_check_comment', 1);
615
616 // For old versions of WP only
617 function akismet_set_comment_status( $comment_id, $status ) {
618         if ( $status == 'spam' ) {
619                 akismet_submit_spam_comment( $comment_id );
620         } elseif ( $status == 'approve' ) {
621                 akismet_submit_nonspam_comment( $comment_id );
622         }
623 }
624
625 // For WP 2.7+
626 function akismet_transition_comment_status( $new_status, $old_status, $comment ) {
627         if ( $new_status == $old_status )
628                 return;
629
630         if ( $new_status == 'spam' ) {
631                 akismet_submit_spam_comment( $comment->comment_ID );
632         } elseif ( $old_status == 'spam' && ( $new_status == 'approved' || $new_status == 'unapproved' ) ) {
633                 akismet_submit_nonspam_comment( $comment->comment_ID );
634         }
635 }
636
637 function akismet_spamtoham( $comment ) { akismet_submit_nonspam_comment( $comment->comment_ID ); }
638
639 if ( function_exists( 'wp_transition_comment_status' ) ) {
640         add_action( 'transition_comment_status', 'akismet_transition_comment_status', 10, 3 );
641 } else {
642         add_action('wp_set_comment_status', 'akismet_set_comment_status', 10, 2);
643         add_action('edit_comment', 'akismet_submit_spam_comment');
644         add_filter( 'comment_spam_to_approved', 'akismet_spamtoham' );
645         add_filter( 'comment_spam_to_unapproved', 'akismet_spamtoham' );
646 }
647 // Total spam in queue
648 // get_option( 'akismet_spam_count' ) is the total caught ever
649 function akismet_spam_count( $type = false ) {
650         global $wpdb;
651
652         if ( !$type ) { // total
653                 $count = wp_cache_get( 'akismet_spam_count', 'widget' );
654                 if ( false === $count ) {
655                         if ( function_exists('wp_count_comments') ) {
656                                 $count = wp_count_comments();
657                                 $count = $count->spam;
658                         } else {
659                                 $count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'");
660                         }
661                         wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
662                 }
663                 return $count;
664         } elseif ( 'comments' == $type || 'comment' == $type ) { // comments
665                 $type = '';
666         } else { // pingback, trackback, ...
667                 $type  = $wpdb->escape( $type );
668         }
669
670         return (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type'");
671 }
672
673
674 // WP 2.5+
675 function akismet_rightnow() {
676         global $submenu, $wp_db_version;
677
678         // clean_url was deprecated in WP 3.0
679         $esc_url = 'clean_url';
680         if ( function_exists( 'esc_url' ) )
681                 $esc_url = 'esc_url';
682
683         if ( 8645 < $wp_db_version  ) // 2.7
684                 $link = 'edit-comments.php?comment_status=spam';
685         elseif ( isset( $submenu['edit-comments.php'] ) )
686                 $link = 'edit-comments.php?page=akismet-admin';
687         else
688                 $link = 'edit.php?page=akismet-admin';
689
690         if ( $count = get_option('akismet_spam_count') ) {
691                 $intro = sprintf( __ngettext(
692                         '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comment already,',
693                         '<a href="%1$s">Akismet</a> has protected your site from %2$s spam comments already,',
694                         $count
695                 ), 'http://akismet.com/', number_format_i18n( $count ) );
696         } else {
697                 $intro = sprintf( __('<a href="%1$s">Akismet</a> blocks spam from getting to your blog,'), 'http://akismet.com/' );
698         }
699
700         if ( $queue_count = akismet_spam_count() ) {
701                 $queue_text = sprintf( __ngettext(
702                         'and there\'s <a href="%2$s">%1$s comment</a> in your spam queue right now.',
703                         'and there are <a href="%2$s">%1$s comments</a> in your spam queue right now.',
704                         $queue_count
705                 ), number_format_i18n( $queue_count ), clean_url($link) );
706         } else {
707                 $queue_text = sprintf( __( "but there's nothing in your <a href='%1\$s'>spam queue</a> at the moment." ), $esc_url($link) );
708         }
709
710         // _c was deprecated in WP 2.9.0
711         if ( function_exists( '_x' ) )
712                 $text = sprintf( _x( '%1$s %2$s', 'akismet_rightnow' ), $intro, $queue_text );
713         else 
714                 $text = sprintf( _c( '%1$s %2$s|akismet_rightnow' ), $intro, $queue_text );
715
716         echo "<p class='akismet-right-now'>$text</p>\n";
717 }
718         
719 add_action('rightnow_end', 'akismet_rightnow');
720
721
722 // For WP >= 2.5
723 function akismet_check_for_spam_button($comment_status) {
724         if ( 'approved' == $comment_status )
725                 return;
726         if ( function_exists('plugins_url') )
727                 $link = 'admin.php?action=akismet_recheck_queue';
728         else
729                 $link = 'edit-comments.php?page=akismet-admin&amp;recheckqueue=true&amp;noheader=true';
730         echo "</div><div class='alignleft'><a class='button-secondary checkforspam' href='$link'>" . __('Check for Spam') . "</a>";
731 }
732 add_action('manage_comments_nav', 'akismet_check_for_spam_button');
733
734 function akismet_recheck_queue() {
735         global $wpdb, $akismet_api_host, $akismet_api_port;
736
737         if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
738                 return;
739
740         $moderation = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = '0'", ARRAY_A );
741         foreach ( (array) $moderation as $c ) {
742                 $c['user_ip']    = $c['comment_author_IP'];
743                 $c['user_agent'] = $c['comment_agent'];
744                 $c['referrer']   = '';
745                 $c['blog']       = get_option('home');
746                 $c['blog_lang']  = get_locale();
747                 $c['blog_charset'] = get_option('blog_charset');
748                 $c['permalink']  = get_permalink($c['comment_post_ID']);
749
750                 $c['user_role'] = '';
751                 if ( isset( $c['user_ID'] ) )
752                         $c['user_role']  = akismet_get_user_roles($c['user_ID']);
753
754                 $id = (int) $c['comment_ID'];
755
756                 $query_string = '';
757                 foreach ( $c as $key => $data )
758                 $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
759
760                 $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
761                 if ( 'true' == $response[1] ) {
762                         if ( function_exists('wp_set_comment_status') )
763                                 wp_set_comment_status($id, 'spam');
764                         else
765                                 $wpdb->query("UPDATE $wpdb->comments SET comment_approved = 'spam' WHERE comment_ID = $id");
766
767                 }
768         }
769         wp_redirect( $_SERVER['HTTP_REFERER'] );
770         exit;
771 }
772
773 add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
774
775 function akismet_check_db_comment( $id ) {
776         global $wpdb, $akismet_api_host, $akismet_api_port;
777
778         $id = (int) $id;
779         $c = $wpdb->get_row( "SELECT * FROM $wpdb->comments WHERE comment_ID = '$id'", ARRAY_A );
780         if ( !$c )
781                 return;
782
783         $c['user_ip']    = $c['comment_author_IP'];
784         $c['user_agent'] = $c['comment_agent'];
785         $c['referrer']   = '';
786         $c['blog']       = get_option('home');
787         $c['blog_lang']  = get_locale();
788         $c['blog_charset'] = get_option('blog_charset');
789         $c['permalink']  = get_permalink($c['comment_post_ID']);
790         $id = $c['comment_ID'];
791
792         $query_string = '';
793         foreach ( $c as $key => $data )
794         $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
795
796         $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
797         return $response[1];
798 }
799
800 // Widget stuff
801 function widget_akismet_register() {
802         if ( function_exists('register_sidebar_widget') ) :
803         function widget_akismet($args) {
804                 extract($args);
805                 $options = get_option('widget_akismet');
806                 $count = number_format_i18n(get_option('akismet_spam_count'));
807                 ?>
808                         <?php echo $before_widget; ?>
809                                 <?php echo $before_title . $options['title'] . $after_title; ?>
810                                 <div id="akismetwrap"><div id="akismetstats"><a id="aka" href="http://akismet.com" title=""><?php printf( __( '%1$s %2$sspam comments%3$s %4$sblocked by%5$s<br />%6$sAkismet%7$s' ), '<span id="akismet1"><span id="akismetcount">' . $count . '</span>', '<span id="akismetsc">', '</span></span>', '<span id="akismet2"><span id="akismetbb">', '</span>', '<span id="akismeta">', '</span></span>' ); ?></a></div></div>
811                         <?php echo $after_widget; ?>
812         <?php
813         }
814
815         function widget_akismet_style() {
816                 $plugin_dir = '/wp-content/plugins';
817                 if ( defined( 'PLUGINDIR' ) )
818                         $plugin_dir = '/' . PLUGINDIR;
819
820                 ?>
821 <style type="text/css">
822 #aka,#aka:link,#aka:hover,#aka:visited,#aka:active{color:#fff;text-decoration:none}
823 #aka:hover{border:none;text-decoration:none}
824 #aka:hover #akismet1{display:none}
825 #aka:hover #akismet2,#akismet1{display:block}
826 #akismet2{display:none;padding-top:2px}
827 #akismeta{font-size:16px;font-weight:bold;line-height:18px;text-decoration:none}
828 #akismetcount{display:block;font:15px Verdana,Arial,Sans-Serif;font-weight:bold;text-decoration:none}
829 #akismetwrap #akismetstats{background:url(<?php echo get_option('siteurl'), $plugin_dir; ?>/akismet/akismet.gif) no-repeat top left;border:none;color:#fff;font:11px 'Trebuchet MS','Myriad Pro',sans-serif;height:40px;line-height:100%;overflow:hidden;padding:8px 0 0;text-align:center;width:120px}
830 </style>
831                 <?php
832         }
833
834         function widget_akismet_control() {
835                 $options = $newoptions = get_option('widget_akismet');
836                 if ( isset( $_POST['akismet-submit'] ) && $_POST["akismet-submit"] ) {
837                         $newoptions['title'] = strip_tags(stripslashes($_POST["akismet-title"]));
838                         if ( empty($newoptions['title']) ) $newoptions['title'] = __('Spam Blocked');
839                 }
840                 if ( $options != $newoptions ) {
841                         $options = $newoptions;
842                         update_option('widget_akismet', $options);
843                 }
844                 $title = htmlspecialchars($options['title'], ENT_QUOTES);
845         ?>
846                                 <p><label for="akismet-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="akismet-title" name="akismet-title" type="text" value="<?php echo $title; ?>" /></label></p>
847                                 <input type="hidden" id="akismet-submit" name="akismet-submit" value="1" />
848         <?php
849         }
850
851         if ( function_exists( 'wp_register_sidebar_widget' ) ) {
852                 wp_register_sidebar_widget( 'akismet', 'Akismet', 'widget_akismet', null, 'akismet');
853                 wp_register_widget_control( 'akismet', 'Akismet', 'widget_akismet_control', null, 75, 'akismet');
854         } else {
855                 register_sidebar_widget('Akismet', 'widget_akismet', null, 'akismet');
856                 register_widget_control('Akismet', 'widget_akismet_control', null, 75, 'akismet');
857         }
858         if ( is_active_widget('widget_akismet') )
859                 add_action('wp_head', 'widget_akismet_style');
860         endif;
861 }
862
863 add_action('init', 'widget_akismet_register');
864
865 // Counter for non-widget users
866 function akismet_counter() {
867         $plugin_dir = '/wp-content/plugins';
868         if ( defined( 'PLUGINDIR' ) )
869                 $plugin_dir = '/' . PLUGINDIR;
870
871 ?>
872 <style type="text/css">
873 #akismetwrap #aka,#aka:link,#aka:hover,#aka:visited,#aka:active{color:#fff;text-decoration:none}
874 #aka:hover{border:none;text-decoration:none}
875 #aka:hover #akismet1{display:none}
876 #aka:hover #akismet2,#akismet1{display:block}
877 #akismet2{display:none;padding-top:2px}
878 #akismeta{font-size:16px;font-weight:bold;line-height:18px;text-decoration:none}
879 #akismetcount{display:block;font:15px Verdana,Arial,Sans-Serif;font-weight:bold;text-decoration:none}
880 #akismetwrap #akismetstats{background:url(<?php echo get_option('siteurl'), $plugin_dir; ?>/akismet/akismet.gif) no-repeat top left;border:none;color:#fff;font:11px 'Trebuchet MS','Myriad Pro',sans-serif;height:40px;line-height:100%;overflow:hidden;padding:8px 0 0;text-align:center;width:120px}
881 </style>
882 <?php
883 $count = number_format_i18n(get_option('akismet_spam_count'));
884 ?>
885 <div id="akismetwrap"><div id="akismetstats"><a id="aka" href="http://akismet.com" title=""><div id="akismet1"><span id="akismetcount"><?php echo $count; ?></span> <span id="akismetsc"><?php _e('spam comments') ?></span></div> <div id="akismet2"><span id="akismetbb"><?php _e('blocked by') ?></span><br /><span id="akismeta">Akismet</span></div></a></div></div>
886 <?php
887 }
888
889 ?>