!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: nginx/1.23.4. PHP/5.6.40-65+ubuntu20.04.1+deb.sury.org+1 

uname -a: Linux foro-restaurado-2 5.15.0-1040-oracle #46-Ubuntu SMP Fri Jul 14 21:47:21 UTC 2023
aarch64
 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/usr/share/nginx/html/phpbb3/forumrunner/support/   drwxrwxr-x
Free 83.35 GB of 96.73 GB (86.17%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     stringparser_bbcode.class.php (53.83 KB)      -rw-rw-r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/**
 * BB code string parsing class
 *
 * Version: 0.3.3
 *
 * @author Christian Seiler <[email protected]>
 * @copyright Christian Seiler 2004-2008
 * @package stringparser
 *
 * The MIT License
 *
 * Copyright (c) 2004-2008 Christian Seiler
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
 
require_once(MCWD '/support/stringparser.class.php');

define ('BBCODE_CLOSETAG_FORBIDDEN', -1);
define ('BBCODE_CLOSETAG_OPTIONAL'0);
define ('BBCODE_CLOSETAG_IMPLICIT'1);
define ('BBCODE_CLOSETAG_IMPLICIT_ON_CLOSE_ONLY'2);
define ('BBCODE_CLOSETAG_MUSTEXIST'3);

define ('BBCODE_NEWLINE_PARSE'0);
define ('BBCODE_NEWLINE_IGNORE'1);
define ('BBCODE_NEWLINE_DROP'2);

define ('BBCODE_PARAGRAPH_ALLOW_BREAKUP'0);
define ('BBCODE_PARAGRAPH_ALLOW_INSIDE'1);
define ('BBCODE_PARAGRAPH_BLOCK_ELEMENT'2);

/**
 * BB code string parser class
 *
 * @package stringparser
 */
class StringParser_BBCode extends StringParser {
    
/**
     * String parser mode
     *
     * The BBCode string parser works in search mode
     *
     * @access protected
     * @var int
     * @see STRINGPARSER_MODE_SEARCH, STRINGPARSER_MODE_LOOP
     */
    
var $_parserMode STRINGPARSER_MODE_SEARCH;
    
    
/**
     * Defined BB Codes
     *
     * The registered BB codes
     *
     * @access protected
     * @var array
     */
    
var $_codes = array ();
    
    
/**
     * Registered parsers
     *
     * @access protected
     * @var array
     */
    
var $_parsers = array ();
    
    
/**
     * Defined maximum occurrences
     *
     * @access protected
     * @var array
     */
    
var $_maxOccurrences = array ();
    
    
/**
     * Root content type
     *
     * @access protected
     * @var string
     */
    
var $_rootContentType 'block';
    
    
/**
     * Do not output but return the tree
     *
     * @access protected
     * @var bool
     */
    
var $_noOutput false;
    
    
/**
     * Global setting: case sensitive
     *
     * @access protected
     * @var bool
     */
    
var $_caseSensitive true;
    
    
/**
     * Root paragraph handling enabled
     *
     * @access protected
     * @var bool
     */
    
var $_rootParagraphHandling false;
    
    
/**
     * Paragraph handling parameters
     * @access protected
     * @var array
     */
    
var $_paragraphHandling = array (
        
'detect_string' => "\n\n",
        
'start_tag' => '<p>',
        
'end_tag' => "</p>\n"
    
);
    
    
/**
     * Allow mixed attribute types (e.g. [code=bla attr=blub])
     * @access private
     * @var bool
     */
    
var $_mixedAttributeTypes false;
    
    
/**
     * Whether to call validation function again (with $action == 'validate_auto') when closetag comes
     * @access protected
     * @var bool
     */
    
var $_validateAgain false;
    
    
/**
     * Add a code
     *
     * @access public
     * @param string $name The name of the code
     * @param string $callback_type See documentation
     * @param string $callback_func The callback function to call
     * @param array $callback_params The callback parameters
     * @param string $content_type See documentation
     * @param array $allowed_within See documentation
     * @param array $not_allowed_within See documentation
     * @return bool
     */
    
function addCode ($name$callback_type$callback_func$callback_params$content_type$allowed_within$not_allowed_within) {
        if (isset (
$this->_codes[$name])) {
            return 
false// already exists
        
}
        if (!
preg_match ('/^[a-zA-Z0-9*_!+-]+$/'$name)) {
            return 
false// invalid
        
}
        
$this->_codes[$name] = array (
            
'name' => $name,
            
'callback_type' => $callback_type,
            
'callback_func' => $callback_func,
            
'callback_params' => $callback_params,
            
'content_type' => $content_type,
            
'allowed_within' => $allowed_within,
            
'not_allowed_within' => $not_allowed_within,
            
'flags' => array ()
        );
        return 
true;
    }
    
    
/**
     * Remove a code
     *
     * @access public
     * @param $name The code to remove
     * @return bool
     */
    
function removeCode ($name) {
        if (isset (
$this->_codes[$name])) {
            unset (
$this->_codes[$name]);
            return 
true;
        }
        return 
false;
    }
    
    
/**
     * Remove all codes
     *
     * @access public
     */
    
function removeAllCodes () {
        
$this->_codes = array ();
    }
    
    
/**
     * Set a code flag
     *
     * @access public
     * @param string $name The name of the code
     * @param string $flag The name of the flag to set
     * @param mixed $value The value of the flag to set
     * @return bool
     */
    
function setCodeFlag ($name$flag$value) {
        if (!isset (
$this->_codes[$name])) {
            return 
false;
        }
        
$this->_codes[$name]['flags'][$flag] = $value;
        return 
true;
    }
    
    
/**
     * Set occurrence type
     *
     * Example:
     *   $bbcode->setOccurrenceType ('url', 'link');
     *   $bbcode->setMaxOccurrences ('link', 4);
     * Would create the situation where a link may only occur four
     * times in the hole text.
     *
     * @access public
     * @param string $code The name of the code
     * @param string $type The name of the occurrence type to set
     * @return bool
     */
    
function setOccurrenceType ($code$type) {
        return 
$this->setCodeFlag ($code'occurrence_type'$type);
    }
    
    
/**
     * Set maximum number of occurrences
     *
     * @access public
     * @param string $type The name of the occurrence type
     * @param int $count The maximum number of occurrences
     * @return bool
     */
    
function setMaxOccurrences ($type$count) {
        
settype ($count'integer');
        if (
$count 0) { // sorry, does not make any sense
            
return false;
        }
        
$this->_maxOccurrences[$type] = $count;
        return 
true;
    }
    
    
/**
     * Add a parser
     *
     * @access public
     * @param string $type The content type for which the parser is to add
     * @param mixed $parser The function to call
     * @return bool
     */
    
function addParser ($type$parser) {
        if (
is_array ($type)) {
            foreach (
$type as $t) {
                
$this->addParser ($t$parser);
            }
            return 
true;
        }
        if (!isset (
$this->_parsers[$type])) {
            
$this->_parsers[$type] = array ();
        }
        
$this->_parsers[$type][] = $parser;
        return 
true;
    }
    
    
/**
     * Set root content type
     *
     * @access public
     * @param string $content_type The new root content type
     */
    
function setRootContentType ($content_type) {
        
$this->_rootContentType $content_type;
    }
    
    
/**
     * Set paragraph handling on root element
     *
     * @access public
     * @param bool $enabled The new status of paragraph handling on root element
     */
    
function setRootParagraphHandling ($enabled) {
        
$this->_rootParagraphHandling = (bool)$enabled;
    }
    
    
/**
     * Set paragraph handling parameters
     *
     * @access public
     * @param string $detect_string The string to detect
     * @param string $start_tag The replacement for the start tag (e.g. <p>)
     * @param string $end_tag The replacement for the start tag (e.g. </p>)
     */
    
function setParagraphHandlingParameters ($detect_string$start_tag$end_tag) {
        
$this->_paragraphHandling = array (
            
'detect_string' => $detect_string,
            
'start_tag' => $start_tag,
            
'end_tag' => $end_tag
        
);
    }
    
    
/**
     * Set global case sensitive flag
     *
     * If this is set to true, the class normally is case sensitive, but
     * the case_sensitive code flag may override this for a single code.
     *
     * If this is set to false, all codes are case insensitive.
     *
     * @access public
     * @param bool $caseSensitive
     */
    
function setGlobalCaseSensitive ($caseSensitive) {
        
$this->_caseSensitive = (bool)$caseSensitive;
    }
    
    
/**
     * Get global case sensitive flag
     *
     * @access public
     * @return bool
     */
    
function globalCaseSensitive () {
        return 
$this->_caseSensitive;
    }
    
    
/**
     * Set mixed attribute types flag
     *
     * If set, [code=val1 attr=val2] will cause 2 attributes to be parsed:
     * 'default' will have value 'val1', 'attr' will have value 'val2'.
     * If not set, only one attribute 'default' will have the value
     * 'val1 attr=val2' (the default and original behaviour)
     *
     * @access public
     * @param bool $mixedAttributeTypes
     */
    
function setMixedAttributeTypes ($mixedAttributeTypes) {
        
$this->_mixedAttributeTypes = (bool)$mixedAttributeTypes;
    }
    
    
/**
     * Get mixed attribute types flag
     *
     * @access public
     * @return bool
     */
    
function mixedAttributeTypes () {
        return 
$this->_mixedAttributeTypes;
    }
    
    
/**
     * Set validate again flag
     *
     * If this is set to true, the class calls the validation function
     * again with $action == 'validate_again' when closetag comes.
     *
     * @access public
     * @param bool $validateAgain
     */
    
function setValidateAgain ($validateAgain) {
        
$this->_validateAgain = (bool)$validateAgain;
    }
    
    
/**
     * Get validate again flag
     *
     * @access public
     * @return bool
     */
    
function validateAgain () {
        return 
$this->_validateAgain;
    }
    
    
/**
     * Get a code flag
     *
     * @access public
     * @param string $name The name of the code
     * @param string $flag The name of the flag to get
     * @param string $type The type of the return value
     * @param mixed $default The default return value
     * @return bool
     */
    
function getCodeFlag ($name$flag$type 'mixed'$default null) {
        if (!isset (
$this->_codes[$name])) {
            return 
$default;
        }
        if (!
array_key_exists ($flag$this->_codes[$name]['flags'])) {
            return 
$default;
        }
        
$return $this->_codes[$name]['flags'][$flag];
        if (
$type != 'mixed') {
            
settype ($return$type);
        }
        return 
$return;
    }
    
    
/**
     * Set a specific status
     * @access protected
     */
    
function _setStatus ($status) {
        switch (
$status) {
            case 
0:
                
$this->_charactersSearch = array ('[/''[');
                
$this->_status $status;
                break;
            case 
1:
                
$this->_charactersSearch = array (']'' = "''="'' = \'''=\''' = ''='': '':'' ');
                
$this->_status $status;
                break;
            case 
2:
                
$this->_charactersSearch = array (']');
                
$this->_status $status;
                
$this->_savedName '';
                break;
            case 
3:
                if (
$this->_quoting !== null) {
                    if (
$this->_mixedAttributeTypes) {
                        
$this->_charactersSearch = array ('\\\\''\\'.$this->_quoting$this->_quoting.' '$this->_quoting.']'$this->_quoting);
                    } else {
                        
$this->_charactersSearch = array ('\\\\''\\'.$this->_quoting$this->_quoting.']'$this->_quoting);
                    }
                    
$this->_status $status;
                    break;
                }
                if (
$this->_mixedAttributeTypes) {
                    
$this->_charactersSearch = array (' '']');
                } else {
                    
$this->_charactersSearch = array (']');
                }
                
$this->_status $status;
                break;
            case 
4:
                
$this->_charactersSearch = array (' '']''="''=\'''=');
                
$this->_status $status;
                
$this->_savedName '';
                
$this->_savedValue '';
                break;
            case 
5:
                if (
$this->_quoting !== null) {
                    
$this->_charactersSearch = array ('\\\\''\\'.$this->_quoting$this->_quoting.' '$this->_quoting.']'$this->_quoting);
                } else {
                    
$this->_charactersSearch = array (' '']');
                }
                
$this->_status $status;
                
$this->_savedValue '';
                break;
            case 
7:
                
$this->_charactersSearch = array ('[/'.$this->_topNode ('name').']');
                if (!
$this->_topNode ('getFlag''case_sensitive''boolean'true) || !$this->_caseSensitive) {
                    
$this->_charactersSearch[] = '[/';
                }
                
$this->_status $status;
                break;
            default:
                return 
false;
        }
        return 
true;
    }
    
    
/**
     * Abstract method Append text depending on current status
     * @access protected
     * @param string $text The text to append
     * @return bool On success, the function returns true, else false
     */
    
function _appendText ($text) {
        if (!
strlen ($text)) {
            return 
true;
        }
        switch (
$this->_status) {
            case 
0:
            case 
7:
                return 
$this->_appendToLastTextChild ($text);
            case 
1:
                return 
$this->_topNode ('appendToName'$text);
            case 
2:
            case 
4:
                
$this->_savedName .= $text;
                return 
true;
            case 
3:
                return 
$this->_topNode ('appendToAttribute''default'$text);
            case 
5:
                
$this->_savedValue .= $text;
                return 
true;
            default:
                return 
false;
        }
    }
    
    
/**
     * Restart parsing after current block
     *
     * To achieve this the current top stack object is removed from the
     * tree. Then the current item
     *
     * @access protected
     * @return bool
     */
    
function _reparseAfterCurrentBlock () {
        if (
$this->_status == 2) {
            
// this status will *never* call _reparseAfterCurrentBlock itself
            // so this is called if the loop ends
            // therefore, just add the [/ to the text
            
            // _savedName should be empty but just in case
            
$this->_cpos -= strlen ($this->_savedName);
            
$this->_savedName '';
            
$this->_status 0;
            
$this->_appendText ('[/');
            return 
true;
        } else {
            return 
parent::_reparseAfterCurrentBlock ();
        }
    }
    
    
/**
     * Apply parsers
     */
    
function _applyParsers ($type$text) {
        if (!isset (
$this->_parsers[$type])) {
            return 
$text;
        }
        foreach (
$this->_parsers[$type] as $parser) {
            if (
is_callable ($parser)) {
                
$ntext call_user_func ($parser$text);
                if (
is_string ($ntext)) {
                    
$text $ntext;
                }
            }
        }
        return 
$text;
    }
    
    
/**
     * Handle status
     * @access protected
     * @param int $status The current status
     * @param string $needle The needle that was found
     * @return bool
     */
    
function _handleStatus ($status$needle) {
        switch (
$status) {
            case 
0// NORMAL TEXT
                
if ($needle != '[' && $needle != '[/') {
                    
$this->_appendText ($needle);
                    return 
true;
                }
                if (
$needle == '[') {
                    
$node = new StringParser_BBCode_Node_Element ($this->_cpos);
                    
$res $this->_pushNode ($node);
                    if (!
$res) {
                        return 
false;
                    }
                    
$this->_setStatus (1);
                } else if (
$needle == '[/') {
                    if (
count ($this->_stack) <= 1) {
                        
$this->_appendText ($needle);
                        return 
true;
                    }
                    
$this->_setStatus (2);
                }
                break;
            case 
1// OPEN TAG
                
if ($needle == ']') {
                    return 
$this->_openElement (0);
                } else if (
trim ($needle) == ':' || trim ($needle) == '=') {
                    
$this->_quoting null;
                    
$this->_setStatus (3); // default value parser
                    
break;
                } else if (
trim ($needle) == '="' || trim ($needle) == '= "' || trim ($needle) == '=\'' || trim ($needle) == '= \'') {
                    
$this->_quoting substr (trim ($needle), -1);
                    
$this->_setStatus (3); // default value parser with quotation
                    
break;
                } else if (
$needle == ' ') {
                    
$this->_setStatus (4); // attribute parser
                    
break;
                } else {
                    
$this->_appendText ($needle);
                    return 
true;
                }
                
// break not necessary because every if clause contains return
            
case 2// CLOSE TAG
                
if ($needle != ']') {
                    
$this->_appendText ($needle);
                    return 
true;
                }
                
$closecount 0;
                if (!
$this->_isCloseable ($this->_savedName$closecount)) {
                    
$this->_setStatus (0);
                    
$this->_appendText ('[/'.$this->_savedName.$needle);
                    return 
true;
                }
                
// this validates the code(s) to be closed after the content tree of
                // that code(s) are built - if the second validation fails, we will have
                // to reparse. note that as _reparseAfterCurrentBlock will not work correctly
                // if we're in $status == 2, we will have to set our status to 0 manually
                
if (!$this->_validateCloseTags ($closecount)) {
                    
$this->_setStatus (0);
                    return 
$this->_reparseAfterCurrentBlock ();
                }
                
$this->_setStatus (0);
                for (
$i 0$i $closecount$i++) {
                    if (
$i == $closecount 1) {
                        
$this->_topNode ('setHadCloseTag');
                    }
                    if (!
$this->_popNode ()) {
                        return 
false;
                    }
                }
                break;
            case 
3// DEFAULT ATTRIBUTE
                
if ($this->_quoting !== null) {
                    if (
$needle == '\\\\') {
                        
$this->_appendText ('\\');
                        return 
true;
                    } else if (
$needle == '\\'.$this->_quoting) {
                        
$this->_appendText ($this->_quoting);
                        return 
true;
                    } else if (
$needle == $this->_quoting.' ') {
                        
$this->_setStatus (4);
                        return 
true;
                    } else if (
$needle == $this->_quoting.']') {
                        return 
$this->_openElement (2);
                    } else if (
$needle == $this->_quoting) {
                        
// can't be, only ']' and ' ' allowed after quoting char
                        
return $this->_reparseAfterCurrentBlock ();
                    } else {
                        
$this->_appendText ($needle);
                        return 
true;
                    }
                } else {
                    if (
$needle == ' ') {
                        
$this->_setStatus (4);
                        return 
true;
                    } else if (
$needle == ']') {
                        return 
$this->_openElement (2);
                    } else {
                        
$this->_appendText ($needle);
                        return 
true;
                    }
                }
                
// break not needed because every if clause contains return!
            
case 4// ATTRIBUTE NAME
                
if ($needle == ' ') {
                    if (
strlen ($this->_savedName)) {
                        
$this->_topNode ('setAttribute'$this->_savedNametrue);
                    }
                    
// just ignore and continue in same mode
                    
$this->_setStatus (4); // reset parameters
                    
return true;
                } else if (
$needle == ']') {
                    if (
strlen ($this->_savedName)) {
                        
$this->_topNode ('setAttribute'$this->_savedNametrue);
                    }
                    return 
$this->_openElement (2);
                } else if (
$needle == '=') {
                    
$this->_quoting null;
                    
$this->_setStatus (5);
                    return 
true;
                } else if (
$needle == '="') {
                    
$this->_quoting '"';
                    
$this->_setStatus (5);
                    return 
true;
                } else if (
$needle == '=\'') {
                    
$this->_quoting '\'';
                    
$this->_setStatus (5);
                    return 
true;
                } else {
                    
$this->_appendText ($needle);
                    return 
true;
                }
                
// break not needed because every if clause contains return!
            
case 5// ATTRIBUTE VALUE
                
if ($this->_quoting !== null) {
                    if (
$needle == '\\\\') {
                        
$this->_appendText ('\\');
                        return 
true;
                    } else if (
$needle == '\\'.$this->_quoting) {
                        
$this->_appendText ($this->_quoting);
                        return 
true;
                    } else if (
$needle == $this->_quoting.' ') {
                        
$this->_topNode ('setAttribute'$this->_savedName$this->_savedValue);
                        
$this->_setStatus (4);
                        return 
true;
                    } else if (
$needle == $this->_quoting.']') {
                        
$this->_topNode ('setAttribute'$this->_savedName$this->_savedValue);
                        return 
$this->_openElement (2);
                    } else if (
$needle == $this->_quoting) {
                        
// can't be, only ']' and ' ' allowed after quoting char
                        
return $this->_reparseAfterCurrentBlock ();
                    } else {
                        
$this->_appendText ($needle);
                        return 
true;
                    }
                } else {
                    if (
$needle == ' ') {
                        
$this->_topNode ('setAttribute'$this->_savedName$this->_savedValue);
                        
$this->_setStatus (4);
                        return 
true;
                    } else if (
$needle == ']') {
                        
$this->_topNode ('setAttribute'$this->_savedName$this->_savedValue);
                        return 
$this->_openElement (2);
                    } else {
                        
$this->_appendText ($needle);
                        return 
true;
                    }
                }
                
// break not needed because every if clause contains return!
            
case 7:
                if (
$needle == '[/') {
                    
// this was case insensitive match
                    
if (strtolower (substr ($this->_text$this->_cpos strlen ($needle), strlen ($this->_topNode ('name')) + 1)) == strtolower ($this->_topNode ('name').']')) {
                        
// this matched
                        
$this->_cpos += strlen ($this->_topNode ('name')) + 1;
                    } else {
                        
// it didn't match
                        
$this->_appendText ($needle);
                        return 
true;
                    }
                }
                
$closecount $this->_savedCloseCount;
                if (!
$this->_topNode ('validate')) {
                    return 
$this->_reparseAfterCurrentBlock ();
                }
                
// do we have to close subnodes?
                
if ($closecount) {
                    
// get top node
                    
$mynode =& $this->_stack[count ($this->_stack)-1];
                    
// close necessary nodes
                    
for ($i 0$i <= $closecount$i++) {
                        if (!
$this->_popNode ()) {
                            return 
false;
                        }
                    }
                    if (!
$this->_pushNode ($mynode)) {
                        return 
false;
                    }
                }
                
$this->_setStatus (0);
                
$this->_popNode ();
                return 
true;
            default: 
                return 
false;
        }
        return 
true;
    }
    
    
/**
     * Open the next element
     *
     * @access protected
     * @return bool
     */
    
function _openElement ($type 0) {
        
$name $this->_getCanonicalName ($this->_topNode ('name'));
        if (
$name === false) {
            return 
$this->_reparseAfterCurrentBlock ();
        }
        
$occ_type $this->getCodeFlag ($name'occurrence_type''string');
        if (
$occ_type !== null && isset ($this->_maxOccurrences[$occ_type])) {
            
$max_occs $this->_maxOccurrences[$occ_type];
            
$occs $this->_root->getNodeCountByCriterium ('flag:occurrence_type'$occ_type);
            if (
$occs >= $max_occs) {
                return 
$this->_reparseAfterCurrentBlock ();
            }
        }
        
$closecount 0;
        
$this->_topNode ('setCodeInfo'$this->_codes[$name]);
        if (!
$this->_isOpenable ($name$closecount)) {
            return 
$this->_reparseAfterCurrentBlock ();
        }
        
$this->_setStatus (0);
        switch (
$type) {
        case 
0:
            
$cond $this->_isUseContent ($this->_stack[count($this->_stack)-1], false);
            break;
        case 
1:
            
$cond $this->_isUseContent ($this->_stack[count($this->_stack)-1], true);
            break;
        case 
2:
            
$cond $this->_isUseContent ($this->_stack[count($this->_stack)-1], true);
            break;
        default:
            
$cond false;
            break;
        }
        if (
$cond) {
            
$this->_savedCloseCount $closecount;
            
$this->_setStatus (7);
            return 
true;
        }
        if (!
$this->_topNode ('validate')) {
            return 
$this->_reparseAfterCurrentBlock ();
        }
        
// do we have to close subnodes?
        
if ($closecount) {
            
// get top node
            
$mynode =& $this->_stack[count ($this->_stack)-1];
            
// close necessary nodes
            
for ($i 0$i <= $closecount$i++) {
                if (!
$this->_popNode ()) {
                    return 
false;
                }
            }
            if (!
$this->_pushNode ($mynode)) {
                return 
false;
            }
        }
        
        if (
$this->_codes[$name]['callback_type'] == 'simple_replace_single' || $this->_codes[$name]['callback_type'] == 'callback_replace_single') {
            if (!
$this->_popNode ())  {
                return 
false;
            }
        }
        
        return 
true;
    }
    
    
/**
     * Is a node closeable?
     *
     * @access protected
     * @return bool
     */
    
function _isCloseable ($name, &$closecount) {
        
$node =& $this->_findNamedNode ($namefalse);
        if (
$node === false) {
            return 
false;
        }
        
$scount count ($this->_stack);
        for (
$i $scount 1$i 0$i--) {
            
$closecount++;
            if (
$this->_stack[$i]->equals ($node)) {
                return 
true;
            }
            if (
$this->_stack[$i]->getFlag ('closetag''integer'BBCODE_CLOSETAG_IMPLICIT) == BBCODE_CLOSETAG_MUSTEXIST) {
                return 
false;
            }
        }
        return 
false;
    }
    
    
/**
     * Revalidate codes when close tags appear
     *
     * @access protected
     * @return bool
     */
    
function _validateCloseTags ($closecount) {
        
$scount count ($this->_stack);
        for (
$i $scount 1$i >= $scount $closecount$i--) {
            if (
$this->_validateAgain) {
                if (!
$this->_stack[$i]->validate ('validate_again')) {
                    return 
false;
                }
            }
        }
        return 
true;
    }
    
    
/**
     * Is a node openable?
     *
     * @access protected
     * @return bool
     */
    
function _isOpenable ($name, &$closecount) {
        if (!isset (
$this->_codes[$name])) {
            return 
false;
        }
        
        
$closecount 0;
        
        
$allowed_within $this->_codes[$name]['allowed_within'];
        
$not_allowed_within $this->_codes[$name]['not_allowed_within'];
        
        
$scount count ($this->_stack);
        if (
$scount == 2) { // top level element
            
if (!in_array ($this->_rootContentType$allowed_within)) {
                return 
false;
            }
        } else {
            if (!
in_array ($this->_stack[$scount-2]->_codeInfo['content_type'], $allowed_within)) {
                return 
$this->_isOpenableWithClose ($name$closecount);
            }
        }
        
        for (
$i 1$i $scount 1$i++) {
            if (
in_array ($this->_stack[$i]->_codeInfo['content_type'], $not_allowed_within)) {
                return 
$this->_isOpenableWithClose ($name$closecount);
            }
        }
        
        return 
true;
    }
    
    
/**
     * Is a node openable by closing other nodes?
     *
     * @access protected
     * @return bool
     */
    
function _isOpenableWithClose ($name, &$closecount) {
        
$tnname $this->_getCanonicalName ($this->_topNode ('name'));
        if (!
in_array ($this->getCodeFlag ($tnname'closetag''integer'BBCODE_CLOSETAG_IMPLICIT), array (BBCODE_CLOSETAG_FORBIDDENBBCODE_CLOSETAG_OPTIONAL))) {
            return 
false;
        }
        
$node =& $this->_findNamedNode ($nametrue);
        if (
$node === false) {
            return 
false;
        }
        
$scount count ($this->_stack);
        if (
$scount 3) {
            return 
false;
        }
        for (
$i $scount 2$i 0$i--) {
            
$closecount++;
            if (
$this->_stack[$i]->equals ($node)) {
                return 
true;
            }
            if (
in_array ($this->_stack[$i]->getFlag ('closetag''integer'BBCODE_CLOSETAG_IMPLICIT), array (BBCODE_CLOSETAG_IMPLICIT_ON_CLOSE_ONLYBBCODE_CLOSETAG_MUSTEXIST))) {
                return 
false;
            }
            if (
$this->_validateAgain) {
                if (!
$this->_stack[$i]->validate ('validate_again')) {
                    return 
false;
                }
            }
        }
        
        return 
false;
    }
    
    
/**
     * Abstract method: Close remaining blocks
     * @access protected
     */
    
function _closeRemainingBlocks () {
        
// everything closed
        
if (count ($this->_stack) == 1) {
            return 
true;
        }
        
// not everything close
        
if ($this->strict) {
            return 
false;
        }
        while (
count ($this->_stack) > 1) {
            if (
$this->_topNode ('getFlag''closetag''integer'BBCODE_CLOSETAG_IMPLICIT) == BBCODE_CLOSETAG_MUSTEXIST) {
                return 
false// sorry
            
}
            
$res $this->_popNode ();
            if (!
$res) {
                return 
false;
            }
        }
        return 
true;
    }
    
    
/**
     * Find a node with a specific name in stack
     *
     * @access protected
     * @return mixed
     */
    
function &_findNamedNode ($name$searchdeeper false) {
        
$lname $this->_getCanonicalName ($name);
        
$case_sensitive $this->_caseSensitive && $this->getCodeFlag ($lname'case_sensitive''boolean'true);
        if (
$case_sensitive) {
            
$name strtolower ($name);
        }
        
$scount count ($this->_stack);
        if (
$searchdeeper) {
            
$scount--;
        }
        for (
$i $scount 1$i 0$i--) {
            if (!
$case_sensitive) {
                
$cmp_name strtolower ($this->_stack[$i]->name ());
            } else {
                
$cmp_name $this->_stack[$i]->name ();
            }
            if (
$cmp_name == $lname) {
                return 
$this->_stack[$i];
            }
        }
        
$result false;
        return 
$result;
    }
    
    
/**
     * Abstract method: Output tree
     * @access protected
     * @return bool
     */
    
function _outputTree () {
        if (
$this->_noOutput) {
            return 
true;
        }
        
$output $this->_outputNode ($this->_root);
        if (
is_string ($output)) {
            
$this->_output $this->_applyPostfilters ($output);
            unset (
$output);
            return 
true;
        }
        
        return 
false;
    }
    
    
/**
     * Output a node
     * @access protected
     * @return bool
     */
    
function _outputNode (&$node) {
        
$output '';
        if (
$node->_type == STRINGPARSER_BBCODE_NODE_PARAGRAPH || $node->_type == STRINGPARSER_BBCODE_NODE_ELEMENT || $node->_type == STRINGPARSER_NODE_ROOT) {
            
$ccount count ($node->_children);
            for (
$i 0$i $ccount$i++) {
                
$suboutput $this->_outputNode ($node->_children[$i]);
                if (!
is_string ($suboutput)) {
                    return 
false;
                }
                
$output .= $suboutput;
            }
            if (
$node->_type == STRINGPARSER_BBCODE_NODE_PARAGRAPH) {
                return 
$this->_paragraphHandling['start_tag'].$output.$this->_paragraphHandling['end_tag'];
            }
            if (
$node->_type == STRINGPARSER_BBCODE_NODE_ELEMENT) {
                return 
$node->getReplacement ($output);
            }
            return 
$output;
        } else if (
$node->_type == STRINGPARSER_NODE_TEXT) {
            
$output $node->content;
            
$before '';
            
$after '';
            
$ol strlen ($output);
            switch (
$node->getFlag ('newlinemode.begin''integer'BBCODE_NEWLINE_PARSE)) {
            case 
BBCODE_NEWLINE_IGNORE:
                if (
$ol && $output{0} == "\n") {
                    
$before "\n";
                }
                
// don't break!
            
case BBCODE_NEWLINE_DROP:
                if (
$ol && $output{0} == "\n") {
                    
$output substr ($output1);
                    
$ol--;
                }
                break;
            }
            switch (
$node->getFlag ('newlinemode.end''integer'BBCODE_NEWLINE_PARSE)) {
            case 
BBCODE_NEWLINE_IGNORE:
                if (
$ol && $output{$ol-1} == "\n") {
                    
$after "\n";
                }
                
// don't break!
            
case BBCODE_NEWLINE_DROP:
                if (
$ol && $output{$ol-1} == "\n") {
                    
$output substr ($output0, -1);
                    
$ol--;
                }
                break;
            }
            
// can't do anything
            
if ($node->_parent === null) {
                return 
$before.$output.$after;
            }
            if (
$node->_parent->_type == STRINGPARSER_BBCODE_NODE_PARAGRAPH)  {
                
$parent =& $node->_parent;
                unset (
$node);
                
$node =& $parent;
                unset (
$parent);
                
// if no parent for this paragraph
                
if ($node->_parent === null) {
                    return 
$before.$output.$after;
                }
            }
            if (
$node->_parent->_type == STRINGPARSER_NODE_ROOT) {
                return 
$before.$this->_applyParsers ($this->_rootContentType$output).$after;
            }
            if (
$node->_parent->_type == STRINGPARSER_BBCODE_NODE_ELEMENT) {
                return 
$before.$this->_applyParsers ($node->_parent->_codeInfo['content_type'], $output).$after;
            }
            return 
$before.$output.$after;
        }
    }
    
    
/**
     * Abstract method: Manipulate the tree
     * @access protected
     * @return bool
     */
    
function _modifyTree () {
        
// first pass: try to do newline handling
        
$nodes =& $this->_root->getNodesByCriterium ('needsTextNodeModification'true);
        
$nodes_count count ($nodes);
        for (
$i 0$i $nodes_count$i++) {
            
$v $nodes[$i]->getFlag ('opentag.before.newline''integer'BBCODE_NEWLINE_PARSE);
            if (
$v != BBCODE_NEWLINE_PARSE) {
                
$n =& $nodes[$i]->findPrevAdjentTextNode ();
                if (!
is_null ($n)) {
                    
$n->setFlag ('newlinemode.end'$v);
                }
                unset (
$n);
            }
            
$v $nodes[$i]->getFlag ('opentag.after.newline''integer'BBCODE_NEWLINE_PARSE);
            if (
$v != BBCODE_NEWLINE_PARSE) {
                
$n =& $nodes[$i]->firstChildIfText ();
                if (!
is_null ($n)) {
                    
$n->setFlag ('newlinemode.begin'$v);
                }
                unset (
$n);
            }
            
$v $nodes[$i]->getFlag ('closetag.before.newline''integer'BBCODE_NEWLINE_PARSE);
            if (
$v != BBCODE_NEWLINE_PARSE) {
                
$n =& $nodes[$i]->lastChildIfText ();
                if (!
is_null ($n)) {
                    
$n->setFlag ('newlinemode.end'$v);
                }
                unset (
$n);
            }
            
$v $nodes[$i]->getFlag ('closetag.after.newline''integer'BBCODE_NEWLINE_PARSE);
            if (
$v != BBCODE_NEWLINE_PARSE) {
                
$n =& $nodes[$i]->findNextAdjentTextNode ();
                if (!
is_null ($n)) {
                    
$n->setFlag ('newlinemode.begin'$v);
                }
                unset (
$n);
            }
        }
        
        
// second pass a: do paragraph handling on root element
        
if ($this->_rootParagraphHandling) {
            
$res $this->_handleParagraphs ($this->_root);
            if (!
$res) {
                return 
false;
            }
        }
        
        
// second pass b: do paragraph handling on other elements
        
unset ($nodes);
        
$nodes =& $this->_root->getNodesByCriterium ('flag:paragraphs'true);
        
$nodes_count count ($nodes);
        for (
$i 0$i $nodes_count$i++) {
            
$res $this->_handleParagraphs ($nodes[$i]);
            if (!
$res) {
                return 
false;
            }
        }
        
        
// second pass c: search for empty paragraph nodes and remove them
        
unset ($nodes);
        
$nodes =& $this->_root->getNodesByCriterium ('empty'true);
        
$nodes_count count ($nodes);
        if (isset (
$parent)) {
            unset (
$parent); $parent null;
        }
        for (
$i 0$i $nodes_count$i++) {
            if (
$nodes[$i]->_type != STRINGPARSER_BBCODE_NODE_PARAGRAPH) {
                continue;
            }
            unset (
$parent);
            
$parent =& $nodes[$i]->_parent;
            
$parent->removeChild ($nodes[$i], true);
        }
        
        return 
true;
    }
    
    
/**
     * Handle paragraphs
     * @access protected
     * @param object $node The node to handle
     * @return bool
     */
    
function _handleParagraphs (&$node) {
        
// if this node is already a subnode of a paragraph node, do NOT 
        // do paragraph handling on this node!
        
if ($this->_hasParagraphAncestor ($node)) {
            return 
true;
        }
        
$dest_nodes = array ();
        
$last_node_was_paragraph false;
        
$prevtype STRINGPARSER_NODE_TEXT;
        
$paragraph null;
        while (
count ($node->_children)) {
            
$mynode =& $node->_children[0];
            
$node->removeChild ($mynode);
            
$subprevtype $prevtype;
            
$sub_nodes =& $this->_breakupNodeByParagraphs ($mynode);
            for (
$i 0$i count ($sub_nodes); $i++) {
                if (!
$last_node_was_paragraph ||  ($prevtype == $sub_nodes[$i]->_type && ($i != || $prevtype != STRINGPARSER_BBCODE_NODE_ELEMENT))) {
                    unset (
$paragraph);
                    
$paragraph = new StringParser_BBCode_Node_Paragraph ();
                }
                
$prevtype $sub_nodes[$i]->_type;
                if (
$sub_nodes[$i]->_type != STRINGPARSER_BBCODE_NODE_ELEMENT || $sub_nodes[$i]->getFlag ('paragraph_type''integer'BBCODE_PARAGRAPH_ALLOW_BREAKUP) != BBCODE_PARAGRAPH_BLOCK_ELEMENT) {
                    
$paragraph->appendChild ($sub_nodes[$i]);
                    
$dest_nodes[] =& $paragraph;
                    
$last_node_was_paragraph true;
                } else {
                    
$dest_nodes[] =& $sub_nodes[$i];
                    
$last_onde_was_paragraph false;
                    unset (
$paragraph);
                    
$paragraph = new StringParser_BBCode_Node_Paragraph ();
                }
            }
        }
        
$count count ($dest_nodes);
        for (
$i 0$i $count$i++) {
            
$node->appendChild ($dest_nodes[$i]);
        }
        unset (
$dest_nodes);
        unset (
$paragraph);
        return 
true;
    }
    
    
/**
     * Search for a paragraph node in tree in upward direction
     * @access protected
     * @param object $node The node to analyze
     * @return bool
     */
    
function _hasParagraphAncestor (&$node) {
        if (
$node->_parent === null) {
            return 
false;
        }
        
$parent =& $node->_parent;
        if (
$parent->_type == STRINGPARSER_BBCODE_NODE_PARAGRAPH) {
            return 
true;
        }
        return 
$this->_hasParagraphAncestor ($parent);
    }
    
    
/**
     * Break up nodes
     * @access protected
     * @param object $node The node to break up
     * @return array
     */
    
function &_breakupNodeByParagraphs (&$node) {
        
$detect_string $this->_paragraphHandling['detect_string'];
        
$dest_nodes = array ();
        
// text node => no problem
        
if ($node->_type == STRINGPARSER_NODE_TEXT) {
            
$cpos 0;
            while ((
$npos strpos ($node->content$detect_string$cpos)) !== false) {
                
$subnode = new StringParser_Node_Text (substr ($node->content$cpos$npos $cpos), $node->occurredAt $cpos);
                
// copy flags
                
foreach ($node->_flags as $flag => $value) {
                    if (
$flag == 'newlinemode.begin') {
                        if (
$cpos == 0) {
                            
$subnode->setFlag ($flag$value);
                        }
                    } else if (
$flag == 'newlinemode.end') {
                        
// do nothing
                    
} else {
                        
$subnode->setFlag ($flag$value);
                    }
                }
                
$dest_nodes[] =& $subnode;
                unset (
$subnode);
                
$cpos $npos strlen ($detect_string);
            }
            
$subnode = new StringParser_Node_Text (substr ($node->content$cpos), $node->occurredAt $cpos);
            if (
$cpos == 0) {
                
$value $node->getFlag ('newlinemode.begin''integer'null);
                if (
$value !== null) {
                    
$subnode->setFlag ('newlinemode.begin'$value);
                }
            }
            
$value $node->getFlag ('newlinemode.end''integer'null);
            if (
$value !== null) {
                
$subnode->setFlag ('newlinemode.end'$value);
            }
            
$dest_nodes[] =& $subnode;
            unset (
$subnode);
            return 
$dest_nodes;
        }
        
// not a text node or an element node => no way
        
if ($node->_type != STRINGPARSER_BBCODE_NODE_ELEMENT) {
            
$dest_nodes[] =& $node;
            return 
$dest_nodes;
        }
        if (
$node->getFlag ('paragraph_type''integer'BBCODE_PARAGRAPH_ALLOW_BREAKUP) != BBCODE_PARAGRAPH_ALLOW_BREAKUP || !count ($node->_children)) {
            
$dest_nodes[] =& $node;
            return 
$dest_nodes;
        }
        
$dest_node =& $node->duplicate ();
        
$nodecount count ($node->_children);
        
// now this node allows breakup - do it
        
for ($i 0$i $nodecount$i++) {
            
$firstnode =& $node->_children[0];
            
$node->removeChild ($firstnode);
            
$sub_nodes =& $this->_breakupNodeByParagraphs ($firstnode);
            for (
$j 0$j count ($sub_nodes); $j++) {
                if (
$j != 0) {
                    
$dest_nodes[] =& $dest_node;
                    unset (
$dest_node);
                    
$dest_node =& $node->duplicate ();
                }
                
$dest_node->appendChild ($sub_nodes[$j]);
            }
            unset (
$sub_nodes);
        }
        
$dest_nodes[] =& $dest_node;
        return 
$dest_nodes;
    }
    
    
/**
     * Is this node a usecontent node
     * @access protected
     * @param object $node The node to check
     * @param bool $check_attrs Also check whether 'usecontent?'-attributes exist
     * @return bool
     */
    
function _isUseContent (&$node$check_attrs false) {
        
$name $this->_getCanonicalName ($node->name ());
        
// this should NOT happen
        
if ($name === false) {
            return 
false;
        }
        if (
$this->_codes[$name]['callback_type'] == 'usecontent') {
            return 
true;
        }
        
$result false;
        if (
$this->_codes[$name]['callback_type'] == 'callback_replace?') {
            
$result true;
        } else if (
$this->_codes[$name]['callback_type'] != 'usecontent?') {
            return 
false;
        }
        if (
$check_attrs === false) {
            return !
$result;
        }
        
$attributes array_keys ($this->_topNodeVar ('_attributes'));
        
$p = @$this->_codes[$name]['callback_params']['usecontent_param'];
        if (
is_array ($p)) {
            foreach (
$p as $param) {
                if (
in_array ($param$attributes)) {
                    return 
$result;
                }
            }
        } else {
            if (
in_array ($p$attributes)) {
                return 
$result;
            }
        }
        return !
$result;
    }

    
/**
    * Get canonical name of a code
    *
    * @access protected
    * @param string $name
    * @return string
    */
    
function _getCanonicalName ($name) {
        if (isset (
$this->_codes[$name])) {
            return 
$name;
        }
        
$found false;
        
// try to find the code in the code list
        
foreach (array_keys ($this->_codes) as $rname) {
            
// match
            
if (strtolower ($rname) == strtolower ($name)) {
                
$found $rname;
                break;
            }
        }
        if (
$found === false || ($this->_caseSensitive && $this->getCodeFlag ($found'case_sensitive''boolean'true))) {
            return 
false;
        }
        return 
$rname;
    }
}

/**
 * Node type: BBCode Element node
 * @see StringParser_BBCode_Node_Element::_type
 */
define ('STRINGPARSER_BBCODE_NODE_ELEMENT'32);

/**
 * Node type: BBCode Paragraph node
 * @see StringParser_BBCode_Node_Paragraph::_type
 */
define ('STRINGPARSER_BBCODE_NODE_PARAGRAPH'33);


/**
 * BBCode String parser paragraph node class
 *
 * @package stringparser
 */
class StringParser_BBCode_Node_Paragraph extends StringParser_Node {
    
/**
     * The type of this node.
     * 
     * This node is a bbcode paragraph node.
     *
     * @access protected
     * @var int
     * @see STRINGPARSER_BBCODE_NODE_PARAGRAPH
     */
    
var $_type STRINGPARSER_BBCODE_NODE_PARAGRAPH;
    
    
/**
     * Determines whether a criterium matches this node
     *
     * @access public
     * @param string $criterium The criterium that is to be checked
     * @param mixed $value The value that is to be compared
     * @return bool True if this node matches that criterium
     */
    
function matchesCriterium ($criterium$value) {
        if (
$criterium == 'empty') {
            if (!
count ($this->_children)) {
                return 
true;
            }
            if (
count ($this->_children) > 1) {
                return 
false;
            }
            if (
$this->_children[0]->_type != STRINGPARSER_NODE_TEXT) {
                return 
false;
            }
            if (!
strlen ($this->_children[0]->content)) {
                return 
true;
            }
            if (
strlen ($this->_children[0]->content) > 2) {
                return 
false;
            }
            
$f_begin $this->_children[0]->getFlag ('newlinemode.begin''integer'BBCODE_NEWLINE_PARSE);
            
$f_end $this->_children[0]->getFlag ('newlinemode.end''integer'BBCODE_NEWLINE_PARSE);
            
$content $this->_children[0]->content;
            if (
$f_begin != BBCODE_NEWLINE_PARSE && $content{0} == "\n") {
                
$content substr ($content1);
            }
            if (
$f_end != BBCODE_NEWLINE_PARSE && $content{strlen($content)-1} == "\n") {
                
$content substr ($content0, -1);
            }
            if (!
strlen ($content)) {
                return 
true;
            }
            return 
false;
        }
    }
}

/**
 * BBCode String parser element node class
 *
 * @package stringparser
 */
class StringParser_BBCode_Node_Element extends StringParser_Node {
    
/**
     * The type of this node.
     * 
     * This node is a bbcode element node.
     *
     * @access protected
     * @var int
     * @see STRINGPARSER_BBCODE_NODE_ELEMENT
     */
    
var $_type STRINGPARSER_BBCODE_NODE_ELEMENT;
    
    
/**
     * Element name
     *
     * @access protected
     * @var string
     * @see StringParser_BBCode_Node_Element::name
     * @see StringParser_BBCode_Node_Element::setName
     * @see StringParser_BBCode_Node_Element::appendToName
     */
    
var $_name '';
    
    
/**
     * Element flags
     * 
     * @access protected
     * @var array
     */
    
var $_flags = array ();
    
    
/**
     * Element attributes
     * 
     * @access protected
     * @var array
     */
    
var $_attributes = array ();
    
    
/**
     * Had a close tag
     *
     * @access protected
     * @var bool
     */
    
var $_hadCloseTag false;
    
    
/**
     * Was processed by paragraph handling
     *
     * @access protected
     * @var bool
     */
    
var $_paragraphHandled false;
    
    
//////////////////////////////////////////////////
    
    /**
     * Duplicate this node (but without children / parents)
     *
     * @access public
     * @return object
     */
    
function &duplicate () {
        
$newnode = new StringParser_BBCode_Node_Element ($this->occurredAt);
        
$newnode->_name $this->_name;
        
$newnode->_flags $this->_flags;
        
$newnode->_attributes $this->_attributes;
        
$newnode->_hadCloseTag $this->_hadCloseTag;
        
$newnode->_paragraphHandled $this->_paragraphHandled;
        
$newnode->_codeInfo $this->_codeInfo;
        return 
$newnode;
    }
    
    
/**
     * Retreive name of this element
     *
     * @access public
     * @return string
     */
    
function name () {
        return 
$this->_name;
    }
    
    
/**
     * Set name of this element
     *
     * @access public
     * @param string $name The new name of the element
     */
    
function setName ($name) {
        
$this->_name $name;
        return 
true;
    }
    
    
/**
     * Append to name of this element
     *
     * @access public
     * @param string $chars The chars to append to the name of the element
     */
    
function appendToName ($chars) {
        
$this->_name .= $chars;
        return 
true;
    }
    
    
/**
     * Append to attribute of this element
     *
     * @access public
     * @param string $name The name of the attribute
     * @param string $chars The chars to append to the attribute of the element
     */
    
function appendToAttribute ($name$chars) {
        if (!isset (
$this->_attributes[$name])) {
            
$this->_attributes[$name] = $chars;
            return 
true;
        }
        
$this->_attributes[$name] .= $chars;
        return 
true;
    }
    
    
/**
     * Set attribute
     *
     * @access public
     * @param string $name The name of the attribute
     * @param string $value The new value of the attribute
     */
    
function setAttribute ($name$value) {
        
$this->_attributes[$name] = $value;
        return 
true;
    }
    
    
/**
     * Set code info
     *
     * @access public
     * @param array $info The code info array
     */
    
function setCodeInfo ($info) {
        
$this->_codeInfo $info;
        
$this->_flags $info['flags'];
        return 
true;
    }
    
    
/**
     * Get attribute value
     *
     * @access public
     * @param string $name The name of the attribute
     */
    
function attribute ($name) {
        if (!isset (
$this->_attributes[$name])) {
            return 
null;
        }
        return 
$this->_attributes[$name];
    }
    
    
/**
     * Set flag that this element had a close tag
     *
     * @access public
     */
    
function setHadCloseTag () {
        
$this->_hadCloseTag true;
    }
    
    
/**
     * Set flag that this element was already processed by paragraph handling
     *
     * @access public
     */
    
function setParagraphHandled () {
        
$this->_paragraphHandled true;
    }
    
    
/**
     * Get flag if this element was already processed by paragraph handling
     *
     * @access public
     * @return bool
     */
    
function paragraphHandled () {
        return 
$this->_paragraphHandled;
    }
    
    
/**
     * Get flag if this element had a close tag
     *
     * @access public
     * @return bool
     */
    
function hadCloseTag () {
        return 
$this->_hadCloseTag;
    }
    
    
/**
     * Determines whether a criterium matches this node
     *
     * @access public
     * @param string $criterium The criterium that is to be checked
     * @param mixed $value The value that is to be compared
     * @return bool True if this node matches that criterium
     */
    
function matchesCriterium ($criterium$value) {
        if (
$criterium == 'tagName') {
            return (
$value == $this->_name);
        }
        if (
$criterium == 'needsTextNodeModification') {
            return ((
$this->getFlag ('opentag.before.newline''integer'BBCODE_NEWLINE_PARSE) != BBCODE_NEWLINE_PARSE || $this->getFlag ('opentag.after.newline''integer'BBCODE_NEWLINE_PARSE) != BBCODE_NEWLINE_PARSE || ($this->_hadCloseTag && ($this->getFlag ('closetag.before.newline''integer'BBCODE_NEWLINE_PARSE) != BBCODE_NEWLINE_PARSE || $this->getFlag ('closetag.after.newline''integer'BBCODE_NEWLINE_PARSE) != BBCODE_NEWLINE_PARSE))) == (bool)$value);
        }
        if (
substr ($criterium05) == 'flag:') {
            
$criterium substr ($criterium5);
            return (
$this->getFlag ($criterium) == $value);
        }
        if (
substr ($criterium06) == '!flag:') {
            
$criterium substr ($criterium6);
            return (
$this->getFlag ($criterium) != $value);
        }
        if (
substr ($criterium06) == 'flag=:') {
            
$criterium substr ($criterium6);
            return (
$this->getFlag ($criterium) === $value);
        }
        if (
substr ($criterium07) == '!flag=:') {
            
$criterium substr ($criterium7);
            return (
$this->getFlag ($criterium) !== $value);
        }
        return 
parent::matchesCriterium ($criterium$value);
    }
    
    
/**
     * Get first child if it is a text node
     *
     * @access public
     * @return mixed
     */
    
function &firstChildIfText () {
        
$ret =& $this->firstChild ();
        if (
is_null ($ret)) {
            return 
$ret;
        }
        if (
$ret->_type != STRINGPARSER_NODE_TEXT) {
            
// DON'T DO $ret = null WITHOUT unset BEFORE!
            // ELSE WE WILL ERASE THE NODE ITSELF! EVIL!
            
unset ($ret);
            
$ret null;
        }
        return 
$ret;
    }
    
    
/**
     * Get last child if it is a text node AND if this element had a close tag
     *
     * @access public
     * @return mixed
     */
    
function &lastChildIfText () {
        
$ret =& $this->lastChild ();
        if (
is_null ($ret)) {
            return 
$ret;
        }
        if (
$ret->_type != STRINGPARSER_NODE_TEXT || !$this->_hadCloseTag) {
            
// DON'T DO $ret = null WITHOUT unset BEFORE!
            // ELSE WE WILL ERASE THE NODE ITSELF! EVIL!
            
if ($ret->_type != STRINGPARSER_NODE_TEXT && !$ret->hadCloseTag ()) {
                
$ret2 =& $ret->_findPrevAdjentTextNodeHelper ();
                unset (
$ret);
                
$ret =& $ret2;
                unset (
$ret2);
            } else {
                unset (
$ret);
                
$ret null;
            }
        }
        return 
$ret;
    }
    
    
/**
     * Find next adjent text node after close tag
     *
     * returns the node or null if none exists
     *
     * @access public
     * @return mixed
     */
    
function &findNextAdjentTextNode () {
        
$ret null;
        if (
is_null ($this->_parent)) {
            return 
$ret;
        }
        if (!
$this->_hadCloseTag) {
            return 
$ret;
        }
        
$ccount count ($this->_parent->_children);
        
$found false;
        for (
$i 0$i $ccount$i++) {
            if (
$this->_parent->_children[$i]->equals ($this)) {
                
$found $i;
                break;
            }
        }
        if (
$found === false) {
            return 
$ret;
        }
        if (
$found $ccount 1) {
            if (
$this->_parent->_children[$found+1]->_type == STRINGPARSER_NODE_TEXT) {
                return 
$this->_parent->_children[$found+1];
            }
            return 
$ret;
        }
        if (
$this->_parent->_type == STRINGPARSER_BBCODE_NODE_ELEMENT && !$this->_parent->hadCloseTag ()) {
            
$ret =& $this->_parent->findNextAdjentTextNode ();
            return 
$ret;
        }
        return 
$ret;
    }
    
    
/**
     * Find previous adjent text node before open tag
     *
     * returns the node or null if none exists
     *
     * @access public
     * @return mixed
     */
    
function &findPrevAdjentTextNode () {
        
$ret null;
        if (
is_null ($this->_parent)) {
            return 
$ret;
        }
        
$ccount count ($this->_parent->_children);
        
$found false;
        for (
$i 0$i $ccount$i++) {
            if (
$this->_parent->_children[$i]->equals ($this)) {
                
$found $i;
                break;
            }
        }
        if (
$found === false) {
            return 
$ret;
        }
        if (
$found 0) {
            if (
$this->_parent->_children[$found-1]->_type == STRINGPARSER_NODE_TEXT) {
                return 
$this->_parent->_children[$found-1];
            }
            if (!
$this->_parent->_children[$found-1]->hadCloseTag ()) {
                
$ret =& $this->_parent->_children[$found-1]->_findPrevAdjentTextNodeHelper ();
            }
            return 
$ret;
        }
        return 
$ret;
    }
    
    
/**
     * Helper function for findPrevAdjentTextNode
     *
     * Looks at the last child node; if it's a text node, it returns it,
     * if the element node did not have an open tag, it calls itself
     * recursively.
     */
    
function &_findPrevAdjentTextNodeHelper () {
        
$lastnode =& $this->lastChild ();
        if (
$lastnode === null || $lastnode->_type == STRINGPARSER_NODE_TEXT) {
            return 
$lastnode;
        }
        if (!
$lastnode->hadCloseTag ()) {
            
$ret =& $lastnode->_findPrevAdjentTextNodeHelper ();
        } else {
            
$ret null;
        }
        return 
$ret;
    }
    
    
/**
     * Get Flag
     *
     * @access public
     * @param string $flag The requested flag
     * @param string $type The requested type of the return value
     * @param mixed $default The default return value
     * @return mixed
     */
    
function getFlag ($flag$type 'mixed'$default null) {
        if (!isset (
$this->_flags[$flag])) {
            return 
$default;
        }
        
$return $this->_flags[$flag];
        if (
$type != 'mixed') {
            
settype ($return$type);
        }
        return 
$return;
    }
    
    
/**
     * Set a flag
     *
     * @access public
     * @param string $name The name of the flag
     * @param mixed $value The value of the flag
     */
    
function setFlag ($name$value) {
        
$this->_flags[$name] = $value;
        return 
true;
    }
    
    
/**
     * Validate code
     *
     * @access public
     * @param string $action The action which is to be called ('validate'
     *                       for first validation, 'validate_again' for
     *                       second validation (optional))
     * @return bool
     */
    
function validate ($action 'validate') {
        if (
$action != 'validate' && $action != 'validate_again') {
            return 
false;
        }
        if (
$this->_codeInfo['callback_type'] != 'simple_replace' && $this->_codeInfo['callback_type'] != 'simple_replace_single') {
            if (!
is_callable ($this->_codeInfo['callback_func'])) {
                return 
false;
            }
            
            if ((
$this->_codeInfo['callback_type'] == 'usecontent' || $this->_codeInfo['callback_type'] == 'usecontent?' || $this->_codeInfo['callback_type'] == 'callback_replace?') && count ($this->_children) == && $this->_children[0]->_type == STRINGPARSER_NODE_TEXT) {
                
// we have to make sure the object gets passed on as a reference
                // if we do call_user_func(..., &$this) this will clash with PHP5
                
$callArray = array ($action$this->_attributes$this->_children[0]->content$this->_codeInfo['callback_params']);
                
$callArray[] =& $this;
                
$res call_user_func_array ($this->_codeInfo['callback_func'], $callArray);
                if (
$res) {
                    
// ok, now, if we've got a usecontent type, set a flag that
                    // this may not be broken up by paragraph handling!
                    // but PLEASE do NOT change if already set to any other setting
                    // than BBCODE_PARAGRAPH_ALLOW_BREAKUP because we could
                    // override e.g. BBCODE_PARAGRAPH_BLOCK_ELEMENT!
                    
$val $this->getFlag ('paragraph_type''integer'BBCODE_PARAGRAPH_ALLOW_BREAKUP);
                    if (
$val == BBCODE_PARAGRAPH_ALLOW_BREAKUP) {
                        
$this->_flags['paragraph_type'] = BBCODE_PARAGRAPH_ALLOW_INSIDE;
                    }
                }
                return 
$res;
            }
            
            
// we have to make sure the object gets passed on as a reference
            // if we do call_user_func(..., &$this) this will clash with PHP5
            
$callArray = array ($action$this->_attributesnull$this->_codeInfo['callback_params']);
            
$callArray[] =& $this;
            return 
call_user_func_array ($this->_codeInfo['callback_func'], $callArray);
        }
        return (bool)(!
count ($this->_attributes));
    }
    
    
/**
     * Get replacement for this code
     *
     * @access public
     * @param string $subcontent The content of all sub-nodes
     * @return string
     */
    
function getReplacement ($subcontent) {
        if (
$this->_codeInfo['callback_type'] == 'simple_replace' || $this->_codeInfo['callback_type'] == 'simple_replace_single') {
            if (
$this->_codeInfo['callback_type'] == 'simple_replace_single') {
                if (
strlen ($subcontent)) { // can't be!
                    
return false;
                }
                return 
$this->_codeInfo['callback_params']['start_tag'];
            }
            return 
$this->_codeInfo['callback_params']['start_tag'].$subcontent.$this->_codeInfo['callback_params']['end_tag'];
        }
        
// else usecontent, usecontent? or callback_replace or callback_replace_single
        // => call function (the function is callable, determined in validate()!)
        
        // we have to make sure the object gets passed on as a reference
        // if we do call_user_func(..., &$this) this will clash with PHP5
        
$callArray = array ('output'$this->_attributes$subcontent$this->_codeInfo['callback_params']);
        
$callArray[] =& $this;
        return 
call_user_func_array ($this->_codeInfo['callback_func'], $callArray);
    }
    
    
/**
     * Dump this node to a string
     *
     * @access protected
     * @return string
     */
    
function _dumpToString () {
        
$str "bbcode \"".substr (preg_replace ('/\s+/'' '$this->_name), 040)."\"";
        if (
count ($this->_attributes)) {
            
$attribs array_keys ($this->_attributes);
            
sort ($attribs);
            
$str .= ' (';
            
$i 0;
            foreach (
$attribs as $attrib) {
                if (
$i != 0) {
                    
$str .= ', ';
                }
                
$str .= $attrib.'="';
                
$str .= substr (preg_replace ('/\s+/'' '$this->_attributes[$attrib]), 010);
                
$str .= '"';
                
$i++;
            }
            
$str .= ')';
        }
        return 
$str;
    }
}

?>

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by HackingTool | HackingTool | Generation time: 0.0062 ]--