<?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 -> BBCode Secondary Scanner Subclass      |
// |                                                                      |
// |   BBcode Input / Output Secondary 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.                |
// +----------------------------------------------------------------------+
// | CONTRIBUTOR(s):                                                      |
// |                                                                      |
// +----------------------------------------------------------------------+
// | MODIFICATIONS:                                                       |
// |                                                                      |
// |                                                                      |
// +----------------------------------------------------------------------+
// | REQUIRED FILES: core_Sanitize.class.php                              |
// |                 core_CheckInput.subclass.php                         |
// |                 core_Sanitize.param.php                              |
// |                 core_AllowArrays.param.php ( MPN Option )            |
// +----------------------------------------------------------------------+
// | NOTES: Extends class Sanitize and is used to encode / decode forum   |
// | messages and other bbcode text                                       |
// +----------------------------------------------------------------------+
// | IMPORTANT:                                                           |
// |   This Subclass Is Intended For Secondary Sanitizing.                |
// |                                                                      |
// |   Specific checks were left out of this class in order to            |
// |   increase perfomance and to avoid redundant checks that the         |
// |   CheckInput Subclass already covered.                               |
// |   Unexpected results could occur if you don't run CheckInput first.  |
// +----------------------------------------------------------------------+
// | SUPPORT: http://myphpnuke.com/                                       |
// +----------------------------------------------------------------------+
// $Id: core_BBCodeConvert.subclass.php,v 1.11.2.12 2004/08/15 12:58:25 kirilt Exp $

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


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

    var $debug                 = FALSE;

    /**
     * Enable / Disable tag closing
     *
     * Tags set in self_closing_tags array
     *
     * @var bool
     */

    var $force_tag_closing     = TRUE;

    /**
     * Add User Signature
     * Determined In Mainfile
     *
     * @var bool
     */

    var $addsig                = FALSE;

    /**
     * Add Attributes To Tags
     *
     * @var bool
    */

    var $add_attrib            = TRUE;

    /**
     * BBCode Swap
     *
     * The array of bb tags and their corresponding HTML tag
     * Array Entries: bbtag => html replacement tag
     *
     * @var array
     */

    var $bb_swap               = array();

    /**
     * Re-initializing the parent variable
     *
     * @var array
     */

    var $strip_tags            = array();

    /**
     * Protect Content Tag Array
     * Default: Protect None
     *
     * @var array
     */

    var $protect_content       = array( 'code', 'lit' );

    /**
     * Allow HTML
     * Default: NO
     *
     * @var bool
     */

    var $allow_html            = FALSE;

    /**
     * Allow BBCode
     * Default: TRUE
     *
     * @var bool
     */

    var $allow_bbcode          = TRUE;

    /**
     * Edited By Stamp Location
     * Default: bottom
     *
     * @var string ( 'top' or 'bottom' )
     */

    var $editby_loc            = 'bottom';

    /**
     * Subclass BBCodeConvert Constructor
     *
     * @param   $allow_html     ( Bool  -> allow / disallow html, Default TRUE )
     *          $allow_bbcode   ( Bool  -> allow / disallow bbcode, Default TRUE )
     *          $addsig         ( Bool  -> Add Users Signature, Default FALSE )
     *          $param_arrays   ( Array -> Custom Runtime Parameter Arrays, Default NULL )
     *          $allowed_bbtags ( Array -> Custom Runtime BBCode Allowed Tag Array, Default NULL )
     *
     * @return  void
     */

    function BBCodeConvert( $allow_html = TRUE, $allow_bbcode = TRUE, $addsig = FALSE, $param_arrays = NULL, $allowed_bbtags = NULL )
    {
        // Check Incoming Runtime Arguments And Adjust If Necessary

        if ( ! empty( $param_arrays ) )
        {
            require $param_arrays;
        }
        else
        {
            require './classes/subs/sanitizer/core_BBCodeConvert.param.php';
        }

        // Allow / Disallow HTML Tags, Strip tags and content if FALSE

        if ( (bool)TRUE === $allow_html )
        {
            $this -> allow_html = (bool)TRUE;
        }

        // Allow / Disallow BBCode Tags, Strip tags and content if FALSE

        if ( (bool)FALSE == $allow_bbcode )
        {
            $this -> allow_bbcode = (bool)FALSE;
        }

        // Add User Signature

        if ( $addsig ) { $this -> addsig = (bool)TRUE; }

        // Runtime Allowed BBCode Tag Array ( Resets $bb_tag Array From Param File )

        if ( empty( $this -> bbtaglist ) )
        {
            $this -> taglist = $this -> bbtaglist = ( ! empty( $allowed_bbtags ) ) ? ( $allowed_bbtags ) : ( $bb_tags );
        }
        else
        {
            $this -> taglist = $_SERVER['SAN'] -> bbtaglist;

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

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

            // Normalize

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

        // Holds The BBCode Swap Tags

        if ( ! empty( $bb_swap ) ) { $this -> bb_swap = $bb_swap; }

        // Add Attributes To Tags

        if ( ! empty( $add_attr_to_tag ) ) { $this -> add_attr_to_tag = $add_attr_to_tag; }

        return;

    } // End Constructor

    /**
     * BBEncodes / BBDecodes Body Of Text
     *
     * It checks both HTML and BBCode Style Tags
     *
     * @param   $body   ( string -> content to process )
     *          $encode ( bool   -> encode(TRUE) / decode(FALSE) content )
     *          $edited ( bool   -> message is being edited )
     *          $editby ( bool   -> message edited by username )
     *
     * @return  string -> Encoded / Decoded String
    */

    function BBConversion( $body, $encode, $edited = FALSE, $editby = '' )
    {
        // Set Encoding / Decoding Conditions & Variables

        if ( $encode )
        {
            $encode = (bool)TRUE;
            $print_tag = $this -> bb_swap;
            $delim = $this -> html_delim;
            $this -> strip_tags = array();

            // If Not Returning Literally, Set strip_tags Array

            if ( ! $this -> return_literal )
            {
                if ( ! $this -> allow_html )
                {
                    $this -> strip_tags[] = '<';
                }

                if ( ! $this -> allow_bbcode )
                {
                    $this -> strip_tags[] = '[';
                }
            }
        }
        else // Decoding
        {
            $encode = (bool)FALSE;
            $this -> taglist = $this -> bb_swap;
            $print_tag = array_flip( $this -> bb_swap );
            $delim = $this -> bb_delim;
            $this -> strip_tags = array( '[' );
        }

        // Adjust Format For Parsing

        $this -> adjustFormat( $body, 3, 11 );

        // Initialize Variables

        $meth = 'BBConversion';

        $curpos = 0;
        $trusted = '';
        $open_tags = array();
        $skip_content = (bool)FALSE;
        $this -> body_length = strlen( $body );

        //$this -> wsDump( "$meth: invoking the loop\n" );

        // Process The Body

        if ( $encode && $edited && $this -> editby_loc == 'top' )
        {
            $trusted .= '<div class="forumsig">[ ' . translate( 'This message was edited by:' ) . ' ' . $editby . ' ' . translate( 'on' ) . ' ';

            $trusted .= strftime( translate( 'forumdatestring2' ), _MPN_TIMESTAMP );

            $trusted .= " ]</div><br /><br />";
        }

        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 );

                $trusted .= $this -> freeContent( $body, $lt, $curpos, $cleanup, $skip_action );
            }
            else
            {
                //$this -> wsDump( "$meth: 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 || ! isset( $print_tag[ $tagname ] ) || 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( "$meth: <b>Removing Invalid Tagset <i>{$skip_content}</i> With Content</b>\n" );

                        $skip_content = $tagname;
                    }
                    else // Self-Closing Tag, Skip The Tag
                    {
                        //$this -> wsDump( "$meth: <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( "$meth: <b>Finished Removing Invalid Tagset <i>{$skip_content}</i></b>.  Continuing With Normal Scanning\n" );

                        $skip_content = (bool)FALSE;
                    }
                }

                continue;
            }

            /**
             * If Decoding, Check If We Have Any Protected Content Present In Body
             * If We Do, Get the Protected Content and Append To Trusted
             * Additionally, We Bypass Any Further Action On That Content
             */

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

                if ( (bool)FALSE !== $protect )
                {
                    //$this -> wsDump( "$meth: Skipping Over Previous Protected Content And Appending " . strlen( $protect[0] ) . " Chars To Trusted Content.\n" );

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

                    continue;
                }
            }

            /**
             * Run All Other Checks
             * If We Have A Valid Tag, Append It To Trusted.
             */

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

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

                if ( (bool)FALSE !== $tagname && (bool)FALSE === $skip_content )
                {
                    //$this -> wsDump( "$meth: Swapping Tag Delimiters And Appending Tag To Trusted.\n" );

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

            $curpos = $gt + 1;

        } // End While/Do

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

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

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

        // Encoding Specific Adjustments

        if ( $encode )
        {
            if ( $this -> addsig )
            {
                $trusted .= "\n[addsig /]\n";
            }

            if ( $edited && $this -> editby_loc == 'bottom' )
            {
                $trusted .= '<br /><br /><div class="forumsig">[ ' . translate( 'This message was edited by:' ) . ' ' . $editby . ' ' . translate( 'on' ) . ' ';

                $trusted .= strftime( translate( 'forumdatestring2' ), _MPN_TIMESTAMP );

                $trusted .= " ]</div>";
            }

            // Adjust Formatting For Screen Display

            $this -> adjustFormat( $trusted, 3, 9 );
        }

        $this -> trimContent( $trusted );

        return $trusted;

    } // End Method BBConversion

} // End Child Class

?>