<?php

    /*
    Copyright 2006 Paul Westbrook (paul@westbrooks.org)
    
    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 2 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, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    */

	lt_include( PLOG_CLASS_PATH."class/security/pipelinefilter.class.php" );

    
    // custom error code that will be returned to the pipeline whenever an
    // error is found... Be careful so as to not to have two different modules
    // use the same code!!
    define( "VALIDATE_TRACKBACK_SPAM", 850 );

	class ValidateTrackbackFilter extends PipelineFilter 
	{

    	function ValidateTrackbackFilter( $pipelineRequest )
        {
        	$this->PipelineFilter( $pipelineRequest );
        }

        function filter()
        {
        	// get some info
            $blogInfo = $this->_pipelineRequest->getBlogInfo();
            $request  = $this->_pipelineRequest->getHttpRequest();

        	// check if this section has been enabled or disabled
            $blogSettings = $blogInfo->getSettings();
		    $pluginEnabled = $blogSettings->getValue( "plugin_validatetrackback_enabled" );
            if( !$pluginEnabled) {
            	// if not, nothing to do here...
                //_debug("ip address filter not enabled! quitting...<br/>");
            	return new PipelineResult();
            }

            // we only have to filter the contents if the user is posting a comment
            // so there's no point in doing anything else if that's not the case
            if(( $request->getValue( "op" ) != "AddTrackback" )) {
            	$result = new PipelineResult();
                return $result;
            }

            // if this is already rejected, there is no reason to do anything here
            if ( $this->_pipelineRequest->getRejectedState() )
                return new PipelineResult();
                
            // text and topic of the comment/trackback
            $commentText = $request->getValue( "excerpt" );
            $commentTopic = $request->getValue( "title" );
            $articleId = $request->getValue( "id" );
            $userName = $request->getValue( "blog_name" );
            $userUrl = $request->getValue( "url" );

            
            if ( $blogSettings->getValue( "plugin_validatetrackback_dns_enabled" ) ) {
				lt_include( PLOG_CLASS_PATH."plugins/validatetrackback/class/security/dnsantispamfilter.class.php" ); 

                // 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 ) {
                    $this->trackbackLog( "Validate Trackback: The ip address ".$clientIpAddress.
                                  " disallowed" );
                   $locale = $blogInfo->getLocale();
                   $result = new PipelineResult( false, VALIDATE_TRACKBACK_SPAM, $locale->tr("error_comment_spam_throw_away") );
                   return $result;                                                 
                }
                // If the client ip address is OK, check the url

                $url = TextFilter::htmlDecode( $userUrl );
                
                $fTrackBackValid = 
                     ValidateTrackbackDNSAntiSpamFilter::checkTrackbackURL( $url );
                     
                if( ! $fTrackBackValid ) {
                    $this->trackbackLog( "Validate Trackback: The url ".$url.
                                  " disallowed" );
                   $locale = $blogInfo->getLocale();
                   $result = new PipelineResult( false, VALIDATE_TRACKBACK_SPAM, $locale->tr("error_comment_spam_throw_away") );
                   return $result;                                                 
                }
            }

            $url = "";
            $page = "";
            
            if( $blogSettings->getValue( "plugin_validatetrackback_trackback_enabled" ) || 
                $blogSettings->getValue( "plugin_validatetrackback_linkchecking_enabled" )) {
  
                // Get the page
                $url = TextFilter::htmlDecode( $userUrl );
                $page = $this->fetchPage( $url );    
            }


            if ( $blogSettings->getValue( "plugin_validatetrackback_trackback_enabled" ) ) {
                
                // Get the trackback client
				lt_include( PLOG_CLASS_PATH."class/dao/trackbackclient.class.php" );				
                $tbClient = new TrackbackClient();
                // get the trackback url
                $tbLinks = $tbClient->getTrackbackLinks( $page, $url );
                if( empty( $tbLinks)) {
                    // there were no trackback links in the page
                    $this->trackbackLog( "Validate Trackback: No trackback urls on resulting page" );
                    $locale = $blogInfo->getLocale();
                    $result = new PipelineResult( false, VALIDATE_TRACKBACK_SPAM, $locale->tr("error_comment_spam_throw_away") );
                    return $result;                                                 
                }
            }
            
            if ( $blogSettings->getValue( "plugin_validatetrackback_linkchecking_enabled" ) ) {

                lt_include( PLOG_CLASS_PATH."class/dao/article.class.php");
                lt_include( PLOG_CLASS_PATH."class/dao/articles.class.php");
                // Make sure that the page referenced in the trackback actually includes a 
                // Link to this article
                
       			$articles = new Articles();
	            $item = $articles->getBlogArticle($articleId);

                // Get the permalink to this article
                $rg = $blogInfo->getBlogRequestGenerator();
                $postUrl = $rg->postLink($item);
                
                // Now deterimine if the page contains the post url
                
                // XXX Ideally this would not just use strpos, but would actually look for a 
                // <a> link that contains this url
                if( strpos($page, $postUrl) === FALSE) {
                    // there were no trackback links in the page
                    $this->trackbackLog( "Validate Trackback: Page doesn't contain link to this post" );
                    $locale = $blogInfo->getLocale();
                    $result = new PipelineResult( false, VALIDATE_TRACKBACK_SPAM, $locale->tr("error_comment_spam_throw_away") );
                    return $result;                                                 
                }
            }

            // if everything went fine, we can say so by returning
            // a positive PipelineResult object
            $result = new PipelineResult( true );
            
            return $result;
        }
        
        /**
      	 * 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 )
	    {
			lt_include( PLOG_CLASS_PATH."class/net/http/httpclient.class.php" );		
    		$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 trackbackLog( $message )
		{
			$logger =& LoggerManager::getLogger( "trackback" );
			$logger->debug( $message );
		}


    }
    
?>
