* Invision Power Services * IP.Board v3.1.4 * BBCode parsing core - legacy routine * Last Updated: $Date: 2010-01-15 10:18:44 -0500 (Fri, 15 Jan 2010) $ * * * @author $Author: bfarber $ * @copyright (c) 2001 - 2009 Invision Power Services, Inc. * @license http://www.invisionpower.com/community/board/license.html * @package IP.Board * @link http://www.invisionpower.com * @since 9th March 2005 11:03 * @version $Revision: 5713 $ */ 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 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 = $this->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}(\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 private * @param string Quote data * @param string Raw text * @return string Converted text */ private 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 */ private 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 */ private 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 */ private 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 */ private 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 */ private 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; */ private 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 = mb_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; } }