<?php

/*                                                                                */
/* NP_Blacklist                                                                   */
/* ------------------------------------                                           */
/* version information ----------------                                           */
/* 0.90 initial release                                                           */
/* 0.91 issues with xhtml compliance. sloppy coding removed                       */
/* 0.92 added user, userid and host to check for spam                             */
/* 0.93 bug in fetching fresh blacklist solved                                    */
/* 0.94 code cleanup,no more pivot specific functions and files                   */
/* 0.952 added the posibility to block on the referrerfield against the same lists
         added the option to ip-ban the commenting machine (commented out! with //ip
         remove all '//ip' if you want to checkout this functionality.
         personally i don't like it -xiffy-
*/
/* 0.95b2 removed ip-ban option.
          added the yet non-existent event PreActioAddComment to kick in at the right moment
          and not 'too late'. Solves emailnotification problem on adding comments
*/
/* 0.95 final
        removed the option to have a different url for referrer spamming. This will grow wild
        if more spam-blocking types (like trackback) will be introduced.
        So 1 url to serve them all.
        the function blacklist is from now on the 1 function to call from other plugins
        to call blacklist from inside your plugin add the following code:
--deleted obsolete call for blacklist --
*/
/* 0.96 Beta
        added ip-based blocking. This option differs from earlier attempts to add the ip to the nucleus ip-ban
        Now, wehn a machine spam your website above the ip-block-threshold (default 10) the machine will be added
        to the blocked ip addresses table. This way, newly undiscovered spamming domains won't be showing up
        easily since most spamming is done by a subset of machines (zombies)
        added menu item to maintain blocked ip-addresses.
*/
/* 0.96 Beta 2
        .htaccess snippets work. Thanks to Karma for his regexp reworke
        there are two modes, one for blocked IP's and one for matched rules, each give a different kind of output
        Once you've generated the rules and incorporated the finished result into your .htaccess you should Reset the file.
        Otherwise you would end up with doubles inside your .htaccess, this should be avoided, but is completly acceptable for apache.
*/
/* 0.96 Beta 3
        Plugins calling plugins. Rakaz and I think we made it happen on a way that is future prove and a proof of concept for
        other plugin writers. This plugin listens to the event SpamCheck, which is unknown inside nucleus-core.
        NP_MailToAFriend, NP_Trackback and Referrer2 call this plugin if it is installed. It handles redirection itself.
        The easy way:
// check for spam attempts, you never knnow !
    $spamcheck = array ('type'  => 'MailtoaFriend',
                        'data'  => $extra.' '.$toEmail.' '.$fromEmail);
    $manager->notify('SpamCheck', array ('spamcheck' => & $spamcheck));
// done
        The hard way and Total Control!
    $spamcheck = array (
        'type'  => 'Referer',
        'data'  => 'data that needs to be checked',
        'return'  => true
    );

    $manager->notify('SpamCheck',
        array ('spamcheck' => & $spamcheck)
    );

    if (isset($spamcheck['result']) &&
        $spamcheck['result'] == true)
    {
        // Handle spam
    }
*/
/* 0.97 Added eventHandler for the new ValidateForm event (nucleus 3.2)
*/
/* 0.98 Solved naar.be bug
*/
if (! function_exists(redirect) ) {
    function redirect($url) {
    	$url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%]|i', '', $url);
    	header('Location: ' . $url);
    	exit;
    }
}

class NP_Blacklist extends NucleusPlugin {
	function getName() 		  { return 'Blacklist'; }
	function getAuthor()  	  { return 'xiffy'; }
	function getURL()  		  { return 'http://xiffy.nl/weblog'; }
	function getVersion() 	  { return '0.98'; }
	function getDescription() { return 'Blacklist for commentspammers';	}
	function supportsFeature($what) {
		switch($what) {
		    case 'SqlTablePrefix':
				return 1;
			default:
				return 0;
		}
	}

    function install() {
        // create some options
        $this->createOption('enabled','Blacklist engine enabled?','yesno','yes');
        $this->createOption('redirect','To which URL should spammers be redireted?','text','http://spamtrap.xiffy.nl/');
        $this->createOption('update','From which URL should we get a fresh blacklist copy?', 'text','http://www.jayallen.org/comment_spam/blacklist.txt');
        $this->createOption('referrerblock','Enable referrer based blocking?','yesno','yes');
        $this->createOption('ipblock','Enable ip based blocking?','yesno','no');
        $this->createOption('ipthreshold','How many spam attempts will block an IP address?','text','10');
    }

	function unInstall() {}

    function getPluginOption ($name) {
        return $this->getOption($name);
    }

	function getEventList() {
		return array('QuickMenu','PreAddComment','PreSkinParse','PreActionAddComment','ValidateForm', 'SpamCheck');
	}

	function hasAdminArea() {
		return 1;
	}

	function event_QuickMenu(&$data) {
		global $member, $nucleus, $blogid;
		// only show to admins
		if (preg_match("/MD$/", $nucleus['version'])) {
			$isblogadmin = $member->isBlogAdmin(-1);
		} else {
			$isblogadmin = $member->isBlogAdmin($blogid);
		}
		if (!($member->isLoggedIn() && ($member->isAdmin() | $isblogadmin))) return;
		array_push(
			$data['options'],
			array(
				'title' => 'Blacklist',
				'url' => $this->getAdminURL(),
				'tooltip' => 'Manage your blacklist'
			)
		);
	}

    // for other plugin writers ...
    function event_SpamCheck (&$data) {
        global $DIR_PLUGINS;
//        $fp  = fopen ($DIR_PLUGINS."blacklist/settings/debug.txt", 'a');
//        fwrite($fp,"==called ==\n");
//        fwrite($fp,'type : ' .$data['spamcheck']['type']."\n");
//        fwrite($fp,'data : ' .$data['spamcheck']['data']."\n");
//        fclose($fp);
        if (isset($data['spamcheck']['result']) &&
            $data['spamcheck']['result'] == true)     {
            // Already checked... and is spam
            return;
        }
        // Check for spam
        $result = $this->blacklist($data['spamcheck']['type'], $data['spamcheck']['data'], $data['spamcheck']['ipblock']);

        if ($result) {
            // Spam found
            // logging !
            pbl_logspammer($data['spamcheck']['type'].': '.$result);
            if  (isset($data['spamcheck']['return']) && $data['spamcheck']['return'] == true) {
                // Return to caller
                $data['spamcheck']['result'] = true;
                return;
            } else {
                redirect($this->getOption('redirect'));
            }
        }
    }

    // will become obsolete when nucleus is patched ...
	function event_PreAddComment(&$data) {
	    $comment = $data['comment'];
	    $result = $this->blacklist('comment',$comment['body'].' '.$comment['host'].' '.$comment['user'].' '.$comment['userid']);
        if ($result != '') {
            pbl_logspammer('comment: '.$result);
            redirect($this->getOption('redirect'));
        }
    }

	function event_ValidateForm(&$data) {
	    $comment = $data['comment'];
	    $result = $this->blacklist('comment',$comment['body'].' '.$comment['host'].' '.$comment['user'].' '.$comment['userid']);
        if ($result != '') {
            pbl_logspammer('comment: '.$result);
            redirect($this->getOption('redirect'));
        }
    }

	// preskinparse will check the referrer for spamming attempts
	// only when option enabled !
	// logging also only when option enabled ...
	function event_PreSkinParse(&$data) {
        $result = $this->blacklist('refer','');
        if ($result != '') {
            pbl_logspammer('referrer: '.$result);
            redirect($this->getOption('redirect'));
        }
	}

	function event_PreActionAddComment(&$data) {
	    // test referrer ...
        $result = $this->blacklist('comment', $data['body'].' '.$data['user'].' '.$data['userid']);
        if ($result != '') {
            pbl_logspammer('comment: '.$result);
            redirect($this->getOption('redirect'));
        }
	}


	function blacklist($type,$testString, $ipblock = true) {
        global $DIR_PLUGINS;
	    if ($this->getOption('enabled') == 'yes') {
            include_once($DIR_PLUGINS."blacklist/blacklist_lib.php");
            // update the blacklist first file
            pbl_updateblacklist($this->getOption('update'),false);
            if ($ipblock) {
                $ipblock = $this->getOption('ipblock');
            } else {
                $ipblock = 'no';
            }
            $refer = parse_url($_SERVER['HTTP_REFERER']);
            $refer = $refer['host'];
            if ($this->getOption('referrerblock') == 'yes')  {
                $spamDetected = pbl_checkforspam($refer, $ipblock , $this->getOption('ipthreshold'), true);
                if($spamDetected != "")  {
                    return $spamDetected;
                }
            }
            if ($testString != '') {
                $spamDetected = pbl_checkforspam($testString, $ipblock, $this->getOption('ipthreshold'), true);
                if($spamDetected != "")  {
                    return $spamDetected;
                }
            }
        }
    }
}
?>