web/wp-content/plugins/akismet/admin.php
changeset 194 32102edaa81b
child 204 09a1c134465b
equal deleted inserted replaced
193:2f6f6f7551ca 194:32102edaa81b
       
     1 <?php
       
     2 add_action( 'admin_menu', 'akismet_admin_menu' );
       
     3 	
       
     4 akismet_admin_warnings();
       
     5 
       
     6 function akismet_admin_init() {
       
     7     global $wp_version;
       
     8     
       
     9     // all admin functions are disabled in old versions
       
    10     if ( !function_exists('is_multisite') && version_compare( $wp_version, '3.0', '<' ) ) {
       
    11         
       
    12         function akismet_version_warning() {
       
    13             echo "
       
    14             <div id='akismet-warning' class='updated fade'><p><strong>".sprintf(__('Akismet %s requires WordPress 3.0 or higher.'), AKISMET_VERSION) ."</strong> ".sprintf(__('Please <a href="%s">upgrade WordPress</a> to a current version, or <a href="%s">downgrade to version 2.4 of the Akismet plugin</a>.'), 'http://codex.wordpress.org/Upgrading_WordPress', 'http://wordpress.org/extend/plugins/akismet/download/'). "</p></div>
       
    15             ";
       
    16         }
       
    17         add_action('admin_notices', 'akismet_version_warning'); 
       
    18         
       
    19         return; 
       
    20     }
       
    21 
       
    22     if ( function_exists( 'get_plugin_page_hook' ) )
       
    23         $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
       
    24     else
       
    25         $hook = 'dashboard_page_akismet-stats-display';
       
    26     add_action('admin_head-'.$hook, 'akismet_stats_script');
       
    27     add_meta_box('akismet-status', __('Comment History'), 'akismet_comment_status_meta_box', 'comment', 'normal');
       
    28 }
       
    29 add_action('admin_init', 'akismet_admin_init');
       
    30 
       
    31 add_action( 'admin_enqueue_scripts', 'akismet_load_js_and_css' );
       
    32 function 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 
       
    54 function akismet_nonce_field($action = -1) { return wp_nonce_field($action); }
       
    55 $akismet_nonce = 'akismet-update-key';
       
    56 
       
    57 function 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 
       
    65 add_filter( 'plugin_action_links', 'akismet_plugin_action_links', 10, 2 );
       
    66 
       
    67 function 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 
       
   243 function akismet_stats_script() {
       
   244 	?>
       
   245 <script type="text/javascript">
       
   246 function resizeIframe() {
       
   247   
       
   248     document.getElementById('akismet-stats-frame').style.height = "2500px";
       
   249     
       
   250 };
       
   251 function resizeIframeInit() {
       
   252 	document.getElementById('akismet-stats-frame').onload = resizeIframe;
       
   253 	window.onresize = resizeIframe;
       
   254 }
       
   255 addLoadEvent(resizeIframeInit);
       
   256 </script><?php
       
   257 }
       
   258 
       
   259 
       
   260 function 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 
       
   277 function 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 }
       
   291 add_action('activity_box_end', 'akismet_stats');
       
   292 
       
   293 function 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 
       
   346 function 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 
       
   401 add_filter( 'comment_row_actions', 'akismet_comment_row_action', 10, 2 );
       
   402 
       
   403 function 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
       
   421 function 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
       
   429 function 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
       
   451 function 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 
       
   460 function 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 
       
   465 add_filter('comment_text', 'akismet_text_add_link_class');
       
   466 
       
   467 
       
   468 // WP 2.5+
       
   469 function 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 	
       
   504 add_action('rightnow_end', 'akismet_rightnow');
       
   505 
       
   506 
       
   507 // For WP >= 2.5
       
   508 function 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 }
       
   517 add_action('manage_comments_nav', 'akismet_check_for_spam_button');
       
   518 
       
   519 function 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 
       
   569 function 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+
       
   621 function 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 
       
   664 add_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
       
   668 function 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 
       
   693 function 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 
       
   748 add_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
       
   751 function 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 
       
   764 add_action('wp_ajax_comment_author_deurl', 'akismet_remove_comment_author_url');
       
   765 
       
   766 function 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 
       
   779 add_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).
       
   783 function 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()
       
   812 function 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.
       
   825 function 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 
       
   834 function 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 
       
   842 function 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 }