PageRenderTime 4ms CodeModel.GetById 98ms app.highlight 211ms RepoModel.GetById 61ms app.codeStats 1ms

/wp-content/plugins/akismet/admin.php

https://bitbucket.org/space87/wordpressstart
PHP | 850 lines | 699 code | 114 blank | 37 comment | 198 complexity | 70bd9505b71270f8d514feb0929cbe8e MD5 | raw file
  1<?php
  2add_action( 'admin_menu', 'akismet_admin_menu' );
  3	
  4akismet_admin_warnings();
  5
  6function akismet_admin_init() {
  7    global $wp_version;
  8    
  9    // all admin functions are disabled in old versions
 10    if ( !function_exists('is_multisite') && version_compare( $wp_version, '3.0', '<' ) ) {
 11        
 12        function akismet_version_warning() {
 13            echo "
 14            <div id='akismet-warning' class='updated fade'><p><strong>".sprintf(__('Akismet %s requires WordPress 3.0 or higher.'), AKISMET_VERSION) ."</strong> ".sprintf(__('Please <a href="%s">upgrade WordPress</a> to a current version, or <a href="%s">downgrade to version 2.4 of the Akismet plugin</a>.'), 'http://codex.wordpress.org/Upgrading_WordPress', 'http://wordpress.org/extend/plugins/akismet/download/'). "</p></div>
 15            ";
 16        }
 17        add_action('admin_notices', 'akismet_version_warning'); 
 18        
 19        return; 
 20    }
 21
 22    if ( function_exists( 'get_plugin_page_hook' ) )
 23        $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
 24    else
 25        $hook = 'dashboard_page_akismet-stats-display';
 26    add_action('admin_head-'.$hook, 'akismet_stats_script');
 27    add_meta_box('akismet-status', __('Comment History'), 'akismet_comment_status_meta_box', 'comment', 'normal');
 28}
 29add_action('admin_init', 'akismet_admin_init');
 30
 31add_action( 'admin_enqueue_scripts', 'akismet_load_js_and_css' );
 32function akismet_load_js_and_css() {
 33	global $hook_suffix;
 34
 35	if (
 36		$hook_suffix == 'index.php'	# dashboard
 37		|| $hook_suffix == 'edit-comments.php' 
 38		|| $hook_suffix == 'comment.php' 
 39		|| $hook_suffix == 'post.php' 
 40		|| $hook_suffix == 'plugins_page_akismet-key-config'
 41	) {
 42		wp_register_style( 'akismet.css', AKISMET_PLUGIN_URL . 'akismet.css', array(), '2.5.4.4' );
 43		wp_enqueue_style( 'akismet.css');
 44	
 45		wp_register_script( 'akismet.js', AKISMET_PLUGIN_URL . 'akismet.js', array('jquery'), '2.5.4.6' );
 46		wp_enqueue_script( 'akismet.js' );
 47		wp_localize_script( 'akismet.js', 'WPAkismet', array(
 48			'comment_author_url_nonce' => wp_create_nonce( 'comment_author_url_nonce' )
 49		) );
 50	}
 51}
 52
 53
 54function akismet_nonce_field($action = -1) { return wp_nonce_field($action); }
 55$akismet_nonce = 'akismet-update-key';
 56
 57function akismet_plugin_action_links( $links, $file ) {
 58	if ( $file == plugin_basename( dirname(__FILE__).'/akismet.php' ) ) {
 59		$links[] = '<a href="admin.php?page=akismet-key-config">'.__('Settings').'</a>';
 60	}
 61
 62	return $links;
 63}
 64
 65add_filter( 'plugin_action_links', 'akismet_plugin_action_links', 10, 2 );
 66
 67function akismet_conf() {
 68	global $akismet_nonce, $wpcom_api_key;
 69
 70	if ( isset($_POST['submit']) ) {
 71		if ( function_exists('current_user_can') && !current_user_can('manage_options') )
 72			die(__('Cheatin&#8217; uh?'));
 73
 74		check_admin_referer( $akismet_nonce );
 75		$key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
 76		$home_url = parse_url( get_bloginfo('url') );
 77
 78		if ( empty($key) ) {
 79			$key_status = 'empty';
 80			$ms[] = 'new_key_empty';
 81			delete_option('wordpress_api_key');
 82		} elseif ( empty($home_url['host']) ) {
 83			$key_status = 'empty';
 84			$ms[] = 'bad_home_url';
 85		} else {
 86			$key_status = akismet_verify_key( $key );
 87		}
 88
 89		if ( $key_status == 'valid' ) {
 90			update_option('wordpress_api_key', $key);
 91			$ms[] = 'new_key_valid';
 92		} else if ( $key_status == 'invalid' ) {
 93			$ms[] = 'new_key_invalid';
 94		} else if ( $key_status == 'failed' ) {
 95			$ms[] = 'new_key_failed';
 96		}
 97
 98		if ( isset( $_POST['akismet_discard_month'] ) )
 99			update_option( 'akismet_discard_month', 'true' );
100		else
101			update_option( 'akismet_discard_month', 'false' );
102
103		if ( isset( $_POST['akismet_show_user_comments_approved'] ) )
104			update_option( 'akismet_show_user_comments_approved', 'true' );
105		else
106			update_option( 'akismet_show_user_comments_approved', 'false' );
107
108	} elseif ( isset($_POST['check']) ) {
109		akismet_get_server_connectivity(0);
110	}
111
112	if ( empty( $key_status) ||  $key_status != 'valid' ) {
113		$key = get_option('wordpress_api_key');
114		if ( empty( $key ) ) {
115			if ( empty( $key_status ) || $key_status != 'failed' ) {
116				if ( akismet_verify_key( '1234567890ab' ) == 'failed' )
117					$ms[] = 'no_connection';
118				else
119					$ms[] = 'key_empty';
120			}
121			$key_status = 'empty';
122		} else {
123			$key_status = akismet_verify_key( $key );
124		}
125		if ( $key_status == 'valid' ) {
126			$ms[] = 'key_valid';
127		} else if ( $key_status == 'invalid' ) {
128			$ms[] = 'key_invalid';
129		} else if ( !empty($key) && $key_status == 'failed' ) {
130			$ms[] = 'key_failed';
131		}
132	}
133
134	$messages = array(
135		'new_key_empty' => array('color' => 'aa0', 'text' => __('Your key has been cleared.')),
136		'new_key_valid' => array('color' => '4AB915', 'text' => __('Your key has been verified. Happy blogging!')),
137		'new_key_invalid' => array('color' => '888', 'text' => __('The key you entered is invalid. Please double-check it.')),
138		'new_key_failed' => array('color' => '888', 'text' => __('The key you entered could not be verified because a connection to akismet.com could not be established. Please check your server configuration.')),
139		'no_connection' => array('color' => '888', 'text' => __('There was a problem connecting to the Akismet server. Please check your server configuration.')),
140		'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/?return=true')),
141		'key_valid' => array('color' => '4AB915', 'text' => __('This key is valid.')),
142		'key_invalid' => array('color' => '888', 'text' => __('This key is invalid.')),
143		'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.')),
144		'bad_home_url' => array('color' => '888', 'text' => sprintf( __('Your WordPress home URL %s is invalid.  Please fix the <a href="%s">home option</a>.'), esc_html( get_bloginfo('url') ), admin_url('options.php#home') ) ),
145	);
146?>
147<?php if ( !empty($_POST['submit'] ) ) : ?>
148<div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
149<?php endif; ?>
150<div class="wrap">
151<h2><?php _e('Akismet Configuration'); ?></h2>
152<?php if (isset($_GET['message']) && $_GET['message'] == 'success') { ?>
153	<div class="updated below-h2" id="message"><p><?php _e( '<strong>Sign up success!</strong> Please check your email for your Akismet API Key and enter it below.' ); ?></p></div>
154<?php } ?>
155<div class="narrow">
156<form action="" method="post" id="akismet-conf" style="margin: auto; width: 400px; ">
157<?php if ( !$wpcom_api_key ) { ?>
158	<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/?return=true', 'http://akismet.com/get/?return=true'); ?></p>
159
160<h3><label for="key"><?php _e('Akismet API Key'); ?></label></h3>
161<?php foreach ( $ms as $m ) : ?>
162	<p style="padding: .5em; background-color: #<?php echo $messages[$m]['color']; ?>; color: #fff; font-weight: bold;"><?php echo $messages[$m]['text']; ?></p>
163<?php endforeach; ?>
164<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/?return=true">What is this?</a>'); ?>)</p>
165<?php if ( isset( $invalid_key) && $invalid_key ) { ?>
166<h3><?php _e('Why might my key be invalid?'); ?></h3>
167<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>
168<?php } ?>
169<?php } ?>
170<?php akismet_nonce_field($akismet_nonce) ?>
171<p><label><input name="akismet_discard_month" id="akismet_discard_month" value="true" type="checkbox" <?php if ( get_option('akismet_discard_month') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Auto-delete spam submitted on posts more than a month old.'); ?></label></p>
172<p><label><input name="akismet_show_user_comments_approved" id="akismet_show_user_comments_approved" value="true" type="checkbox" <?php if ( get_option('akismet_show_user_comments_approved') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Show the number of comments you\'ve approved beside each comment author.'); ?></label></p>
173	<p class="submit"><input type="submit" name="submit" value="<?php _e('Update options &raquo;'); ?>" /></p>
174</form>
175
176<form action="" method="post" id="akismet-connectivity" style="margin: auto; width: 400px; ">
177
178<h3><?php _e('Server Connectivity'); ?></h3>
179<?php
180	if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) {
181		?>
182			<p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Network functions are disabled.'); ?></p>
183			<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>
184		<?php
185	} else {
186		$servers = akismet_get_server_connectivity();
187		$fail_count = count($servers) - count( array_filter($servers) );
188		if ( is_array($servers) && count($servers) > 0 ) {
189			// some connections work, some fail
190			if ( $fail_count > 0 && $fail_count < count($servers) ) { ?>
191				<p style="padding: .5em; background-color: #aa0; color: #fff; font-weight:bold;"><?php _e('Unable to reach some Akismet servers.'); ?></p>
192				<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>
193			<?php
194			// all connections fail
195			} elseif ( $fail_count > 0 ) { ?>
196				<p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Unable to reach any Akismet servers.'); ?></p>
197				<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>
198			<?php
199			// all connections work
200			} else { ?>
201				<p style="padding: .5em; background-color: #4AB915; color: #fff; font-weight:bold;"><?php  _e('All Akismet servers are available.'); ?></p>
202				<p><?php _e('Akismet is working correctly.  All servers are accessible.'); ?></p>
203			<?php
204			}
205		} else {
206			?>
207				<p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Unable to find Akismet servers.'); ?></p>
208				<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>
209			<?php
210		}
211	}
212	
213	if ( !empty($servers) ) {
214?>
215<table style="width: 100%;">
216<thead><th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th></thead>
217<tbody>
218<?php
219		asort($servers);
220		foreach ( $servers as $ip => $status ) {
221			$color = ( $status ? '#4AB915' : '#888');
222	?>
223		<tr>
224		<td><?php echo htmlspecialchars($ip); ?></td>
225		<td style="padding: 0 .5em; font-weight:bold; color: #fff; background-color: <?php echo $color; ?>"><?php echo ($status ? __('Accessible') : __('Re-trying') ); ?></td>
226		
227	<?php
228		}
229	}
230?>
231</tbody>
232</table>
233	<p><?php if ( get_option('akismet_connectivity_time') ) echo sprintf( __('Last checked %s ago.'), human_time_diff( get_option('akismet_connectivity_time') ) ); ?></p>
234	<p class="submit"><input type="submit" name="check" value="<?php _e('Check network status &raquo;'); ?>" /></p>
235	<p><?php printf( __('<a href="%s" target="_blank">Click here</a> to confirm that <a href="%s" target="_blank">Akismet.com is up</a>.'), 'http://status.automattic.com/9931/136079/Akismet-API', 'http://status.automattic.com/9931/136079/Akismet-API' ); ?></p>
236</form>
237
238</div>
239</div>
240<?php
241}
242
243function akismet_stats_script() {
244	?>
245<script type="text/javascript">
246function resizeIframe() {
247  
248    document.getElementById('akismet-stats-frame').style.height = "2500px";
249    
250};
251function resizeIframeInit() {
252	document.getElementById('akismet-stats-frame').onload = resizeIframe;
253	window.onresize = resizeIframe;
254}
255addLoadEvent(resizeIframeInit);
256</script><?php
257}
258
259
260function akismet_stats_display() {
261	global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
262	$blog = urlencode( get_bloginfo('url') );
263
264	$url = 'http://';
265	if ( is_ssl() )
266		$url = 'https://';
267
268	$url .= 'akismet.com/web/1.0/user-stats.php';
269	$url .= "?blog={$blog}&api_key=" . akismet_get_key();
270	?>
271	<div class="wrap">
272	<iframe src="<?php echo $url; ?>" width="100%" height="100%" frameborder="0" id="akismet-stats-frame"></iframe>
273	</div>
274	<?php
275}
276
277function akismet_stats() {
278	if ( !function_exists('did_action') || did_action( 'rightnow_end' ) ) // We already displayed this info in the "Right Now" section
279		return;
280	if ( !$count = get_option('akismet_spam_count') )
281		return;
282	$path = plugin_basename(__FILE__);
283	echo '<h3>' . _x( 'Spam', 'comments' ) . '</h3>';
284	global $submenu;
285	if ( isset( $submenu['edit-comments.php'] ) )
286		$link = 'edit-comments.php';
287	else
288		$link = 'edit.php';
289	echo '<p>'.sprintf( _n( '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', '<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.', $count ), 'http://akismet.com/?return=true', clean_url("$link?page=akismet-admin"), number_format_i18n($count) ).'</p>';
290}
291add_action('activity_box_end', 'akismet_stats');
292
293function akismet_admin_warnings() {
294	global $wpcom_api_key, $pagenow;
295
296	if (
297		$pagenow == 'edit-comments.php'
298		|| ( !empty( $_GET['page'] ) && $_GET['page'] == 'akismet-key-config' )
299		|| ( !empty( $_GET['page'] ) && $_GET['page'] == 'akismet-stats-display' )
300	) {
301		if ( get_option( 'akismet_alert_code' ) ) {
302			function akismet_alert() {
303				$alert = array(
304					'code' => (int) get_option( 'akismet_alert_code' ),
305					'msg' => get_option( 'akismet_alert_msg' )
306				);
307			?>
308				<div class='error'>
309					<p><strong>Akismet Error Code: <?php echo $alert['code']; ?></strong></p>
310					<p><?php esc_html_e( $alert['msg'] ); ?></p>
311					<p>More information is available at <a href="https://akismet.com/errors/<?php echo $alert['code']; ?>">https://akismet.com/errors/<?php echo $alert['code']; ?></a></p>
312				</div>
313			<?php
314			}
315
316			add_action( 'admin_notices', 'akismet_alert' );
317		}
318	}
319
320	if ( !get_option('wordpress_api_key') && !$wpcom_api_key && !isset($_POST['submit']) ) {
321		function akismet_warning() {
322			echo "
323			<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.'), "admin.php?page=akismet-key-config")."</p></div>
324			";
325		}
326		add_action('admin_notices', 'akismet_warning');
327		return;
328	} elseif ( ( empty($_SERVER['SCRIPT_FILENAME']) || basename($_SERVER['SCRIPT_FILENAME']) == 'edit-comments.php' ) &&  wp_next_scheduled('akismet_schedule_cron_recheck') ) {
329		function akismet_warning() {
330			global $wpdb;
331				akismet_fix_scheduled_recheck();
332				$waiting = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->commentmeta WHERE meta_key = 'akismet_error'" ) );
333				$next_check = wp_next_scheduled('akismet_schedule_cron_recheck');
334				if ( $waiting > 0 && $next_check > time() )
335					echo "
336			<div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet has detected a problem.')."</strong> ".sprintf(__('Some comments have not yet been checked for spam by Akismet. They have been temporarily held for moderation. Please check your <a href="%s">Akismet configuration</a> and contact your web host if problems persist.'), 'admin.php?page=akismet-key-config')."</p></div>
337			";
338		}
339		add_action('admin_notices', 'akismet_warning');
340		return;
341	}
342}
343
344// FIXME placeholder
345
346function akismet_comment_row_action( $a, $comment ) {
347
348	// failsafe for old WP versions
349	if ( !function_exists('add_comment_meta') )
350		return $a;
351
352	$akismet_result = get_comment_meta( $comment->comment_ID, 'akismet_result', true );
353	$akismet_error = get_comment_meta( $comment->comment_ID, 'akismet_error', true );
354	$user_result = get_comment_meta( $comment->comment_ID, 'akismet_user_result', true);
355	$comment_status = wp_get_comment_status( $comment->comment_ID );
356	$desc = null;
357	if ( $akismet_error ) {
358		$desc = __( 'Awaiting spam check' );
359	} elseif ( !$user_result || $user_result == $akismet_result ) {
360		// Show the original Akismet result if the user hasn't overridden it, or if their decision was the same
361		if ( $akismet_result == 'true' && $comment_status != 'spam' && $comment_status != 'trash' )
362			$desc = __( 'Flagged as spam by Akismet' );
363		elseif ( $akismet_result == 'false' && $comment_status == 'spam' )
364			$desc = __( 'Cleared by Akismet' );
365	} else {
366		$who = get_comment_meta( $comment->comment_ID, 'akismet_user', true );
367		if ( $user_result == 'true' )
368			$desc = sprintf( __('Flagged as spam by %s'), $who );
369		else
370			$desc = sprintf( __('Un-spammed by %s'), $who );
371	}
372
373	// add a History item to the hover links, just after Edit
374	if ( $akismet_result ) {
375		$b = array();
376		foreach ( $a as $k => $item ) {
377			$b[ $k ] = $item;
378			if (
379				$k == 'edit'
380				|| ( $k == 'unspam' && $GLOBALS['wp_version'] >= 3.4 )
381			) {
382				$b['history'] = '<a href="comment.php?action=editcomment&amp;c='.$comment->comment_ID.'#akismet-status" title="'. esc_attr__( 'View comment history' ) . '"> '. __('History') . '</a>';
383			}
384		}
385		
386		$a = $b;
387	}
388		
389	if ( $desc )
390		echo '<span class="akismet-status" commentid="'.$comment->comment_ID.'"><a href="comment.php?action=editcomment&amp;c='.$comment->comment_ID.'#akismet-status" title="' . esc_attr__( 'View comment history' ) . '">'.htmlspecialchars($desc).'</a></span>';
391		
392	if ( apply_filters( 'akismet_show_user_comments_approved', get_option('akismet_show_user_comments_approved') ) == 'true' ) {
393		$comment_count = akismet_get_user_comments_approved( $comment->user_id, $comment->comment_author_email, $comment->comment_author, $comment->comment_author_url );
394		$comment_count = intval( $comment_count );
395		echo '<span class="akismet-user-comment-count" commentid="'.$comment->comment_ID.'" style="display:none;"><br><span class="akismet-user-comment-counts">'.sprintf( _n( '%s approved', '%s approved', $comment_count ), number_format_i18n( $comment_count ) ) . '</span></span>';
396	}
397	
398	return $a;
399}
400
401add_filter( 'comment_row_actions', 'akismet_comment_row_action', 10, 2 );
402
403function akismet_comment_status_meta_box($comment) {
404	$history = akismet_get_comment_history( $comment->comment_ID );
405
406	if ( $history ) {
407		echo '<div class="akismet-history" style="margin: 13px;">';
408		foreach ( $history as $row ) {
409			$time = date( 'D d M Y @ h:i:m a', $row['time'] ) . ' GMT';
410			echo '<div style="margin-bottom: 13px;"><span style="color: #999;" alt="' . $time . '" title="' . $time . '">' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '</span> - ';
411			echo htmlspecialchars( $row['message'] ) . '</div>';
412		}
413		
414		echo '</div>';
415
416	}
417}
418
419
420// add an extra column header to the comments screen
421function akismet_comments_columns( $columns ) {
422	$columns[ 'akismet' ] = __( 'Akismet' );
423	return $columns;
424}
425
426#add_filter( 'manage_edit-comments_columns', 'akismet_comments_columns' );
427
428// Show stuff in the extra column
429function akismet_comment_column_row( $column, $comment_id ) {
430	if ( $column != 'akismet' )
431		return;
432		
433	$history = akismet_get_comment_history( $comment_id );
434	
435	if ( $history ) {
436		echo '<dl class="akismet-history">';
437		foreach ( $history as $row ) {
438			echo '<dt>' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '</dt>';
439			echo '<dd>' . htmlspecialchars( $row['message'] ) . '</dd>';
440		}
441		
442		echo '</dl>';
443	}
444}
445
446#add_action( 'manage_comments_custom_column', 'akismet_comment_column_row', 10, 2 );
447
448// END FIXME
449
450// call out URLS in comments
451function akismet_text_add_link_callback( $m ) {
452	
453		// bare link?
454        if ( $m[4] == $m[2] )
455                return '<a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a>';
456        else
457                return '<span title="'.$m[2].'" class="comment-link"><a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a></span>';
458}
459
460function akismet_text_add_link_class( $comment_text ) {
461
462        return preg_replace_callback( '#<a ([^>]*)href="([^"]+)"([^>]*)>(.*?)</a>#i', 'akismet_text_add_link_callback', $comment_text );
463}
464
465add_filter('comment_text', 'akismet_text_add_link_class');
466
467
468// WP 2.5+
469function akismet_rightnow() {
470	global $submenu, $wp_db_version;
471
472	if ( 8645 < $wp_db_version  ) // 2.7
473		$link = 'edit-comments.php?comment_status=spam';
474	elseif ( isset( $submenu['edit-comments.php'] ) )
475		$link = 'edit-comments.php?page=akismet-admin';
476	else
477		$link = 'edit.php?page=akismet-admin';
478
479	if ( $count = get_option('akismet_spam_count') ) {
480		$intro = sprintf( _n(
481			'<a href="%1$s">Akismet</a> has protected your site from %2$s spam comment already. ',
482			'<a href="%1$s">Akismet</a> has protected your site from %2$s spam comments already. ',
483			$count
484		), 'http://akismet.com/?return=true', number_format_i18n( $count ) );
485	} else {
486		$intro = sprintf( __('<a href="%1$s">Akismet</a> blocks spam from getting to your blog. '), 'http://akismet.com/?return=true' );
487	}
488
489	$link = function_exists( 'esc_url' ) ? esc_url( $link ) : clean_url( $link );
490	if ( $queue_count = akismet_spam_count() ) {
491		$queue_text = sprintf( _n(
492			'There\'s <a href="%2$s">%1$s comment</a> in your spam queue right now.',
493			'There are <a href="%2$s">%1$s comments</a> in your spam queue right now.',
494			$queue_count
495		), number_format_i18n( $queue_count ), $link );
496	} else {
497		$queue_text = sprintf( __( "There's nothing in your <a href='%1\$s'>spam queue</a> at the moment." ), $link );
498	}
499
500	$text = $intro . '<br />' . $queue_text;
501	echo "<p class='akismet-right-now'>$text</p>\n";
502}
503	
504add_action('rightnow_end', 'akismet_rightnow');
505
506
507// For WP >= 2.5
508function akismet_check_for_spam_button($comment_status) {
509	if ( 'approved' == $comment_status )
510		return;
511	if ( function_exists('plugins_url') )
512		$link = 'admin.php?action=akismet_recheck_queue';
513	else
514		$link = 'edit-comments.php?page=akismet-admin&amp;recheckqueue=true&amp;noheader=true';
515	echo "</div><div class='alignleft'><a class='button-secondary checkforspam' href='$link'>" . __('Check for Spam') . "</a>";
516}
517add_action('manage_comments_nav', 'akismet_check_for_spam_button');
518
519function akismet_submit_nonspam_comment ( $comment_id ) {
520	global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
521	$comment_id = (int) $comment_id;
522
523	$comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
524	if ( !$comment ) // it was deleted
525		return;
526		
527	// use the original version stored in comment_meta if available	
528	$as_submitted = get_comment_meta( $comment_id, 'akismet_as_submitted', true);
529	if ( $as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content']) ) {
530		$comment = (object) array_merge( (array)$comment, $as_submitted );
531	}
532	
533	$comment->blog = get_bloginfo('url');
534	$comment->blog_lang = get_locale();
535	$comment->blog_charset = get_option('blog_charset');
536	$comment->permalink = get_permalink($comment->comment_post_ID);
537	$comment->reporter_ip = $_SERVER['REMOTE_ADDR'];
538	if ( is_object($current_user) ) {
539	    $comment->reporter = $current_user->user_login;
540	}
541	if ( is_object($current_site) ) {
542		$comment->site_domain = $current_site->domain;
543	}
544
545	$comment->user_role = '';
546	if ( isset( $comment->user_ID ) )
547		$comment->user_role = akismet_get_user_roles($comment->user_ID);
548
549	if ( akismet_test_mode() )
550		$comment->is_test = 'true';
551
552	$post = get_post( $comment->comment_post_ID );
553	$comment->comment_post_modified_gmt = $post->post_modified_gmt;
554
555	$query_string = '';
556	foreach ( $comment as $key => $data )
557		$query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
558
559	$response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-ham", $akismet_api_port);
560	if ( $comment->reporter ) {
561		akismet_update_comment_history( $comment_id, sprintf( __('%s reported this comment as not spam'), $comment->reporter ), 'report-ham' );
562		update_comment_meta( $comment_id, 'akismet_user_result', 'false' );
563		update_comment_meta( $comment_id, 'akismet_user', $comment->reporter );
564	}
565	
566	do_action('akismet_submit_nonspam_comment', $comment_id, $response[1]);
567}
568
569function akismet_submit_spam_comment ( $comment_id ) {
570	global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site;
571	$comment_id = (int) $comment_id;
572
573	$comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'");
574	if ( !$comment ) // it was deleted
575		return;
576	if ( 'spam' != $comment->comment_approved )
577		return;
578	
579	// use the original version stored in comment_meta if available	
580	$as_submitted = get_comment_meta( $comment_id, 'akismet_as_submitted', true);
581	if ( $as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content']) ) {
582		$comment = (object) array_merge( (array)$comment, $as_submitted );
583	}
584	
585	$comment->blog = get_bloginfo('url');
586	$comment->blog_lang = get_locale();
587	$comment->blog_charset = get_option('blog_charset');
588	$comment->permalink = get_permalink($comment->comment_post_ID);
589	$comment->reporter_ip = $_SERVER['REMOTE_ADDR'];
590	if ( is_object($current_user) ) {
591	    $comment->reporter = $current_user->user_login;
592	}
593	if ( is_object($current_site) ) {
594		$comment->site_domain = $current_site->domain;
595	}
596
597	$comment->user_role = '';
598	if ( isset( $comment->user_ID ) )
599		$comment->user_role = akismet_get_user_roles($comment->user_ID);
600
601	if ( akismet_test_mode() )
602		$comment->is_test = 'true';
603
604	$post = get_post( $comment->comment_post_ID );
605	$comment->comment_post_modified_gmt = $post->post_modified_gmt;
606
607	$query_string = '';
608	foreach ( $comment as $key => $data )
609		$query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
610
611	$response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-spam", $akismet_api_port);
612	if ( $comment->reporter ) {
613		akismet_update_comment_history( $comment_id, sprintf( __('%s reported this comment as spam'), $comment->reporter ), 'report-spam' );
614		update_comment_meta( $comment_id, 'akismet_user_result', 'true' );
615		update_comment_meta( $comment_id, 'akismet_user', $comment->reporter );
616	}
617	do_action('akismet_submit_spam_comment', $comment_id, $response[1]);
618}
619
620// For WP 2.7+
621function akismet_transition_comment_status( $new_status, $old_status, $comment ) {
622	if ( $new_status == $old_status )
623		return;
624
625	# we don't need to record a history item for deleted comments
626	if ( $new_status == 'delete' )
627		return;
628		
629	if ( !is_admin() )
630		return;
631		
632	if ( !current_user_can( 'edit_post', $comment->comment_post_ID ) && !current_user_can( 'moderate_comments' ) )
633		return;
634
635	if ( defined('WP_IMPORTING') && WP_IMPORTING == true )
636		return;
637
638	// if this is present, it means the status has been changed by a re-check, not an explicit user action
639	if ( get_comment_meta( $comment->comment_ID, 'akismet_rechecking' ) )
640		return;
641		
642	global $current_user;
643	$reporter = '';
644	if ( is_object( $current_user ) )
645		$reporter = $current_user->user_login;
646	
647	// Assumption alert:
648	// We want to submit comments to Akismet only when a moderator explicitly spams or approves it - not if the status
649	// is changed automatically by another plugin.  Unfortunately WordPress doesn't provide an unambiguous way to
650	// determine why the transition_comment_status action was triggered.  And there are several different ways by which
651	// to spam and unspam comments: bulk actions, ajax, links in moderation emails, the dashboard, and perhaps others.
652	// We'll assume that this is an explicit user action if POST or GET has an 'action' key.
653	if ( isset($_POST['action']) || isset($_GET['action']) ) {
654		if ( $new_status == 'spam' && ( $old_status == 'approved' || $old_status == 'unapproved' || !$old_status ) ) {
655				return akismet_submit_spam_comment( $comment->comment_ID );
656		} elseif ( $old_status == 'spam' && ( $new_status == 'approved' || $new_status == 'unapproved' ) ) {
657				return akismet_submit_nonspam_comment( $comment->comment_ID );
658		}
659	}
660	
661	akismet_update_comment_history( $comment->comment_ID, sprintf( __('%s changed the comment status to %s'), $reporter, $new_status ), 'status-' . $new_status );
662}
663
664add_action( 'transition_comment_status', 'akismet_transition_comment_status', 10, 3 );
665
666// Total spam in queue
667// get_option( 'akismet_spam_count' ) is the total caught ever
668function akismet_spam_count( $type = false ) {
669	global $wpdb;
670
671	if ( !$type ) { // total
672		$count = wp_cache_get( 'akismet_spam_count', 'widget' );
673		if ( false === $count ) {
674			if ( function_exists('wp_count_comments') ) {
675				$count = wp_count_comments();
676				$count = $count->spam;
677			} else {
678				$count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'");
679			}
680			wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 );
681		}
682		return $count;
683	} elseif ( 'comments' == $type || 'comment' == $type ) { // comments
684		$type = '';
685	} else { // pingback, trackback, ...
686		$type  = $wpdb->escape( $type );
687	}
688
689	return (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type'");
690}
691
692
693function akismet_recheck_queue() {
694	global $wpdb, $akismet_api_host, $akismet_api_port;
695
696	akismet_fix_scheduled_recheck();
697
698	if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) )
699		return;
700		
701	$moderation = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = '0'", ARRAY_A );
702	foreach ( (array) $moderation as $c ) {
703		$c['user_ip']    = $c['comment_author_IP'];
704		$c['user_agent'] = $c['comment_agent'];
705		$c['referrer']   = '';
706		$c['blog']       = get_bloginfo('url');
707		$c['blog_lang']  = get_locale();
708		$c['blog_charset'] = get_option('blog_charset');
709		$c['permalink']  = get_permalink($c['comment_post_ID']);
710
711		$c['user_role'] = '';
712		if ( isset( $c['user_ID'] ) )
713			$c['user_role']  = akismet_get_user_roles($c['user_ID']);
714
715		if ( akismet_test_mode() )
716			$c['is_test'] = 'true';
717
718		$id = (int) $c['comment_ID'];
719
720		$query_string = '';
721		foreach ( $c as $key => $data )
722		$query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
723
724		add_comment_meta( $c['comment_ID'], 'akismet_rechecking', true );
725		$response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
726		if ( 'true' == $response[1] ) {
727			wp_set_comment_status($c['comment_ID'], 'spam');
728			update_comment_meta( $c['comment_ID'], 'akismet_result', 'true' );
729			delete_comment_meta( $c['comment_ID'], 'akismet_error' );
730			akismet_update_comment_history( $c['comment_ID'], __('Akismet re-checked and caught this comment as spam'), 'check-spam' );
731		
732		} elseif ( 'false' == $response[1] ) {
733			update_comment_meta( $c['comment_ID'], 'akismet_result', 'false' );
734			delete_comment_meta( $c['comment_ID'], 'akismet_error' );
735			akismet_update_comment_history( $c['comment_ID'], __('Akismet re-checked and cleared this comment'), 'check-ham' );
736		// abnormal result: error
737		} else {
738			update_comment_meta( $c['comment_ID'], 'akismet_result', 'error' );
739			akismet_update_comment_history( $c['comment_ID'], sprintf( __('Akismet was unable to re-check this comment (response: %s)'), substr($response[1], 0, 50)), 'check-error' );
740		}
741
742		delete_comment_meta( $c['comment_ID'], 'akismet_rechecking' );
743	}
744	wp_safe_redirect( $_SERVER['HTTP_REFERER'] );
745	exit;
746}
747
748add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue');
749
750// Adds an 'x' link next to author URLs, clicking will remove the author URL and show an undo link
751function akismet_remove_comment_author_url() {
752    if ( !empty($_POST['id'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) {
753        global $wpdb;
754        $comment = get_comment( intval($_POST['id']), ARRAY_A );
755        if (current_user_can('edit_comment', $comment['comment_ID'])) {
756            $comment['comment_author_url'] = '';
757            do_action( 'comment_remove_author_url' );
758            print(wp_update_comment( $comment ));
759            die();
760        }
761    }
762}
763
764add_action('wp_ajax_comment_author_deurl', 'akismet_remove_comment_author_url');
765
766function akismet_add_comment_author_url() {
767    if ( !empty( $_POST['id'] ) && !empty( $_POST['url'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) {
768        global $wpdb;
769        $comment = get_comment( intval($_POST['id']), ARRAY_A );
770        if (current_user_can('edit_comment', $comment['comment_ID'])) {
771            $comment['comment_author_url'] = esc_url($_POST['url']);
772            do_action( 'comment_add_author_url' );
773            print(wp_update_comment( $comment ));
774            die();
775        }
776    }
777}
778
779add_action('wp_ajax_comment_author_reurl', 'akismet_add_comment_author_url');
780
781// Check connectivity between the WordPress blog and Akismet's servers.
782// 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).
783function akismet_check_server_connectivity() {
784	global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
785	
786	$test_host = 'rest.akismet.com';
787	
788	// Some web hosts may disable one or both functions
789	if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') )
790		return array();
791	
792	$ips = gethostbynamel($test_host);
793	if ( !$ips || !is_array($ips) || !count($ips) )
794		return array();
795		
796	$servers = array();
797	foreach ( $ips as $ip ) {
798		$response = akismet_verify_key( akismet_get_key(), $ip );
799		// even if the key is invalid, at least we know we have connectivity
800		if ( $response == 'valid' || $response == 'invalid' )
801			$servers[$ip] = true;
802		else
803			$servers[$ip] = false;
804	}
805
806	return $servers;
807}
808
809// Check the server connectivity and store the results in an option.
810// Cached results will be used if not older than the specified timeout in seconds; use $cache_timeout = 0 to force an update.
811// Returns the same associative array as akismet_check_server_connectivity()
812function akismet_get_server_connectivity( $cache_timeout = 86400 ) {
813	$servers = get_option('akismet_available_servers');
814	if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false )
815		return $servers;
816	
817	// There's a race condition here but the effect is harmless.
818	$servers = akismet_check_server_connectivity();
819	update_option('akismet_available_servers', $servers);
820	update_option('akismet_connectivity_time', time());
821	return $servers;
822}
823
824// Returns true if server connectivity was OK at the last check, false if there was a problem that needs to be fixed.
825function akismet_server_connectivity_ok() {
826	// skip the check on WPMU because the status page is hidden
827	global $wpcom_api_key;
828	if ( $wpcom_api_key )
829		return true;
830	$servers = akismet_get_server_connectivity();
831	return !( empty($servers) || !count($servers) || count( array_filter($servers) ) < count($servers) );
832}
833
834function akismet_admin_menu() {
835	if ( class_exists( 'Jetpack' ) ) {
836		add_action( 'jetpack_admin_menu', 'akismet_load_menu' );
837	} else {
838		akismet_load_menu();
839	}
840}
841
842function akismet_load_menu() {
843	if ( class_exists( 'Jetpack' ) ) {
844		add_submenu_page( 'jetpack', __( 'Akismet Configuration' ), __( 'Akismet Configuration' ), 'manage_options', 'akismet-key-config', 'akismet_conf' );
845		add_submenu_page( 'jetpack', __( 'Akismet Stats' ), __( 'Akismet Stats' ), 'manage_options', 'akismet-stats-display', 'akismet_stats_display' );
846	} else {
847		add_submenu_page('plugins.php', __('Akismet Configuration'), __('Akismet Configuration'), 'manage_options', 'akismet-key-config', 'akismet_conf');
848		add_submenu_page('index.php', __('Akismet Stats'), __('Akismet Stats'), 'manage_options', 'akismet-stats-display', 'akismet_stats_display');
849	}
850}