<?php

@( (bool)FALSE === strpos( $_SERVER['REQUEST_URI'], basename( __FILE__ ) ) ) OR exit( '!! ACCESS DENIED !!' );
error_reporting( _E_VALUE );

/* vim: set expandtab tabstop=4 shiftwidth=4: */

// ***** BEGIN LICENSE BLOCKS ( DO NOT REMOVE ) *****

// +----------------------------------------------------------------------+
// | WebSanitizer For MPN 188_8 Input/Output Sanitizer Extension          |
// |                                                                      |
// | -> Input/Output Sanitizing                                           |
// | -> Input/Output Formatting                                           |
// | -> Database Content Input/Output Prep                                |
// | -> Request URI Sanitizing                                            |
// +----------------------------------------------------------------------+
// | VERSION: 0.3 Alpha                                                   |
// +----------------------------------------------------------------------+
// | LICENSE: GPL 2.0 (see docs/LICENSE_GPL)                              |
// |                                                                      |
// | This file is part of WebSanitizer For MPN 188_8.                     |
// |                                                                      |
// | WebSanitizer For MPN 188_8 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.               |
// |                                                                      |
// | WebSanitizer For MPN 188_8 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 WebSanitizer For MPN 188_8; if not, write to the          |
// | Free Software Foundation, Inc.,                                      |
// | 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA               |
// +----------------------------------------------------------------------+
// | AUTHOR(s):                                                           |
// |                                                                      |
// | The Original Code is the WebSanitizer For MPN 188_8.                 |
// | The Initial Developer of the Original Code is Eric Haddix.           |
// |                                                                      |
// | Portions created by Eric Haddix or Kiril Threndor                    |
// | <support@websanitizer.illearth.net> are                              |
// | Copyright (C) 2003 Eric Haddix.  All Rights Reserved.                |
// |                                                                      |
// | Portions from htmlfilter.inc v. 1.1, created by                      |
// | Konstantin Riabitsev <icon@linux.duke.edu> are                       |
// | Copyright (C) 2002-2003 by Duke University.  All Rights Reserved.    |
// +----------------------------------------------------------------------+
// | CONTRIBUTOR(s):                                                      |
// |                                                                      |
// |                                                                      |
// +----------------------------------------------------------------------+
// | MODIFICATIONS:                                                       |
// |                                                                      |
// |                                                                      |
// +----------------------------------------------------------------------+
// | REQUIRED FILES: core_Sanitize.param.php                              |
// |                 core_AllowArrays.param.php ( Optional )              |
// +----------------------------------------------------------------------+
// | NOTES:                                                               |
// |   Method sanitize was once part of htmlfilter.  It has been highly   |
// |   modified for this class.                                           |
// |                                                                      |
// |   The oringal htmlfilter source code can be found at:                |
// |   http://linux.duke.edu/projects/mini/htmlfilter/                    |
// +----------------------------------------------------------------------+
// | SUPPORT:                                                             |
// |   WEB:   http://myphpnuke.com/                                       |
// |   EMAIL: support@websanitizer.illearth.net                           |
// +----------------------------------------------------------------------+
// $Id: core_CheckInput.subclass.php,v 1.24.2.20 2004/08/15 14:32:27 kirilt Exp $

// ***** END LICENSE BLOCK ( DO NOT REMOVE ) *****


class CheckRequest extends Sanitizer
{
    /**
     * Enable / Disable debugging
     *
     * @var bool
     */

    var $debug            = FALSE;

    /**
     * Marks The Initial Security Pass Active
     *
     * @var bool
     */

    var $init_pass        = FALSE;

    /**
     * Click Array
     *
     * Holds Form Variable Names Of Content
     * That needs to pass through makeClickable
     * and linkSmiley
     *
     * @var array
     */

    var $click_ary         = array();

    /**
     * Strip Array
     *
     * Holds Form Variable Names Of Content
     * That Has HTML/BBCode Unconditionally
     * Stripped
     *
     * @var array
     */

    var $strip_ary         = array();

    /**
     * Binary Array
     *
     * Holds Form Variable Names Of Content
     * That Contains Binary Data
     *
     * @var array
     */

    var $bin_ary           = array();

    /**
     * Section Type
     *
     * Determines How To Format
     * Returned Data
     *
     * @var interger
     */

    var $sectype           = 0;

    /**
     * Dynamic Scan Time Allowed Tag List
     *
     * @var array
     */

    var $scan_taglist      = array();

    /**
     * Add Slashes
     *
     * @var bool  DEFAULT = FALSE ( Do Nothing )
     */

    var $add_slashes       = FALSE;

    /**
     * Enable /Disable Text Formatting
     *
     * @var bool  DEFAULT = FALSE ( Do Nothing )
     */

    var $format_text       = FALSE;

    /**
     * Used To Determine Final Storage Format
     *
     * @var bool  DEFAULT = FALSE
     */

    var $pure_html         = FALSE;

    /**
     * Absolute Path To Directory Where Smiles Are Kept
     *
     * Example: http://mydomain.com/images/smiles/
     *
     * NOTE: Must Contain Trailing Slash
     *
     * @var string
     */

    var $smile_uri            = NULL;

    /**
     * Child Class Tag List Copy
     *
     * @var array
     */

    var $tag_list;

    /**
     * Child Class Remove Tags Copy
     *
     * @var bool
     */

    var $rm_tags;

    /**
     * Child Class force_tag_closing Copy
     * Default
     *
     * @var bool
     */

    var $run_auto_close;

    /**
     * Child Class Runtime Processing Type Copy
     *
     * @var integer
     */

    var $run_proc_type;

    /**
     * Child Class Strip Tags Copy
     *
     * @var array
     */

    var $run_strip_tags;

    /**
     * Child Class Strip Slashes Copy
     *
     * @var array
     */

    var $run_strip_slashes;

    /**
     * Child Class Return Literal Copy
     *
     * @var bool
     */

    var $run_literal;

/**
 * Class Constructor
 *
 * Calls the parent class constructor passing any required
 * adjustments to the initialization of the sanitizer if
 * required and set defaults
 *
 * @return  void.
 */

function CheckRequest( $allow_html = TRUE, $param_arrays = FALSE, $allowed_tags = NULL, $censor = TRUE )
    {
        /**
         * Reinitialized The Parent If Required
         *
         * Note: All Arguments Must Be Present To Reinitialized
         */

        $num_args = func_num_args();

        if ( $num_args == 4 )
        {
            $this -> Sanitizer( $allow_html, $param_arrays, $allowed_tags, $censor );
        }
        else
        {
            $this -> Sanitizer();
        }

        // Initialize Child Class Parent Copies

        $this -> restoreDefaults( 0 );

        // Build The Smile URI

        $this -> smile_uri = './images/forum/smilies/';

        // Build The Smile Array

        $this -> smile_ary = $_SERVER['F_LIB'] -> getSmiles();

        return;

    } // End Constructor

/**
 * Used To Restore Parent Sanitizers Variables To Defaults
 * Retains Copies Of The Parent Class Variables For Runtime Switching
 *
 * Allows For Applying Different Restrictions To Different Content
 * When Calling Method Sanitize With Arguments.
 *
 * Default Allowed Html Is Essentially All Tags Allowed
 * Except For Tags That Can Contain Malicious Code.
 */

function restoreDefaults( $init )
    {
        switch ( $init )
        {
            // Initialize The Parent Copies

            case 0:

                $this -> init_pass          = (bool)TRUE;

                $this -> tag_list           = $this -> taglist;
                $this -> scan_taglist       = $this -> taglist;
                $this -> rm_tags            = $this -> rmtags;
                $this -> bbtag_list         = $this -> bbtaglist;
                //$this -> scan_bbtaglist     = $this -> bbtaglist;
                $this -> bbrm_tags          = $this -> bbrmtags;
                $this -> run_proc_type      = $this -> proc_type;
                $this -> run_auto_close     = $this -> force_tag_closing;
                $this -> run_strip_tags     = $this -> strip_tags;
                $this -> run_strip_slashes  = $this -> strip_slashes;
                $this -> run_literal        = $this -> return_literal;

            break;

            // Reset Sanitizer For Next Scan

            case 1:

                $this -> init_pass         = (bool)FALSE;

                $this -> taglist           = $this -> tag_list;
                $this -> rmtags            = $this -> rm_tags;
                $this -> bbtaglist         = $this -> bbtag_list;
                $this -> bbrmtags          = $this -> bbrm_tags;
                $this -> proc_type         = $this -> run_proc_type;
                $this -> force_tag_closing = $this -> run_auto_close;
                $this -> strip_tags        = $this -> run_strip_tags;
                $this -> strip_slashes     = $this -> run_strip_slashes;
                $this -> return_literal    = $this -> run_literal;
                $this -> strip_slashes     = $this -> run_strip_slashes;

                $this -> add_slashes       = (bool)FALSE;
                $this -> make_clickable    = (bool)FALSE;
                $this -> encode_smileys    = (bool)FALSE;
                $this -> format_text       = (bool)FALSE;
                $this -> pure_html         = (bool)FALSE;
                $this -> form_variables    = array();
                $this -> form_cnt          = 0;
                $this -> sectype           = 0;
                $this -> body_length       = 0;

            break;

            // Reset Primary Scan For Next Request Variable

            case 2:

                $this -> make_clickable = (bool)FALSE;
                $this -> encode_smileys = (bool)FALSE;
                $this -> format_text    = (bool)FALSE;
                $this -> pure_html      = (bool)FALSE;
                $this -> bbencoder_on   = (bool)FALSE;
                $this -> add_slashes    = (bool)FALSE;
                $this -> proc_type      = $this -> run_proc_type;
                $this -> strip_slashes  = $this -> run_strip_slashes;
                $this -> return_literal = $this -> run_literal;
                $this -> strip_tags     = $this -> run_strip_tags;
                $this -> taglist        = $this -> scan_taglist;
                $this -> rmtags         = $this -> scan_rmtags;
                $this -> bbtaglist      = $this -> scan_bbtaglist;
                $this -> bbrmtags       = $this -> scan_bbrmtags;
                $this -> body_length    = 0;


            break;

        } // End Switch

        return;

    } // End Method restoreDefaults

/**
 * Set Global Parameters For Primary Scan
 *
 * @param &$set_param ( array -> Data Required To Determine Scan Settings )
 *
 * @return void
 */

function setGlobalParameters( &$set_param )
    {
        // Load The Post Variable Names Into The Array
        // These Generally Apply To Textarea Data

        if ( ! empty( $set_param['clickit_form'] ) )
        {
            if ( (bool)FALSE !== strpos( $set_param['clickit_form'], '|' ) )
            {
                $this -> click_ary = explode( '|' , $set_param['clickit_form'] );
            }
            else
            {
                $this -> click_ary = array( $set_param['clickit_form'] );
            }
        }

        // Load The Post Variable Names Into The Array
        // These Generally Apply To Textbox Data

        if ( ! empty( $set_param['stripit_form'] ) )
        {
            if ( (bool)FALSE !== strpos( $set_param['stripit_form'], '|' ) )
            {
                $this -> strip_ary = explode( '|' , $set_param['stripit_form'] );
            }
            else
            {
                $this -> strip_ary = array( $set_param['stripit_form'] );
            }
        }

        // Load The Post Variable Names Into The Array
        // These Generally Apply To Post Data That Contains Binary Data

        if ( ! empty( $set_param['mpn_binary'] ) )
        {
            if ( (bool)FALSE !== strpos( $set_param['mpn_binary'], '|' ) )
            {
                $this -> bin_ary = explode( '|' , $set_param['mpn_binary'] );
            }
            else
            {
                $this -> bin_ary = array( $set_param['mpn_binary'] );
            }
        }

        // Set The Allowed HTML Tag Array For The Appropriate User

        if ( ! empty( $set_param['allow_html'] ) )
        {
            $this -> scan_taglist = $set_param['allow_html'];

            if ( is_bool( $this -> scan_taglist[0] ) )
            {
                $this -> scan_rmtags = array_shift( $this -> scan_taglist );
            }

            // Normalize

            array_walk( $this -> scan_taglist, array( $this, 'casenormalize' ) );
        }

        // Set The Allowed BBCode Tag Array For The Appropriate User

        if ( ! empty( $set_param['allow_bbcode'] ) )
        {
            $this -> bbtaglist = $this -> scan_bbtaglist = $set_param['allow_bbcode'];

            if ( is_bool( $this -> scan_bbtaglist[0] ) )
            {
                $this -> bbrmtags = $this -> scan_bbrmtags = array_shift( $this -> scan_bbtaglist );
            }

            // Normalize

            array_walk( $this -> scan_bbtaglist, array( $this, 'casenormalize' ) );
        }

        // Set The Form Section Type For This Page Load

        if ( ! empty( $set_param['mpn_sectype'] ) )
        {
            $this -> sectype = (int)$set_param['mpn_sectype'];
        }

    } // End Method setGlobalParameters

/**
 * Set Per Request Variable Scan Parameters For Primary Scan
 *
 * @param &$set_param ( array -> Data Required To Determine Scan Settings )
 * @param &$varname   ( string -> Current Variable Being Scanned )
 *
 * @return void
 */

function setScanParameters( &$set_param, &$varname )
    {
        //$this -> wsDump( "Method checkInput: <b>Setting Per Variable Parameters</b>\n" );

        // If Variable Name Is In The click_ary, Set Some Runtime Parameters

        if ( ! empty( $this -> click_ary ) && in_array( $varname, $this -> click_ary ) )
        {
            $this -> make_clickable = (bool)TRUE;
            $this -> encode_smileys = (bool)TRUE;
            $this -> format_text    = (bool)TRUE;

            // Enable The BBEncoder If Necessary

            if ( ! empty( $set_param['mpn_encode'] ) )
            {
                $this -> bbencoder_on = (bool)TRUE;
            }

            // Disable Smileys If Necessary

            if ( ! empty( $set_param['smile'] ) )
            {
                $this -> encode_smileys = (bool)FALSE;
            }

            if ( $this -> sectype != 0 )
            {
                // Return Literal Content If Required

                if ( ! empty( $set_param['literal'] ) )
                {
                    $this -> return_literal = (bool)TRUE;
                }

                // If Pure HTML Is Desired, Change The Final Storage Format

                if ( ! empty( $set_param['purehtml'] ) )
                {
                    $this -> pure_html  = (bool)TRUE;
                }

                // Add Slashes If Final Destination is Database

                if ( $this -> sectype === 2 && ! in_array( $varname, $this -> bin_ary ) )
                {
                    $this -> add_slashes = (bool)TRUE;
                }

                // Strip ALL BBCode Tags And Content If Not BBEncoding

                if ( ! $this -> bbencoder_on && ! $this -> return_literal )
                {
                    $this -> strip_tags = array( '[' );
                }

                // Enable Auto Tag Closing If Open Tags Are Not Closed

                $this -> force_tag_closing = (bool)TRUE;
            }
        }

        // Strip ALL HTML From Variables In This Array
        // Add Slashes If Final Destination Is Database

        if ( ! empty( $this -> strip_ary ) && in_array( $varname, $this -> strip_ary ) )
        {
            $this -> taglist = array();
            $this -> rmtags  = (bool)TRUE;

            if ( $this -> sectype === 2 && ! in_array( $varname, $this -> bin_ary ) )
            {
                $this -> add_slashes = (bool)TRUE;
            }
        }

        // Disable Stripslashes For This Variable If Binary Data

        if ( $this -> strip_slashes && in_array( $varname, $this -> bin_ary ) )
        {
            $this -> strip_slashes = (bool)FALSE;
        }

    } // End method setScanParameters

/**
 * This Child Class Checks All Input $_REQUEST Variables
 *
 * To protect your site from malicious code and hack attempts
 * call this function either on every page,
 * or if you have an include that is required for every page request, call it there.
 *
 * It checks both HTML and BBCode Style Tags
 *
 * @param  $set_param = Req   ( Array -> Data Required To Determine Scan Settings )
 * @param  $chkRvar   = NULL  ( Array -> restricted gPc variable names )
 * @param  $chkGPvar  = NULL  ( Array -> restricted gP variable names )
 * @param  $chkuri    = TRUE  ( Bool  -> check requested URI for malicious code )
 *
 * @return  void
 */

function checkInput(   $set_param
                     , $chkRvar  = NULL
                     , $chkGPvar = NULL
                     , $chkuri   = TRUE
                   )
    {
        global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS;

        $checkAll = array_merge( $_REQUEST, $HTTP_GET_VARS, $_GET, $HTTP_POST_VARS, $_POST, $HTTP_COOKIE_VARS, $_COOKIE );

        // Check Request Uri If Required

        if ( $chkuri && (bool)TRUE !== $this -> validateInput( 'request_uri', 1 ) )
        {
            exit( '<h1>!- ACCESS DENIED -!</h1>' );
        }

        // Check Get/Post Variable Names If Required

        if ( empty( $checkAll ) )
        {
            return;
        }

        if ( ! empty( $chkGPvar ) )
        {
            $tmpary = array_keys( array_merge( $HTTP_GET_VARS, $_GET, $HTTP_POST_VARS, $_POST ) );

            foreach( $chkGPvar AS $v )
            {
                if ( in_array( $v , $tmpary ) )
                {
                    exit( '<h1>!-! ACCESS DENIED !-!</h1>' );
                }
            }

            unset( $tmpary );

        } // End GP Check

        // CHECK AND SANITIZE ALL REQUEST VARIABLES

        $this -> init_pass = (bool)TRUE;

        // Set Global Runtime Parameters

        if ( ! empty( $set_param ) )
        {
            $this -> setGlobalParameters( $set_param );
        }

        // Set Defaults For First Pass

        $this -> restoreDefaults( 2 );

        //$this -> wsDump( "Method checkInput: <b>Checking ALL Request Variables</b>\n"   );

        foreach( $checkAll AS $key => $v )
        {
            $protect_key = (bool)FALSE;

            // Check checkAll Array For Restricted Variable Names

            if ( ! empty( $chkRvar ) && in_array( $key, $chkRvar ) )
            {
               exit( '<h1>!!-! ACCESS DENIED !-!!</h1>' );
            }

            // Set Per Variable Scan Parameters

            $this -> setScanParameters( $set_param, $key );

            if ( ! empty( $this -> strip_ary ) && in_array( $key, $this -> strip_ary ) )
            {
                $v = $this -> stripQuotes( $v, 'double' );
            }

            if ( $this -> return_literal )
            {
                $this -> protectContent( $this -> slashIT( $v ), 1, 1 );
            }

            // Protect This Variable if Admin Is Trusted

            if ( _ADMIN_TRUSTED && ( ! empty( $GLOBALS['protectKeys'] ) && in_array( $key, $GLOBALS['protectKeys'] ) ) )
            {
                //$this -> wsDump( "Method checkInput: <b>PROTECTING ADMIN CONTENT: {$key}</b>\n" );

                $this -> proc_type = 5;
            }

            // Sanitize

            //$this -> wsDump( "Method checkInput: <h3>SANITIZING HTML</h3>\n" );

            $checkAll[ $key ] = $this -> sanitize( $v );

            // Replace All Registered GPC Variables With Sanitized Version

            //$this -> wsDump( "Method checkInput: <b>Replacing GPC Globals With Sanitized Version</b>\n" );

            $this -> replaceGPC_Globals( $key, $checkAll[ $key ] );

            $this -> restoreDefaults( 2 );

        } // End HTML GPC Check / Clean

        $this -> restoreDefaults( 1 );

        return;

    } // End Method

/**
 * This is the main entry point for sanitizing
 * Parameter arrays can be found in core_Sanitize.param.php
 * And Are Loaded Into The Class By The Parent Constructor
 *
 * @param string  $body                   The string with HTML you wish to filter.
 * @param integer $type       (optional)  How do you want to process the string.
 * @param bool    $auto_close (optional)  Close Any Open Tags.
 * @param array   $tag_list   (optional)  Optional runtime tag_list.
 * @param array   $legacy     (optional)  Used To Enable / Disable Free Content Actions
 *
 * Scan Type Options:
 *     1 -> Normal Processing
 *     2 -> Skip Add Attributes
 *     3 -> Skip Remove Tags With Content
 *     4 -> Skip Fixing Attributes
 *     5 -> Skip All Except Allowed Tags
 *
 *
 * @return string -> sanitized content
 */

function sanitize(   $content
                   , $type       = NULL
                   , $auto_close = NULL
                   , $strip      = NULL
                   , $tag_list   = NULL
                   , $legacy     = array( FALSE, TRUE, FALSE )
                 )
    {
        $me = 'Method sanitize';
        $num_args = func_num_args();
        $allow_reset = (bool)FALSE;

        // Reset Parent Class Variable Defaults If Not Initial Scan

        if ( ! $this -> init_pass || $num_args >= 5 )
        {
            $allow_reset = (bool)TRUE;
            $this -> restoreDefaults( 1 );
        }

        /**
         * Reinitialized Variables If Required
         *
         * Note: First 5 Arguments Must Be Present To Reinitialized
         */

        if ( $allow_reset )
        {
            // Replace Parent Variables With Arguments For This Sanitizer Pass

            $this -> proc_type = ( ! empty( $type ) ) ? ( $type ) : ( $this -> run_proc_type );
            $this -> force_tag_closing = ( ! empty( $auto_close ) ) ? ( $auto_close ) : ( $this -> run_auto_close );
            $this -> strip_tags = ( ! empty( $strip ) ) ? ( $strip ) : ( $this -> run_strip_tags );

            $this -> taglist = ( ! empty( $tag_list ) ) ? ( $tag_list ) : ( $this -> tag_list );

            if ( $legacy[0] )
            {
                if ( $legacy[1] ) { $this -> make_clickable = (bool)TRUE; }
                if ( $legacy[2] ) { $this -> encode_smileys = (bool)TRUE; }
            }
        }

        if ( ! empty( $this -> taglist ) && is_bool( $this -> taglist[0] ) )
        {
            $this -> rmtags = array_shift( $this -> taglist );

            // Normalize

            array_walk( $this -> taglist, array( $this, 'casenormalize' ) );
        }

        if ( $this -> strip_slashes )
        {
            $this -> slashIT( $content );
        }

        // Run The Content Through The Sanitizer

        if ( is_array( $content ) )
        {
            foreach( $content AS $key => $v )
            {
                $body[ $key ] = $this -> sanitizeContent( $v );
            }
        }
        else
        {
            $body = $this -> sanitizeContent( $content );
        }

        if ( $this -> add_slashes )
        {
            $this -> slashIT( $body, TRUE );
        }

        return $body;

    } // End Method sanitize

/**
 * This was the main sanitizing function "sanitize" originally from htmlfilter.inc.
 *
 * The original function has been extensively modified for the WebSanitizer.
 * Any portions of this method which can be reasonably considered
 * as a part of htmlfilter.inc are copyright protected by Duke University.
 * (See htmlfilter.inc copyright and notices in core_Sanitizer.class.php)
 *
 * Scan Type Options:
 *     1 -> Normal Processing
 *     2 -> Skip Add Attributes
 *     3 -> Skip Remove Tags With Content
 *     4 -> Skip Attribute Checks
 *     5 -> Skip All Except Allowed Tags
 *
 * @param string  ( $body -> The string to filter. )
 *
 * @return string -> sanitized content
 */

function sanitizeContent( $body )
    {
        $me = 'Method sanitize';

        // Initialize Sanitizer Loop Variables

        $curpos       = 0;
        $trusted      = '';
        $open_tags    = array();
        $skip_content = (bool)FALSE;
        $found_tag    = (bool)FALSE;
        $this -> cleanup = (bool)FALSE;

        /**
         * Take care of netscape's stupid javascript entities like
         * &{alert('boo')};
         */

        $body = preg_replace( '/&(\{.*?\};)/si', '&amp;\\1', $body );

        $this -> body_length = strlen( $body );

        //$this -> wsDump( "$me: INVOKING THE LOOP NOW\n" );

        /**
         * Invoke The Loop
         */

        while ( (bool)FALSE !== ( $curtag = $this -> getnxtag( $body, $curpos ) ) )
        {
            list( $tagname, $attary, $tagtype, $lt, $gt ) = $curtag;

            /**
             * Append Free Content To Trusted
             */

            if ( (bool)FALSE === $skip_content )
            {
                $cleanup     = ( $curpos == 0 ) ? ( 1 ) : ( 0 );

                $skip_action = ( $tagtype == 2 && in_array( $tagname, $this -> skip_action_tag ) )
                             ? ( (bool)TRUE )
                             : ( (bool)FALSE );

                if ( $this -> add_pos_comm && ( $curpos - $this -> add_pos_tracker ) >= $this -> add_pos_inc )
                {
                    $this -> add_pos_tracker = $curpos;

                    $trusted .= "\n" . '<!--|[' . $curpos . ']|-->' . "\n";
                }

                $trusted .= $this -> freeContent( $body, $lt, $curpos, $cleanup, $skip_action );
            }
            else
            {
                //$this -> wsDump( "$me: Skipping free content.\n" );
            }

            /**
             * If Tag Delimiter Is In The Strip By Delimiter Array,
             * Remove The Tag And Content Unconditionally
             * Additionally Remove Any Content And Tags That Are Not Allowed
             */

            if ( (bool)FALSE !== $skip_content || in_array( substr( $body, $lt, 1 ), $this -> strip_tags ) )
            {
                $curpos = $gt + 1;

                if ( $skip_content === (bool)FALSE )
                {
                    if ( $tagtype != 3 )
                    {
                        // Found Opening Tag, Start Content Skipping

                        //$this -> wsDump( "$me: <b>Removing Invalid Tagset <i>{$skip_content}</i> With Content</b>\n" );

                       $skip_content = $tagname;
                    }
                    else // Found A Self-Closing Tag, Skip The Tag
                    {
                        //$this -> wsDump( "$me: <b>Removing Invalid Type 3 Tag <i>{$tagname}</i></b>\n" );
                    }
                }
                else
                {
                    if ( $skip_content == $tagname && $tagtype == 2 )
                    {
                        // Found the Closing Tag, Stop Skipping And Continue

                        //$this -> wsDump( "$me: <b>Finished Removing Invalid Tagset <i>{$skip_content}</i></b>.  Continuing With Normal Scanning\n" );

                        $skip_content = (bool)FALSE;
                    }
                }

                continue;
            }

            /**
             * Check Current Tag Against Protected Content Tag Array
             *
             * If tag is found, protect the content contained between
             * opening and closing tags and append to trusted content
             */

            if (    (bool)FALSE === $skip_content
                 && $tagtype == 1
                 && ! empty( $this -> protect_content )
                 && in_array( $tagname, $this -> protect_content )
               )
            {
                $protect = $this -> getProtectedContent( $body, $lt, $tagname );

                if ( (bool)FALSE !== $protect && $protect[0] != '' )
                {
                    //$this -> wsDump( "$me: Appending Protected Content To Trusted.\n" );

                    $trusted .= $protect[0];
                    $curpos   = $protect[1];

                    continue;
                }
                else if ( is_integer( $protect[1] ) )
                {
                    // Found Content To Protect, But Not In Users Allowed Tag Array
                    // Remove The Tag And Content

                    //$this -> wsDump( "$me: Found Protected Content But Is Not In Allowed Tag Array. Discarding Tag Set And Content.\n" );

                    $curpos = $protect[1];
                    continue;
                }
                else
                {
                    // Something Went Wrong, We Should Never Get Here
                    // Remove The Tag And It's Content

                    //$this -> wsDump( "$me: Found A Protected Tag But Failed To Verify In Protected Tag Scan. Discarding Invalid Tag And Content.\n" );

                    $skip_content = $tagname;
                    $tagname = (bool)FALSE;
                }
            }

            /**
             * Check The Tag If It Hasn't Already
             * Been Determined As Invalid
             */

            if ( (bool)FALSE === $tagname )
            {
                //$this -> wsDump( "$me: <h4>Removing invalid tag</h4>\n" );
            }
            else
            {
                if ( (bool)FALSE === $skip_content && ! in_array( $tagname, $this -> self_closing_tags ) )
                {
                    $tagtrack = $this -> tagprint( $tagname, array(), 2 );
                }

                $this -> processTag(   $skip_content
                                     , $tagname
                                     , $tagtype
                                     , $open_tags
                                     , $attary
                                     , $tagtrack
                               );

                if ( (bool)FALSE !== $tagname && (bool)FALSE === $skip_content )
                {
                    //$this -> wsDump( "$me: Appending tag to trusted.\n" );

                    $trusted .= $this -> tagprint( $tagname, $attary, $tagtype );
                }
            }

            $curpos = $gt + 1;

        } // End While/Do

        //$this -> wsDump( "$me: Appending any leftover   content\n" );

        $trusted .= $this -> freeContent( $body, $this -> body_length, $curpos, 2 );

        /**
         * Close Open Tags If Required
         */

        if ( (bool)TRUE === $this -> force_tag_closing && ! empty( $open_tags ) )
        {
            $this -> closeTags( $trusted, $open_tags );
        }

        // Scan Body For Restricted Doms if Necessary

        if ( $this -> chkall_restricted_doms )
        {
            $trusted = str_replace( $this -> restricted_doms, ' ', $trusted );
        }

        // Apply Final Formatting Changes

        if ( $this -> format_text )
        {
            $this -> trimContent( $trusted );

            if ( ! $this -> pure_html )
            {
                $this -> adjustFormat( $trusted, 3, 9 );
            }
            else
            {
                $this -> adjustFormat( $trusted, 3, 12 );
            }
        }

        $this -> trimContent( $trusted );

        return $trusted;

    } // End Method sanitized

/**
 * Format Legacy Content
 *
 * $param $text    -> string
 * $param $slashit -> bool ( addslashes )
 *
 * return string ( Formatted $text )
 */

function sanitizeLegacyContent( &$text, $strip = NULL, $click = TRUE, $smile = FALSE )
    {
        // REFERENCE: sanitize( $body, $type = NULL, $auto_close = NULL, $strip = NULL, $tag_list = NULL, $legacy = FALSE )

        $strip = ( empty( $strip ) ) ? ( array( '[' ) ) : ( $strip );

        if ( $click || $smile )
        {
            if ( _SAN_LEGACY_SCAN_ || _SAN_LEGACY_FORUM_ )
            {

                if ( is_array( $text ) )
                {
                    foreach( $text AS $key => $v )
                    {
                        $this -> undoHtmlSpecialChars( $text[ $key ] );
                    }
                }
                else
                {
                    $this -> undoHtmlSpecialChars( $text );
                }

                $text = $this -> sanitize( $text, _SAN_LEGACY_LEVEL_, TRUE, $strip, NULL, array( TRUE, $click, $smile ) );
            }
            else if ( ! _SAN_LEGACY_FORUM_ )
            {
                if ( $click ) { $text = $this -> makeClickable( $text ); }
                if ( $smile ) { $text = $this -> linkSmiley( $text ); }
            }
        }

        if ( is_array( $text ) )
        {
            foreach( $text AS $key => $v )
            {
                $text[ $key ] = nl2br( $v );
            }
        }
        else
        {
            $text = nl2br( $text );
        }

        // Wrap Code And Blockquote Tags With A Division

        $this -> adjustHTML( $text );

        return $text;

    } // End Method sanitizeLegacyContent

/**
 * This Method Is Used With The New Sanitizer
 *
 * It inserts / replaces any other required strings
 * into the message during page loading
 *
 * $param string  ( &$message -> ( string to parse )
 * $param string  ( $usersig  -> ( strip or replace [addsig] )
 *
 * @return void ( $message passed by reference )
 */

function adjustHTML( &$message, $usersig = NULL )
    {
        if ( is_array( $message ) )
        {
            foreach( $message AS $key => $v )
            {
               $this -> htmlReplace( $message[ $key ], $usersig );
            }
        }
        else
        {
            $this -> htmlReplace( $message, $usersig );
        }

        return;

    } // End Method adjustHTML

/**
 * Formatting Replacements For Method adjustHTML
 *
 * @return void
 */

function htmlReplace( &$content, $usersig )
{
    $srch = array
    (
          '<code>'
        , '</code>'
        , '<blockquote>'
        , '</blockquote>'
    );

    $repl = array
    (
          '<div class="codefrag"><p>!!! CODE !!!</p><code>'
        , '</code></div>'
        , '<div class="quote"><p>!!! QUOTE !!!</p><blockquote>'
        , '</blockquote></div>'
    );

    if ( (bool)FALSE == strpos( $content, '!-- BBCode' ) && ( (bool)FALSE !== strpos( $content, '<code>' ) || (bool)FALSE !== strpos( $content, '<blockquote>' ) ) )
    {
        $content = str_replace( $srch, $repl, $content );
    }

    if ( isset( $usersig ) && ( (bool)FALSE !== strpos( $content, '[addsig]' ) || (bool)FALSE !== strpos( $content, '[addsig /]' ) ) )
    {
        $sig_types = array( '[addsig]', '[addsig /]' );

        if ( $usersig != '' )
        {
            $content = str_replace( $sig_types, '<br /><br />-----------------<br />' . nl2br( $this -> adjustFormat( $usersig, 3, 10 ) ), $content );
        }
        else
        {
            $content = str_replace( $sig_types, '', $content );
        }
    }

    // MPN Specific Edited By Stamp Hiding

    if ( ! _MPN_ADMIN && _FORUM_RESTRICT_EDIT_STAMP_ && (bool)FALSE !== strpos( $content, 'class="forumsig"' ) )
    {
        $srch = array( '<br /><br /><div class="forumsig">', '<div class="forumsig">', ' ]</div><br /><br />' );
        $repl = array( '<div class="invisi">', '<div class="invisi">', ']</div>' );

        $content = str_replace( $srch, $repl, $content );
    }

    return;

} // End Method

/**
 * Format Forum Posts For Display
 *
 * @param string  &$post     ( Content to format )
 * @param string  $postedby  ( Content Posted By Name )
 *
 * @return void ( $post passed by reference )
 */

function formatPost( &$post, $postedby )
    {
        $this -> adjustFormat( $post, 3, 10 );
        $this -> adjustHTML( $post, $postedby );

        return $post;

    } // End Method formatPost

/**
 * Verifies / Validates Input Content
 *
 * Provides basic content and form field validation
 *
 * Validation Options:
 *    1) Check For Valid URI
 *    2) Check For Valid Email
 *    3) Check For Empty String
 *    4) Check For Text Only String
 *    5) Check For Num Only String
 *
 * @param string / array  ( $content -> string or array of strings to validate )
 * @param integer         ( $type -> scan type )
 *
 * @return bool ( TRUE = Passed, FALSE = Failed )
 *
 * Note: If an array is passed, an array of bool results
 * keyed the same as the input array is returned
 */

function verifyContent( $content, $type )
    {
        if ( ! is_integer( $type ) )
        {
           return (bool)FALSE;
        }

        if ( is_array( $content ) )
        {
            foreach( $content AS $key => $v )
            {
                $results[ $key ] = $this -> validateInput( $v, $type );
            }
        }
        else
        {
            $results = $this -> validateInput( $content, $type );
        }

        return $results;

    } // End Method verifyContent

} // End Sub-Class

?>