<?php

    include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
    include_once( PLOG_CLASS_PATH."class/dao/trackback.class.php" );
    include_once( PLOG_CLASS_PATH."class/dao/trackbackclient.class.php" );
    include_once( PLOG_CLASS_PATH."class/dao/trackbacks.class.php" );
    include_once( PLOG_CLASS_PATH."class/net/http/httpclient.class.php" );
    include_once( PLOG_CLASS_PATH."class/security/bayesianfilter.class.php" );
    include_once( PLOG_CLASS_PATH."plugins/validatetrackback/class/security/dnsantispamfilter.class.php" );
    
	/**
	 * implements moderation of comments
	 */
	class PluginValidateTrackback extends PluginBase
	{
	    var $pluginEnabled;
	    
		function PluginValidateTrackback()
		{
			$this->PluginBase();
			
			$this->id = "validatetrackback";
			$this->desc = "Provides validation of trackbacks.";
			$this->author = "Paul Westbrook";
			$this->locales = Array( "en_UK", "zh_TW", "es_ES" );
			
			$this->init();
		}

		/**
		 * registers all the filters and actions that we're going to use
		 */
		function init()
		{			
			// register the events we want
			$this->registerNotification( EVENT_POST_TRACKBACK_ADD );
			
			// register an action that will allow users to see which comments have not been
			// accepted yet
			$this->registerAdminAction( "validatetrackbackPluginSettings", "AdminValidateTrackbackPluginSettingsAction" );
			$this->registerAdminAction( "validatetrackbackPluginUpdateSettings", "AdminValidateTrackbackPluginUpdateSettingsAction" );
			
			// add a menu entry
			$menu =& Menu::getMenu();
            if( !$menu->entryExists( "/menu/controlCenter/manageAntiSpamPlugins" ))                     
                $this->addMenuEntry( "/menu/controlCenter", "manageAntiSpamPlugins", "", "", true, false );
            $this->addMenuEntry( "/menu/controlCenter/manageAntiSpamPlugins", "validatetrackbackPluginSettings", "admin.php?op=validatetrackbackPluginSettings", "", true, false );
		}

		function register()
		{
		    $blogSettings = $this->blogInfo->getSettings();
			$this->pluginEnabled = $blogSettings->getValue( "plugin_validatetrackback_enabled" );
		}

	    function isEnabled()
	    {
	        return $this->pluginEnabled;
	    }		
		
		/**
		 * process the events that we have registered
		 *
		 * @see PluginBase::process
		 * @see PluginManager
		 */
		function process( $eventType, $params )
		{
		    // make sure we're processing the right event!
		    if( $eventType != EVENT_POST_TRACKBACK_ADD ) 
		      return true;
			  
			// do nothing if the plugin is not enabled!
			$blogSettings = $this->blogInfo->getSettings();
			if( !$blogSettings->getValue( "plugin_validatetrackback_enabled" ))
				return true;
			  
			// change the stauts of the comment, as is easy as it seems...
			$trackback = $params["trackback"];
			$this->Validate( $trackback );
		      
			return true;
		}
		
	    /**
     	* Fetches a page from the given url.
	     *
	     * @param url The url with the page we would like to fetch.
	     * @return Returns a string with the contents of the page or an empty string if the page
	     * could not be fetched.
	     */
	    function fetchPage( $url )
	    {
    		$s = new HttpClient();
    		
    		// Set the time out to 15 seconds.  We don't want this web server
    		// thread waiting a long time as it could cause a DoS with enough 
    		// trackbacks
    		$s->read_timeout = 15;
    		
        	$result = $s->fetch( $url );

        	if( !$result ) {
                if($s->timed_out)
                {
                	//print("timed out!!!");
                }
        		return "";
            }
        	else
        		return $s->results;
    	}
		
		function Validate( $trackback )
		{
            $fTrackBackValid = true;
 			$blogSettings = $this->blogInfo->getSettings();
            
            if ( $blogSettings->getValue( "plugin_validatetrackback_dns_enabled" ) ) {
                
                // First check to see if the ip address is listed in black lists
                $clientInfo = new Client();
                
                $clientIpAddress = $clientInfo->getIp();
                
                $fTrackBackValid = 
                     ValidateTrackbackDNSAntiSpamFilter::checkClientIP( $clientIpAddress );
                     
                if( ! $fTrackBackValid ) {
                    trackbackLog( "Validate Trackback: The ip address ".$clientIpAddress.
                                  " disallowed" );
                }
                // If the client ip address is OK, check the url
                if ( $fTrackBackValid ) {
                    $url = TextFilter::htmlDecode( $trackback->_url );
                    
                    $fTrackBackValid = 
                         ValidateTrackbackDNSAntiSpamFilter::checkTrackbackURL( $url );
                         
                    if( ! $fTrackBackValid ) {
                        trackbackLog( "Validate Trackback: The url ".$url.
                                      " disallowed" );
                    }
                }
            }
            
            
            if ( $fTrackBackValid && 
                 $blogSettings->getValue( "plugin_validatetrackback_trackback_enabled" ) ) {
                // Get the page
                $url = TextFilter::htmlDecode( $trackback->_url );
                $page = $this->fetchPage( $url );            
                
                // Get the trackback client
                $tbClient = new TrackbackClient();
                // get the trackback url
                $tbLinks = $tbClient->getTrackbackLinks( $page, $url );
                if( empty( $tbLinks)) {
                    // there were no trackback links in the page
                    $fTrackBackValid = false;
                    
                    if( ! $fTrackBackValid ) {
                        trackbackLog( "Validate Trackback: No trackback urls on resulting page" );
                    }
                }
            }
            
            // if this is still a valid trackback and we are supposed to check the bayesian filter
            if ( $fTrackBackValid && 
                 $blogSettings->getValue( "plugin_validatetrackback_bayesian_enabled" ) ) {

                $config	=& Config::getConfig();
                if ($config->getValue("bayesian_filter_enabled"))
                {
                    $tokenizer = new BayesianTokenizer();
        
                    $tokensTopic = $tokenizer->addContextMark($tokenizer->tokenize($trackback->getTitle()), TOKEN_TOPIC_MARK);
                    $tokensText = $tokenizer->tokenize($trackback->getExcerpt());
        
                    $tokensUserUrl = $tokenizer->addContextMark($tokenizer->tokenize($trackback->getUrl()), TOKEN_USER_URL_MARK);
        
                    $tokens = array_merge($tokensTopic, $tokensText, $tokensUserUrl);
                    $significantTokens = BayesianFilter::_getMostSignificantTokens($this->blogInfo->getId(), $tokens);
                    
                    $spamicity =  BayesianFilter::_getBayesProbability($significantTokens);

                    if ($spamicity >= $config->getValue("bayesian_filter_spam_probability_treshold"))
                    {
                        // value is over spam limit
                        $fTrackBackValid = false;
                        
                        if( ! $fTrackBackValid ) {
                            trackbackLog( "Validate Trackback:Spamicity ".$spamicity.
                                          " too high" );
                        }
                    }
                }
            }
            
            if ( !$fTrackBackValid ) {
                // Trackback is not valid
                // Delete this trackback
                $trackbacks = new Trackbacks();
                
                $trackbacks->deletePostTrackback( $trackback->_id, $trackback->_articleId );
                //print("Error: trackback unavailable<br/>");
            }
		}
	}  
?>