* Invision Power Services
* IP.Board v3.4.6
* BBCode parsing core - legacy routine
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
*
*
* @author $Author: bfarber $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.invisionpower.com/company/standards.php#license
* @package IP.Board
* @link http://www.invisionpower.com
* @since 9th March 2005 11:03
* @version $Revision: 10721 $
*/
if ( ! defined( 'IN_IPB' ) )
{
print "
Incorrect access
You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.";
exit();
}
class class_bbcode_legacy extends class_bbcode_core
{
/**
* Constructor
*
* @access public
* @param object Registry object
* @return @e void
*/
public function __construct( ipsRegistry $registry )
{
parent::__construct( $registry );
}
/**
* Parse before saving (not used in legacy parser)
*
* @access public
* @param string Text to parse
* @return string Parsed text
*/
public function preDbParse( $txt="" )
{
return $txt;
}
/**
* Parse before displaying (not used in legacy parser)
*
* @access public
* @param string Text to parse
* @return string Parsed text
*/
public function preDisplayParse( $txt="" )
{
return $txt;
}
/**
* This function processes the text before showing for editing, etc
* Used for rebuilding after upgrade to 3.0
*
* @access public
* @param string Raw text
* @return string Converted text
*/
public function preEditParse( $txt="" )
{
//-----------------------------------------
// Before we start, strip newlines or we'll
// end up duplicating them
//-----------------------------------------
$txt = str_replace( "\n", "", $txt );
$txt = str_replace( "\r", "", $txt );
//-----------------------------------------
// Clean up BR tags
//-----------------------------------------
if ( !$this->parse_html OR $this->parse_nl2br )
{
$txt = str_replace( "
" , "\n", $txt );
$txt = str_replace( "
", "\n", $txt );
}
# Make EMO_DIR safe so the ^> regex works
$txt = str_replace( "<#EMO_DIR#>", "<#EMO_DIR>", $txt );
# New emo
$txt = preg_replace( "#(\s)?<([^>]+?)emoid=\"(.+?)\"([^>]*?)".">(\s)?#is", "\\1\\3\\5", $txt );
# And convert it back again...
$txt = str_replace( "<#EMO_DIR>", "<#EMO_DIR#>", $txt );
# Legacy
$txt = preg_replace( "#.+?#", "\\1" , $txt );
# New (3.0)
$txt = IPSText::unconvertSmilies( $txt );
//-----------------------------------------
// Clean up nbsp
//-----------------------------------------
$txt = str_replace( ' ', "\t", $txt );
$txt = str_replace( ' ' , " ", $txt );
if ( $this->parse_bbcode )
{
//-----------------------------------------
// Custom bbcode...
//-----------------------------------------
$txt = preg_replace( "#(.+?)#is", "[acronym=\"\\1\"]\\2[/acronym]", $txt );
$txt = preg_replace( "#(.+?)#is", "[entry=\"\\2\"]\\3[/entry]", $txt );
$txt = preg_replace( "#(.+?)#is", "[blog=\"\\2\"]\\3[/blog]", $txt );
$txt = preg_replace( "#(.+?)#is", "[post=\"\\2\"]\\3[/post]", $txt );
$txt = preg_replace( "#(.+?)#is", "[topic=\"\\1\"]\\2[/topic]", $txt );
$txt = preg_replace( "#<\{POST_SNAPBACK\}>#is", "[snapback]\\3[/snapback]", $txt );
$txt = preg_replace( "#(.+?)
(.+?)
#is", "[codebox]\\2[/codebox]", $txt );
$txt = preg_replace( "#(.+?)#is", "[extract]\\1[/extract]", $txt );
$txt = preg_replace( "#(.+?)#is", "[spoiler]\\1[/spoiler]", $txt );
//-----------------------------------------
// SQL
//-----------------------------------------
$txt = preg_replace_callback( "#(.+?)(.+?)(.+?)#is", array( &$this, 'unconvert_sql'), $txt );
//-----------------------------------------
// HTML
//-----------------------------------------
$txt = preg_replace_callback( "#(.+?)(.+?)(.+?)#is", array( &$this, 'unconvert_htm'), $txt );
//-----------------------------------------
// Images / Flash
//-----------------------------------------
$txt = preg_replace_callback( "#.+?#", array( &$this, 'unconvert_flash'), $txt );
$txt = preg_replace( "#
]+?>#is" , "\[img\]\\1\[/img\]" , $txt );
//-----------------------------------------
// Email, URLs
//-----------------------------------------
$txt = preg_replace( "#(.+?)#s" , "\[email=\\1\]\\2\[/email\]" , $txt );
$txt = preg_replace( "#(.+?)#s" , "\[url=\"\\1\\2\"\]\\3\[/url\]" , $txt );
//-----------------------------------------
// Quote
//-----------------------------------------
$txt = preg_replace( "#(.+?)#" , '[quote]' , $txt );
$txt = preg_replace( "#(.+?)#", "[quote name='\\1' date='\\2']" , $txt );
$txt = preg_replace( "#(.+?)#" , "[quote name='\\1']" , $txt );
$txt = preg_replace( "#(.+?)#" , '[/quote]' , $txt );
//-----------------------------------------
// Super old quotes
//-----------------------------------------
$txt = preg_replace( "#\[quote=(.+?),(.+?)\]#i" , "[quote name='\\1' date='\\2']", $txt );
//-----------------------------------------
// URL Inside Quote
//-----------------------------------------
$txt = preg_replace( "#\[quote=(.*?)\[url(.*?)\](.+?)\[\/url\]\]#i", "[quote=\\1\\3]", str_replace( "\\", "", $txt ) );
//-----------------------------------------
// New quote
//-----------------------------------------
$txt = preg_replace_callback( "#(.+?)#si", array( &$this, '_parse_new_quote'), $txt );
//-----------------------------------------
// Ident => Block quote
//-----------------------------------------
while( preg_match( "#(.+?)
#is" , $txt ) )
{
$txt = preg_replace( "#(.+?)
#is" , "[indent]\\1[/indent]", $txt );
}
//-----------------------------------------
// CODE
//-----------------------------------------
$txt = preg_replace( "#(.+?)#", '[code]' , $txt );
$txt = preg_replace( "#(.+?)#", '[/code]', $txt );
//-----------------------------------------
// left, right, center
//-----------------------------------------
$txt = preg_replace( "#(.+?)
#is" , "[\\1]\\2[/\\1]", $txt );
//-----------------------------------------
// Start off with the easy stuff
//-----------------------------------------
$txt = $this->parse_simple_tag_recursively( 'b' , 'b' , 0, $txt );
$txt = $this->parse_simple_tag_recursively( 'i' , 'i' , 0, $txt );
$txt = $this->parse_simple_tag_recursively( 'u' , 'u' , 0, $txt );
$txt = $this->parse_simple_tag_recursively( 'strike', 's' , 0, $txt );
$txt = $this->parse_simple_tag_recursively( 'sub' , 'sub', 0, $txt );
$txt = $this->parse_simple_tag_recursively( 'sup' , 'sup', 0, $txt );
//-----------------------------------------
// List headache
//-----------------------------------------
$txt = preg_replace( "#(\n){0,1}#" , "\\1\[list\]" , $txt );
$txt = preg_replace( "#(\n){0,1}#" , "\\1\[list=1\]" , $txt );
$txt = preg_replace( "#(\n){0,1}#" , "\\1\[list=\\2\]\n" , $txt );
$txt = preg_replace( "#(\n){0,1}- #" , "\n\[*\]" , $txt );
$txt = preg_replace( "#(\n){0,1}
(\n){0,1}#", "\n\[/list\]\\2" , $txt );
$txt = preg_replace( "#(\n){0,1}(\n){0,1}#", "\n\[/list\]\\2" , $txt );
//-----------------------------------------
// Opening style attributes
//-----------------------------------------
$txt = preg_replace( "#(.+?)#" , "[size=\\1]" , $txt );
$txt = preg_replace( "#(.+?)#" , "[color=\"\\1\"]", $txt );
$txt = preg_replace( "#(.+?)#" , "[font=\"\\1\"]" , $txt );
$txt = preg_replace( "#(.+?)#" , "[background=\\1]" , $txt );
//-----------------------------------------
// Closing style attributes
//-----------------------------------------
$txt = preg_replace( "#(.+?)#" , "[/size]" , $txt );
$txt = preg_replace( "#(.+?)#" , "[/color]", $txt );
$txt = preg_replace( "#(.+?)#" , "[/font]" , $txt );
$txt = preg_replace( "#(.+?)#", "[/background]" , $txt );
//-----------------------------------------
// LEGACY SPAN TAGS
//-----------------------------------------
//-----------------------------------------
// WYSI-Weirdness #9923464: Opera span tags
//-----------------------------------------
while ( preg_match( "#(.+?)#is", $txt ) )
{
$txt = preg_replace( "#(.+?)#is", "\[font=\\1\]\\2\[/font\]", $txt );
}
while ( preg_match( "#(.+?)#is", $txt ) )
{
$txt = preg_replace_callback( "#(.+?)#is" , array( &$this, 'unconvert_size' ), $txt );
}
while ( preg_match( "#(.+?)#is", $txt ) )
{
$txt = preg_replace( "#(.+?)#is" , "\[color=" . trim("\\1") . "\]\\2\[/color\]", $txt );
}
while ( preg_match( "#(.+?)#is", $txt ) )
{
$txt = preg_replace( "#(.+?)#is", "\[font=\"" . trim("\\1") . "\"\]\\2\[/font\]", $txt );
}
while ( preg_match( "#(.+?)#is", $txt ) )
{
$txt = preg_replace( "#(.+?)#is", "\[background=\\1\]\\2\[/font\]", $txt );
}
# Legacy
$txt = preg_replace( "#(.+?)#is" , "\[s\]\\1\[/s\]" , $txt );
//-----------------------------------------
// Tidy up the end quote stuff
//-----------------------------------------
$txt = preg_replace( "#(\[/QUOTE\])\s*?
\s*#si", "\\1\n", $txt );
$txt = preg_replace( "#(\[/QUOTE\])\s*?
\s*#si" , "\\1\n", $txt );
$txt = preg_replace( "##" , "" , $txt );
$txt = str_replace( "", "", $txt );
$txt = str_replace( "", "(tm)", $txt );
}
//-----------------------------------------
// Unconvert custom bbcode
//-----------------------------------------
$txt = $this->post_db_unparse_bbcode( $txt );
//-----------------------------------------
// Parse html
//-----------------------------------------
if ( $this->parse_html )
{
$txt = str_replace( "'", "'", $txt);
}
return trim(stripslashes($txt));
}
/**
* Parse new quotes
*
* @access protected
* @param string Quote data
* @param string Raw text
* @return string Converted text
*/
protected function _parse_new_quote( $matches=array() )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$return = array();
$quote_data = $matches[1];
$quote_text = $matches[2];
//-----------------------------------------
// No data?
//-----------------------------------------
if ( ! $quote_data )
{
return '[quote]';
}
else
{
preg_match( "#\(post=(.+?)?:date=(.+?)?:name=(.+?)?\)#", $quote_data, $match );
if ( $match[3] )
{
$return[] = " name='{$match[3]}'";
}
if ( $match[1] )
{
$return[] = " post='".intval($match[1])."'";
}
if ( $match[2] )
{
$return[] = " date='{$match[2]}'";
}
return str_replace( ' ', ' ', '[quote' . implode( ' ', $return ).']' );
}
}
/**
* Convert font-size HTML back into BBCode
*
* @param integer Core size
* @param string Raw text
* @return string Converted text
*/
protected function unconvert_size( $matches=array() )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$size = trim($matches[1]);
$text = $matches[2];
foreach( $this->font_sizes as $k => $v )
{
if( $size == $v )
{
$size = $k;
break;
}
}
//$size -= 7;
return '[size='.$size.']'.$text.'[/size]';
}
/**
* Convert flash HTML back into BBCode
*
* @param string Raw text
* @return string Converted text
*/
protected function unconvert_flash($matches=array())
{
$f_arr = explode( "+", $matches[1] );
return '[flash='.$f_arr[0].','.$f_arr[1].']'.$f_arr[2].'[/flash]';
}
/**
* Convert SQL HTML back into BBCode
*
* @param string Raw text
* @return string Converted text
*/
protected function unconvert_sql($matches=array())
{
$sql = stripslashes($matches[2]);
$sql = preg_replace( "##is", "", $sql );
$sql = str_replace( "" , "", $sql );
$sql = rtrim( $sql );
return '[sql]'.$sql.'[/sql]';
}
/**
* Convert HTML TAG HTML back into BBCode
*
* @param string Raw text
* @return string Converted text
*/
protected function unconvert_htm($matches=array())
{
$html = stripslashes($matches[2]);
$html = preg_replace( "##is", "", $html );
$html = str_replace( "" , "", $html );
$html = rtrim( $html );
return '[html]'.$html.'[/html]';
}
/**
* Pre-edit unparse custom BBCode
*
* @param string Converted text
* @return string Raw text
*/
protected function post_db_unparse_bbcode($t="")
{
//-----------------------------------------
// INIT
//-----------------------------------------
$snapback = 0;
//-----------------------------------------
// Check...
//-----------------------------------------
if ( is_array( ipsRegistry::cache()->getCache('bbcode') ) and count( ipsRegistry::cache()->getCache('bbcode') ) )
{
foreach( ipsRegistry::cache()->getCache('bbcode') as $row )
{
if( !$row['bbcode_replace'] )
{
continue;
}
$preg_tag = preg_quote( $row['bbcode_replace'], '#' );
//NK: only return the first match
$preg_tag = preg_replace( '/\\\{option\\\}/', '(.*?)', $preg_tag, 1 );
$preg_tag = preg_replace( '/\\\{content\\\}/', '(.*?)', $preg_tag, 1 );
$preg_tag = str_replace( '\{option\}', '.*?', $preg_tag );
$preg_tag = str_replace( '\{content\}', '.*?', $preg_tag );
// Bug 5658 - tags in custom bbcode don't play nice with inbuilt bbcode
$preg_tag = str_replace( "\", "\(?!\<\!--/sizec|\<\!--/colorc|\<\!--/fontc|\<\!--/backgroundc)", $preg_tag );
//-----------------------------------------
// Slightly slower
//-----------------------------------------
while ( preg_match_all( "#".$preg_tag."#si", $t, $match ) )
{
for ( $i = 0; $i < count($match[0]); $i++)
{
//-----------------------------------------
// Does the option tag come first?
//-----------------------------------------
$_option = 1;
$_content = 2;
if ( $row['bbcode_switch_option'] )
{
$_option = 2;
$_content = 1;
}
else if( count( $match ) == 2 )
{
$_content = 1;
}
# XSS Check: Bug ID: 980
if ( $row['bbcode_tag'] == 'post' OR $row['bbcode_tag'] == 'topic' OR $row['bbcode_tag'] == 'snapback' )
{
$match[ $_option ][$i] = intval( $match[ $_option ][$i] );
}
# Recurse?
if ( preg_match( "#".$preg_tag."#si", $match[ $_content ][$i] ) )
{
$match[ $_content ][$i] = $this->post_db_unparse_bbcode( $match[ $_content ][$i] );
}
$tmp = '[' . $row['bbcode_tag'];
if( $row['bbcode_useoption'] )
{
if( $row['bbcode_switch_option'] )
{
$tmp .= '={content}]{option}[/' . $row['bbcode_tag'] . ']';
}
else
{
$tmp .= '={option}]{content}[/' . $row['bbcode_tag'] . ']';
}
}
else
{
$tmp .= ']{content}[/' . $row['bbcode_tag'] . ']';
}
$tmp = str_replace( '{option}' , $match[ $_option ][$i], $tmp );
$tmp = str_replace( '{content}', $match[ $_content ][$i], $tmp );
$t = str_replace( $match[0][$i], $tmp, $t );
}
}
}
}
return $t;
}
/**
* Recursively parse a simple tag
*
* @param string Tag name (ie "b", "i", "s")
* @param string Convert tag (ie "b", "i", "strike" )
* @param int To BBcode
* @param string HTML to search in
* @return string Parsed HTML;
*/
protected function parse_simple_tag_recursively( $tag_name, $convert_name, $bbcode, $text )
{
//----------------------------------------
// INIT
//----------------------------------------
$_open = ( $bbcode ) ? '[' : '<';
$_close = ( $bbcode ) ? ']' : '>';
$_s_open = ( $bbcode ) ? '<' : '[';
$_s_close = ( $bbcode ) ? '>' : ']';
$total_length = strlen( $text );
$_text = $text;
$statement = "";
# Tag specifics
$tag_open = $_open . $tag_name . $_close;
$found_tag_open = 0;
$tag_close = $_open . "/" . $tag_name . $_close;
$found_tag_close = 0;
//----------------------------------------
// Keep the server busy for a while
//----------------------------------------
while ( 1 == 1 )
{
//-----------------------------------------
// Update template length
//-----------------------------------------
$_beginning_of_code = 0;
$_l_text = strtolower( $_text );
//----------------------------------------
// Look for opening [TAG].
//----------------------------------------
$found_tag_open = strpos( $_l_text, $tag_open, $found_tag_close );
//----------------------------------------
// No logic found?
//----------------------------------------
if ( $found_tag_open === FALSE )
{
break;
}
//----------------------------------------
// End [/TAG] statement?
//----------------------------------------
$found_tag_close = strpos( $_l_text, $tag_close, $found_tag_open );
//----------------------------------------
// No end statement found
//----------------------------------------
if ( $found_tag_close === FALSE )
{
return $_text;
}
$_beginning_of_code = $found_tag_open + strlen( $tag_open );
//----------------------------------------
// Check recurse
//----------------------------------------
$tag_found_recurse = $_beginning_of_code;
while ( 1 == 1 )
{
//----------------------------------------
// Got an IF?
//----------------------------------------
$tag_found_recurse = strpos( $_l_text, $tag_open, $tag_found_recurse );
//----------------------------------------
// None found...
//----------------------------------------
if ( $tag_found_recurse === FALSE OR $tag_found_recurse >= $found_tag_close )
{
break;
}
$tag_end_recurse = $found_tag_close + strlen( $tag_close );
# Start at tag_found_recurse...
$found_tag_close = strpos( $_l_text, $tag_close, $tag_found_recurse );
//----------------------------------------
// None found...
//----------------------------------------
if ( $found_tag_close === FALSE )
{
return $_text;
}
$tag_found_recurse += strlen( $tag_open );
}
//----------------------------------------
// Continue
//----------------------------------------
$_code = substr( $_text, $_beginning_of_code, $found_tag_close - $_beginning_of_code );
//----------------------------------------
// Recurse
//----------------------------------------
if ( strpos( strtolower( $_code ), $tag_open ) !== FALSE )
{
$_code = $this->parse_simple_tag_recursively( $tag_name, $convert_name, $bbcode, $_code );
}
//----------------------------------------
// Swap old text for new...
//----------------------------------------
$_new_code = $_s_open . $convert_name . $_s_close . $_code . $_s_open . '/' . $convert_name . $_s_close;
$_text = substr_replace( $_text, $_new_code, $found_tag_open, ( $found_tag_close - $found_tag_open ) + strlen( $tag_close ) );
$found_tag_close = $found_tag_open + strlen($_new_code);
}
return $_text;
}
}