|
From: FlorinCB <ory...@us...> - 2008-06-16 05:28:33
|
Update of /cvsroot/mxbb/core/includes In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv28251 Modified Files: mx_functions_bbcode.php mx_functions_tools.php Log Message: bbcode fix Index: mx_functions_tools.php =================================================================== RCS file: /cvsroot/mxbb/core/includes/mx_functions_tools.php,v retrieving revision 1.29 retrieving revision 1.30 diff -C2 -d -r1.29 -r1.30 *** mx_functions_tools.php 15 Jun 2008 21:00:03 -0000 1.29 --- mx_functions_tools.php 16 Jun 2008 05:28:28 -0000 1.30 *************** *** 317,321 **** if (!empty($text)) { ! $this->bbcode_uid = ($this->bbcode_on) ? make_bbcode_uid() : ''; $text = $this->prepare_message(trim($text), $this->html_on, $this->bbcode_on, $this->smilies_on, $this->bbcode_uid); } --- 317,321 ---- if (!empty($text)) { ! $this->bbcode_uid = ($this->bbcode_on) ? mx_make_bbcode_uid() : ''; $text = $this->prepare_message(trim($text), $this->html_on, $this->bbcode_on, $this->smilies_on, $this->bbcode_uid); } *************** *** 403,407 **** $text = ( !empty($text) ) ? htmlspecialchars(trim(stripslashes($text))) : ''; ! $bbcode_uid = ( $this->bbcode_on ) ? make_bbcode_uid() : ''; $text = stripslashes($this->prepare_message(addslashes($this->unprepare_message($text)), $this->html_on, $this->bbcode_on, $this->smilies_on, $bbcode_uid)); --- 403,407 ---- $text = ( !empty($text) ) ? htmlspecialchars(trim(stripslashes($text))) : ''; ! $bbcode_uid = ( $this->bbcode_on ) ? mx_make_bbcode_uid() : ''; $text = stripslashes($this->prepare_message(addslashes($this->unprepare_message($text)), $this->html_on, $this->bbcode_on, $this->smilies_on, $bbcode_uid)); *************** *** 507,511 **** if($bbcode_on && $bbcode_uid != '') { ! $message = bbencode_first_pass($message, $bbcode_uid); } --- 507,511 ---- if($bbcode_on && $bbcode_uid != '') { ! $message = mx_bbencode_first_pass($message, $bbcode_uid); } *************** *** 1857,1861 **** if ( $this->bbcode_on ) { ! $bbcode_uid = make_bbcode_uid(); } --- 1857,1861 ---- if ( $this->bbcode_on ) { ! $bbcode_uid = mx_make_bbcode_uid(); } *************** *** 2040,2044 **** if ( $this->bbcode_on ) { ! $bbcode_uid = make_bbcode_uid(); } --- 2040,2044 ---- if ( $this->bbcode_on ) { ! $bbcode_uid = mx_make_bbcode_uid(); } Index: mx_functions_bbcode.php =================================================================== RCS file: /cvsroot/mxbb/core/includes/mx_functions_bbcode.php,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** mx_functions_bbcode.php 15 Jun 2008 21:08:18 -0000 1.4 --- mx_functions_bbcode.php 16 Jun 2008 05:28:28 -0000 1.5 *************** *** 508,511 **** --- 508,830 ---- } + function mx_make_bbcode_uid() + { + // Unique ID for this message.. + + $uid = mx_dss_rand(); + $uid = substr($uid, 0, BBCODE_UID_LEN); + + return $uid; + } + + function mx_bbencode_first_pass($text, $uid) + { + // pad it with a space so we can distinguish between FALSE and matching the 1st char (index 0). + // This is important; bbencode_quote(), bbencode_list(), and bbencode_code() all depend on it. + $text = " " . $text; + + // [CODE] and [/CODE] for posting code (HTML, PHP, C etc etc) in your posts. + $text = mx_bbencode_first_pass_pda($text, $uid, '[code]', '[/code]', '', true, ''); + + // [QUOTE] and [/QUOTE] for posting replies with quote, or just for quoting stuff. + $text = mx_bbencode_first_pass_pda($text, $uid, '[quote]', '[/quote]', '', false, ''); + $text = mx_bbencode_first_pass_pda($text, $uid, '/\[quote=\\\\"(.*?)\\\\"\]/is', '[/quote]', '', false, '', "[quote:$uid=\\\"\\1\\\"]"); + + // [list] and [list=x] for (un)ordered lists. + $open_tag = array(); + $open_tag[0] = "[list]"; + + // unordered.. + $text = mx_bbencode_first_pass_pda($text, $uid, $open_tag, "[/list]", "[/list:u]", false, 'replace_listitems'); + + $open_tag[0] = "[list=1]"; + $open_tag[1] = "[list=a]"; + + // ordered. + $text = mx_bbencode_first_pass_pda($text, $uid, $open_tag, "[/list]", "[/list:o]", false, 'replace_listitems'); + + // [color] and [/color] for setting text color + $text = preg_replace("#\[color=(\#[0-9A-F]{6}|[a-z\-]+)\](.*?)\[/color\]#si", "[color=\\1:$uid]\\2[/color:$uid]", $text); + + // [size] and [/size] for setting text size + $text = preg_replace("#\[size=([1-2]?[0-9])\](.*?)\[/size\]#si", "[size=\\1:$uid]\\2[/size:$uid]", $text); + + // [b] and [/b] for bolding text. + $text = preg_replace("#\[b\](.*?)\[/b\]#si", "[b:$uid]\\1[/b:$uid]", $text); + + // [u] and [/u] for underlining text. + $text = preg_replace("#\[u\](.*?)\[/u\]#si", "[u:$uid]\\1[/u:$uid]", $text); + + // [i] and [/i] for italicizing text. + $text = preg_replace("#\[i\](.*?)\[/i\]#si", "[i:$uid]\\1[/i:$uid]", $text); + + // [img]image_url_here[/img] code.. + $text = preg_replace("#\[img\]((http|ftp|https|ftps)://)([^ \?&=\#\"\n\r\t<]*?(\.(jpg|jpeg|gif|png)))\[/img\]#sie", "'[img:$uid]\\1' . str_replace(' ', '%20', '\\3') . '[/img:$uid]'", $text); + + // Remove our padding from the string.. + return substr($text, 1);; + + } // bbencode_first_pass() + + /** + * $text - The text to operate on. + * $uid - The UID to add to matching tags. + * $open_tag - The opening tag to match. Can be an array of opening tags. + * $close_tag - The closing tag to match. + * $close_tag_new - The closing tag to replace with. + * $mark_lowest_level - boolean - should we specially mark the tags that occur + * at the lowest level of nesting? (useful for [code], because + * we need to match these tags first and transform HTML tags + * in their contents.. + * $func - This variable should contain a string that is the name of a function. + * That function will be called when a match is found, and passed 2 + * parameters: ($text, $uid). The function should return a string. + * This is used when some transformation needs to be applied to the + * text INSIDE a pair of matching tags. If this variable is FALSE or the + * empty string, it will not be executed. + * If open_tag is an array, then the pda will try to match pairs consisting of + * any element of open_tag followed by close_tag. This allows us to match things + * like [list=A]...[/list] and [list=1]...[/list] in one pass of the PDA. + * + * NOTES: - this function assumes the first character of $text is a space. + * - every opening tag and closing tag must be of the [...] format. + */ + function mx_bbencode_first_pass_pda($text, $uid, $open_tag, $close_tag, $close_tag_new, $mark_lowest_level, $func, $open_regexp_replace = false) + { + $open_tag_count = 0; + + if (!$close_tag_new || ($close_tag_new == '')) + { + $close_tag_new = $close_tag; + } + + $close_tag_length = strlen($close_tag); + $close_tag_new_length = strlen($close_tag_new); + $uid_length = strlen($uid); + + $use_function_pointer = ($func && ($func != '')); + + $stack = array(); + + if (is_array($open_tag)) + { + if (0 == count($open_tag)) + { + // No opening tags to match, so return. + return $text; + } + $open_tag_count = count($open_tag); + } + else + { + // only one opening tag. make it into a 1-element array. + $open_tag_temp = $open_tag; + $open_tag = array(); + $open_tag[0] = $open_tag_temp; + $open_tag_count = 1; + } + + $open_is_regexp = false; + + if ($open_regexp_replace) + { + $open_is_regexp = true; + if (!is_array($open_regexp_replace)) + { + $open_regexp_temp = $open_regexp_replace; + $open_regexp_replace = array(); + $open_regexp_replace[0] = $open_regexp_temp; + } + } + + if ($mark_lowest_level && $open_is_regexp) + { + mx_message_die(GENERAL_ERROR, "Unsupported operation for bbcode_first_pass_pda()."); + } + + // Start at the 2nd char of the string, looking for opening tags. + $curr_pos = 1; + while ($curr_pos && ($curr_pos < strlen($text))) + { + $curr_pos = strpos($text, "[", $curr_pos); + + // If not found, $curr_pos will be 0, and the loop will end. + if ($curr_pos) + { + // We found a [. It starts at $curr_pos. + // check if it's a starting or ending tag. + $found_start = false; + $which_start_tag = ""; + $start_tag_index = -1; + + for ($i = 0; $i < $open_tag_count; $i++) + { + // Grab everything until the first "]"... + $possible_start = substr($text, $curr_pos, strpos($text, ']', $curr_pos + 1) - $curr_pos + 1); + + // + // We're going to try and catch usernames with "[' characters. + // + if( preg_match('#\[quote=\\\"#si', $possible_start, $match) && !preg_match('#\[quote=\\\"(.*?)\\\"\]#si', $possible_start) ) + { + // OK we are in a quote tag that probably contains a ] bracket. + // Grab a bit more of the string to hopefully get all of it.. + if ($close_pos = strpos($text, '"]', $curr_pos + 14)) + { + if (strpos(substr($text, $curr_pos + 14, $close_pos - ($curr_pos + 14)), '[quote') === false) + { + $possible_start = substr($text, $curr_pos, $close_pos - $curr_pos + 7); + } + } + } + + // Now compare, either using regexp or not. + if ($open_is_regexp) + { + $match_result = array(); + if (preg_match($open_tag[$i], $possible_start, $match_result)) + { + $found_start = true; + $which_start_tag = $match_result[0]; + $start_tag_index = $i; + break; + } + } + else + { + // straightforward string comparison. + if (0 == strcasecmp($open_tag[$i], $possible_start)) + { + $found_start = true; + $which_start_tag = $open_tag[$i]; + $start_tag_index = $i; + break; + } + } + } + + if ($found_start) + { + // We have an opening tag. + // Push its position, the text we matched, and its index in the open_tag array on to the stack, and then keep going to the right. + $match = array("pos" => $curr_pos, "tag" => $which_start_tag, "index" => $start_tag_index); + array_push($stack, $match); + // + // Rather than just increment $curr_pos + // Set it to the ending of the tag we just found + // Keeps error in nested tag from breaking out + // of table structure.. + // + $curr_pos += strlen($possible_start); + } + else + { + // check for a closing tag.. + $possible_end = substr($text, $curr_pos, $close_tag_length); + if (0 == strcasecmp($close_tag, $possible_end)) + { + // We have an ending tag. + // Check if we've already found a matching starting tag. + if (sizeof($stack) > 0) + { + // There exists a starting tag. + $curr_nesting_depth = sizeof($stack); + // We need to do 2 replacements now. + $match = array_pop($stack); + $start_index = $match['pos']; + $start_tag = $match['tag']; + $start_length = strlen($start_tag); + $start_tag_index = $match['index']; + + if ($open_is_regexp) + { + $start_tag = preg_replace($open_tag[$start_tag_index], $open_regexp_replace[$start_tag_index], $start_tag); + } + + // everything before the opening tag. + $before_start_tag = substr($text, 0, $start_index); + + // everything after the opening tag, but before the closing tag. + $between_tags = substr($text, $start_index + $start_length, $curr_pos - $start_index - $start_length); + + // Run the given function on the text between the tags.. + if ($use_function_pointer) + { + $between_tags = $func($between_tags, $uid); + } + + // everything after the closing tag. + $after_end_tag = substr($text, $curr_pos + $close_tag_length); + + // Mark the lowest nesting level if needed. + if ($mark_lowest_level && ($curr_nesting_depth == 1)) + { + if ($open_tag[0] == '[code]') + { + $code_entities_match = array('#<#', '#>#', '#"#', '#:#', '#\[#', '#\]#', '#\(#', '#\)#', '#\{#', '#\}#'); + $code_entities_replace = array('<', '>', '"', ':', '[', ']', '(', ')', '{', '}'); + $between_tags = preg_replace($code_entities_match, $code_entities_replace, $between_tags); + } + $text = $before_start_tag . substr($start_tag, 0, $start_length - 1) . ":$curr_nesting_depth:$uid]"; + $text .= $between_tags . substr($close_tag_new, 0, $close_tag_new_length - 1) . ":$curr_nesting_depth:$uid]"; + } + else + { + if ($open_tag[0] == '[code]') + { + $text = $before_start_tag . '[code]'; + $text .= $between_tags . '[/code]'; + } + else + { + if ($open_is_regexp) + { + $text = $before_start_tag . $start_tag; + } + else + { + $text = $before_start_tag . substr($start_tag, 0, $start_length - 1) . ":$uid]"; + } + $text .= $between_tags . substr($close_tag_new, 0, $close_tag_new_length - 1) . ":$uid]"; + } + } + + $text .= $after_end_tag; + + // Now.. we've screwed up the indices by changing the length of the string. + // So, if there's anything in the stack, we want to resume searching just after it. + // otherwise, we go back to the start. + if (sizeof($stack) > 0) + { + $match = array_pop($stack); + $curr_pos = $match['pos']; + // bbcode_array_push($stack, $match); + // ++$curr_pos; + } + else + { + $curr_pos = 1; + } + } + else + { + // No matching start tag found. Increment pos, keep going. + ++$curr_pos; + } + } + else + { + // No starting tag or ending tag.. Increment pos, keep looping., + ++$curr_pos; + } + } + } + } // while + + return $text; + + } // mx_bbencode_first_pass_pda() + + /** * Does second-pass bbencoding. This should be used before displaying the message in |