<?php
/*
Plugin Name: Geo-Captcha & Geo-Blacklist
Plugin URI: http://plugins.deformed-design.de
Description: Geo-Captcha shows a captcha image only to countries you don't trust. Geo-Blacklists allows you to disable comments for some countries.
Version: 1.0
Author: Deformed Design
Author URI: http://plugins.deformed-design.de
Min WP Version: 3.0
*/

/* This script uses GeoLite Country from MaxMind (http://www.maxmind.com) which is available under terms of GPL/LGPL */

/*  This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */


if (!class_exists('geo_capblack')) {
	if( !isset( $_SESSION ) ) {
		session_start();
	}
}

load_plugin_textdomain('geo-captcha-blacklist', WP_PLUGIN_DIR . '/geo-captcha-geo-blacklist/', dirname(plugin_basename(__FILE__)));

// Include pages
require_once(WP_PLUGIN_DIR . '/geo-captcha-geo-blacklist/geo-captcha-blacklist-pages.php');

if (!class_exists("GeoIP")) {
	require_once WP_PLUGIN_DIR . '/geo-captcha-geo-blacklist/geoip.inc';
}
	 
class geo_capblack {

	public $country_list = array();
	public $country_blacklist = array();
	
	function init() {
		global $wpdb, $table_prefix;
		if (isset($_GET['activate']) and $_GET['activate'] == 'true') {
			$tables = $wpdb->get_col('SHOW TABLES');
			if (!in_array($table_prefix . 'geo_capblack_stats', $tables)) {
				$this->install();
			} elseif (!in_array($table_prefix . 'geo_capblack_log', $tables)) {
				$this->install();
			}
		}

		// Create country list array
		$geo_capblack_legal = get_option('geo_capblack_legal');
		$legal_countries = explode("\n", $geo_capblack_legal);
		if(is_array($legal_countries)) {
			foreach($legal_countries as $country) {
				$country = trim($country);
				if($country !== '') {
					$this->country_list[] = $country;
				}
			}
		}
		
		$geo_capblack_black = get_option('geo_capblack_black');
		$black_countries = explode("\n", $geo_capblack_black);
		if(is_array($black_countries)) {
			foreach($black_countries as $bad_country) {
				$bad_country = trim($bad_country);
				if($bad_country !== '') {
					$this->country_blacklist[] = $bad_country;
				}
			}
		}
	}
	
	// Try to get the charset of the mysql tables
	function get_charset () {
		global $wpdb, $table_prefix;
		
		// Check Charset
		$charset_collate = '';
		if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') ) {
			if (!empty($wpdb->charset)) {
				$charset_collate .= sprintf(' DEFAULT CHARACTER SET %s', $wpdb->charset);
			}
			if (!empty($wpdb->collate)) {
				$charset_collate .= ' COLLATE $wpdb->collate';
			}
		}
		return $charset_collat;
	}
	
	// Installs the plugin and creates the needed tables
	function install() {
		global $wpdb, $table_prefix;
		
		$charset_collate = $this->get_charset();
		
		// Create Stats-Table
		$sql_stats = 'CREATE TABLE `' . $table_prefix . 'geo_capblack_stats` (
					 `country` VARCHAR(100) NOT NULL,
					 `positiv_count` INT,
					 `negativ_count` INT
					 )%s';
		$wpdb->query(sprintf($sql_stats, $charset_collate));
		
		// Create Log-Table
		$sql_stats = 'CREATE TABLE `' . $table_prefix . 'geo_capblack_log` (
					 `country` VARCHAR(100) NOT NULL,
					 `type` VARCHAR(5),
					 `where` VARCHAR(20),
					 `date` VARCHAR(14),
					 `ip` VARCHAR(15)
					 )%s';
		$wpdb->query(sprintf($sql_stats, $charset_collate));
	}
	
	// Get the IP of the visitor
	function get_ip_address() {
		if (empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
			$ip_address = $_SERVER["REMOTE_ADDR"];
		} else {
			$ip_address = $_SERVER["HTTP_X_FORWARDED_FOR"];
		}
		if(strpos($ip_address, ',') !== false) {
			$ip_address = explode(',', $ip_address);
			$ip_address = $ip_address[0];
		}
		return $ip_address;
	}
	
	// Get Location of current user
	function get_location($answer = 'code') {
		
		$ip_address = $this->get_ip_address();

		$gi = geoip_open(WP_PLUGIN_DIR . '/geo-captcha-geo-blacklist/GeoIP.dat', GEOIP_STANDARD);

		if($answer == 'name') {
			$geo_location = geoip_country_name_by_addr($gi, $ip_address);
			if($geo_location == '') {
				$geo_location = 'Unknown';
			}
		} else {
			$geo_location = geoip_country_code_by_addr($gi, $ip_address);
			if('' == $geo_location) {
				$geo_location = 'Unknown';
			}
		}
		return $geo_location;
	}
	
	// Update country stats
	function update_stats($country, $pos_neg) {
		global $wpdb, $table_prefix;
		
		if($country == '') {
			$country = 'Unknown';
		}
		
		$old_info = $wpdb->get_row("SELECT * FROM " . $table_prefix . "geo_capblack_stats WHERE country = '" . $country . "'", ARRAY_A);
		if(isset($old_info['country'])) {
			if($pos_neg == 'neg') {
				$wpdb->query("UPDATE " . $table_prefix . "geo_capblack_stats SET negativ_count = " . ($old_info['negativ_count']+1) . "
					WHERE country = '" . $country . "'");
			} elseif ($pos_neg == 'pos') {
				$wpdb->query("UPDATE " . $table_prefix . "geo_capblack_stats SET positiv_count = " . ($old_info['positiv_count']+1) . "
					WHERE country = '" . $country . "'");
			} elseif ($pos_neg == 'delpos') {
				$wpdb->query("UPDATE " . $table_prefix . "geo_capblack_stats SET positiv_count = " . ($old_info['positiv_count']-1) . ",
					negativ_count = " . ($old_info['negativ_count']+1) . "
					WHERE country = '" . $country . "'");
			} elseif ($pos_neg == 'delneg') {
				$wpdb->query("UPDATE " . $table_prefix . "geo_capblack_stats SET positiv_count = " . ($old_info['positiv_count']+1) . ",
					negativ_count = " . ($old_info['negativ_count']-1) . "
					WHERE country = '" . $country . "'");
			}
		} else {
			if($pos_neg == 'neg') {
				$new_neg = 1;
				$new_pos = 0;
			} elseif ($pos_neg == 'pos') {
				$new_neg = 0;
				$new_pos = 1;
			} elseif ($pos_neg == 'delpos') {
				$new_neg = 1;
				$new_pos = 0;
			} elseif ($pos_neg == 'delneg') {
				$new_neg = 0;
				$new_pos = 1;
			}
			$wpdb->query("INSERT INTO " . $table_prefix . "geo_capblack_stats 
			VALUES('" . $country . "',
			'" . $new_pos . "',
			'" . $new_neg . "')");
		}
	}
	
	function geo_write_log($type, $where) {
		global $wpdb, $table_prefix;
			
		$charset_collate = $this->get_charset();
	
		// Gets the ip to log
		if(1 == get_option("geo_capblack_log_ips")) {
			$log_ip_address = $this->get_ip_address();
		} else {
			$log_ip_address = ' - ';
		}
		
		$sql_stats = 'INSERT INTO `' . $table_prefix . 'geo_capblack_log` VALUES (
			"'. $this->get_location('name') . '",
			"' . $type . '",
			"' . $where . '",
			"' . date("YmdHis") . '",
			"' . $log_ip_address . '"
			)';
		$wpdb->query(sprintf($sql_stats, $charset_collate));
		
	
	}
	
	// Check for captcha when sending a comment
	function geo_comment_post($incoming_comment) {
		
		if (is_user_logged_in()) {
			// If user is loggedin, save it to stats and return comment
			update_option("geo_capblack_registered_comments", get_option('geo_capblack_registered_comments')+1);
			$this->geo_write_log('user', 'comments');
			return $incoming_comment;
		}
		
		if (in_array($this->get_location(), $this->country_list)) {
			// If user is whitelisted, save it to stats and return comment
			update_option("geo_capblack_whitelisted_comments", get_option('geo_capblack_whitelisted_comments')+1);
			$this->geo_write_log('white', 'comments');
			return $incoming_comment;
		}
		
		if (in_array($this->get_location(), $this->country_blacklist)) {
			$this->geo_write_log('black', 'comments');
			wp_die( __('ERROR: Sorry but your country is blacklisted due to high spam amount!', 'geo-captcha-blacklist'));
		}
		
		include_once WP_PLUGIN_DIR . '/geo-captcha-geo-blacklist/securimage/securimage.php';

		$securimage = new Securimage();
		
		if ($securimage->check($_POST['captcha_code']) == false) {
		
			// If captcha was correct, save it to log and return comment
			$this->geo_write_log('bad', 'comments');
			update_option("geo_capblack_blocked_spam", get_option('geo_capblack_blocked_spam')+1);
			
			$this->update_stats($this->get_location('name'), 'neg');
			
			wp_die( __('ERROR: The Code you have entered was not correct. Please try again.', 'geo-captcha-blacklist'));
		} else {
			// If captcha was not correct, save it to log and die with an error
			$this->geo_write_log('good', 'comments');
			update_option("geo_capblack_not_whitelisted_comments", get_option('geo_capblack_not_whitelisted_comments')+1);
			
			$this->update_stats($this->get_location('name'), 'pos');
			
			return $incoming_comment;
		}
	}
	
	// Check for captcha when sending a comment
	function geo_register_post() {
		
		if (is_user_logged_in()) {
			// If user is loggedin, save it to stats and return comment
			update_option("geo_capblack_registered_comments", get_option('geo_capblack_registered_comments')+1);
			return $incoming_comment;
		}
		
		if (in_array($this->get_location(), $this->country_list)) {
			// If user is whitelisted, save it to stats and return comment
			update_option("geo_capblack_whitelisted_comments", get_option('geo_capblack_whitelisted_comments')+1);
			return $incoming_comment;
		}
		
		include_once WP_PLUGIN_DIR . '/geo-captcha-geo-blacklist/securimage/securimage.php';

		$securimage = new Securimage();
		
		if ($securimage->check($_POST['captcha_code']) == false) {
		
			// If captcha was correct, save it to log and return comment
			$this->geo_write_log('bad', 'registration');
			update_option("geo_capblack_blocked_spam", get_option('geo_capblack_blocked_spam')+1);
			
			$this->update_stats($this->get_location('name'), 'neg');
			
			wp_die( __('ERROR: The Code you have entered was not correct. Please try again.', 'geo-captcha-blacklist'));
		} else {
			// If captcha was not correct, save it to log and die with an error
			$this->geo_write_log('good', 'registration');
			update_option("geo_capblack_not_whitelisted_comments", get_option('geo_capblack_not_whitelisted_comments')+1);
			
			$this->update_stats($this->get_location('name'), 'pos');
			
			return $incoming_comment;
		}
	}

	// Create captcha if user is not loggedin and not in whitelist
	function geo_comment_form()
	{
		if (is_user_logged_in()) return true;

		if (in_array($this->get_location(), $this->country_list)) return true;
		
		$this->geo_output_captcha();
		
		return $fields = '';
	}
	
		// Create captcha if user is not loggedin and not in whitelist
	function geo_register_form()
	{
		if (is_user_logged_in()) return true;

		if (in_array($this->get_location(), $this->country_list)) return true;
		
		$this->geo_output_captcha();
	}
	
	// Creates the HTML output for the forms
	function geo_output_captcha() {
		?>
		<p><?php _e('Please insert the signs in the image:', 'geo-captcha-blacklist') ?></p>
		<div style="width: 250px">
		 <div style="width: 220px; float: left;">
		  <img src="<?php echo WP_PLUGIN_URL; ?>/geo-captcha-geo-blacklist/securimage/securimage_show.php" id="captcha" border="0" /><br />
		  <input type="text" name="captcha_code" size="10" maxlength="6" />
		 </div>
		 <div style="width: 25px; float: right;">
		  <a href="#" onclick="document.getElementById('captcha').src = '<?php echo WP_PLUGIN_URL; ?>/geo-captcha-geo-blacklist/securimage/securimage_show.php?' + Math.random(); return false">
		   <img src="<?php echo WP_PLUGIN_URL; ?>/geo-captcha-geo-blacklist/securimage/images/refresh.gif" alt="<?php _e('Reload Image', 'geo-captcha-blacklist'); ?>" border="0" />
		  </a>
		  <a href="<?php echo WP_PLUGIN_URL; ?>/geo-captcha-geo-blacklist/securimage/securimage_play.php">
		   <img src="<?php echo WP_PLUGIN_URL; ?>/geo-captcha-geo-blacklist/securimage/images/audio_icon.gif" alt="<?php _e('Play Audio-CAPTCHA', 'geo-captcha-blacklist'); ?>" border="0" />
		  </a>
		 </div>
		 <p style="clear: both;"></p>
		</div>
		<?php
	}

	function geo_remove_comment_form( $file ) {
		if (in_array($this->get_location(), $this->country_blacklist)) {
			$file = WP_PLUGIN_DIR . '/geo-captcha-geo-blacklist/images/blacklisted.php';
			return $file;
		}
	}
}

/*
 * Manuell marked spam
 */
add_action('wp_set_comment_status', 'geo_test_comment', 10, 2);


function geo_test_comment($comment_id, $comment_status) {
	
	$gi = geoip_open(WP_PLUGIN_DIR . '/geo-captcha-geo-blacklist/GeoIP.dat', GEOIP_STANDARD);

	$comment_info = get_comment($comment_id);
	
	if('spam' == $comment_status) {
		
		$geo_location = geoip_country_name_by_addr($gi, $comment_info->comment_author_IP);
		$geo_location_code = geoip_country_code_by_addr($gi, $comment_info->comment_author_IP);
		if($geo_location == '') {
			$geo_location = 'Unknown';
		}
		
		$geo_capblack_img = new geo_capblack();
		$geo_capblack_img->init();
		
		if(!in_array($geo_location_code, $geo_capblack_img->country_list)) {
			$geo_capblack_img->update_stats($geo_location, 'delpos');
			update_option("geo_capblack_manuell_spam", get_option('geo_capblack_manuell_spam')+1);
		} else {
			update_option("geo_capblack_whitelisted_spam", get_option('geo_capblack_whitelisted_spam')+1);
		}
	} elseif('spam' == $comment_info->comment_approved) {
		
		$geo_location = geoip_country_name_by_addr($gi, $comment_info->comment_author_IP);
		$geo_location_code = geoip_country_code_by_addr($gi, $comment_info->comment_author_IP);
		if($geo_location == '') {
			$geo_location = 'Unknown';
		}
		
		$geo_capblack_img = new geo_capblack();
		$geo_capblack_img->init();
		
		if(!in_array($geo_location_code, $geo_capblack_img->country_list)) {
			$geo_capblack_img->update_stats($geo_location, 'delneg');
			update_option("geo_capblack_manuell_spam", get_option('geo_capblack_manuell_spam')-1);
		} else {
			update_option("geo_capblack_whitelisted_spam", get_option('geo_capblack_whitelisted_spam')-1);
		}

	}
}



if (class_exists("geo_capblack")) {
	$geo_capblack_img = new geo_capblack();
	$geo_capblack_img->init();
}

function geo_capblack_admin_head() {
	echo '<style type="text/css" media="screen">
	@import url("' . WP_PLUGIN_URL . '/geo-captcha-geo-blacklist/geo-captcha-blacklist.css");
	</style>';
}

add_action('admin_head', 'geo_capblack_admin_head');

if(1 == get_option("geo_capblack_comments")) {
	add_action('comment_form', array(&$geo_capblack_img, 'geo_comment_form'));
	add_filter('preprocess_comment', array( &$geo_capblack_img, 'geo_comment_post'));
	add_filter('comments_template',  array( &$geo_capblack_img, 'geo_remove_comment_form'));
}
if(1 == get_option("geo_capblack_registration")) {
	add_action('register_form', array(&$geo_capblack_img, 'geo_register_form'));
	add_action('register_post', array( &$geo_capblack_img, 'geo_register_post'));
}
?>