diff options
-rw-r--r-- | phpBB/includes/message_parser.php | 117 |
1 files changed, 94 insertions, 23 deletions
diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 39489250d7..52bba31da3 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -360,29 +360,11 @@ class bbcode_firstpass extends bbcode } /** - * Parse code tag - * Expects the argument to start right after the opening [code] tag and to end with [/code] + * Parse code text from code tag + * @private */ - function bbcode_code($stx, $in) + function bbcode_parse_code($stx, $code) { - if (!$this->check_bbcode('code', $in)) - { - return ''; - } - - // We remove the hardcoded elements from the code block here because it is not used in code blocks - // Having it here saves us one preg_replace per message containing [code] blocks - // Additionally, magic url parsing should go after parsing bbcodes, but for safety those are stripped out too... - $htm_match = get_preg_expression('bbcode_htm'); - unset($htm_match[4], $htm_match[5]); - $htm_replace = array('\1', '\1', '\2', '\1'); - - $out = ''; - - // Strip the last [/code] block from $in - $code = substr($in, 0, -7); - $code = preg_replace($htm_match, $htm_replace, $code); - switch (strtolower($stx)) { case 'php': @@ -434,13 +416,102 @@ class bbcode_firstpass extends bbcode $code = substr($code, 0, -1); } - $out .= "[code=$stx:" . $this->bbcode_uid . ']' . $code . '[/code:' . $this->bbcode_uid . ']'; + return "[code=$stx:" . $this->bbcode_uid . ']' . $code . '[/code:' . $this->bbcode_uid . ']'; break; default: - $out .= '[code:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($code) . '[/code:' . $this->bbcode_uid . ']'; + return '[code:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($code) . '[/code:' . $this->bbcode_uid . ']'; break; } + } + + /** + * Parse code tag + * Expects the argument to start right after the opening [code] tag and to end with [/code] + */ + function bbcode_code($stx, $in) + { + if (!$this->check_bbcode('code', $in)) + { + return ''; + } + + // We remove the hardcoded elements from the code block here because it is not used in code blocks + // Having it here saves us one preg_replace per message containing [code] blocks + // Additionally, magic url parsing should go after parsing bbcodes, but for safety those are stripped out too... + $htm_match = get_preg_expression('bbcode_htm'); + unset($htm_match[4], $htm_match[5]); + $htm_replace = array('\1', '\1', '\2', '\1'); + + $in = preg_replace($htm_match, $htm_replace, $in); + $out = $code_block = ''; + $open = 1; + + while ($in) + { + // Determine position and tag length of next code block + preg_match('#(.*?)(\[code(?:=([a-z]+))?\])(.+)#is', $in, $buffer); + $pos = (isset($buffer[1])) ? strlen($buffer[1]) : false; + $tag_length = (isset($buffer[2])) ? strlen($buffer[2]) : false; + + // Determine position of ending code tag + $pos2 = stripos($in, '[/code]'); + + // Which is the next block, ending code or code block + if ($pos !== false && $pos < $pos2) + { + // Open new block + if (!$open) + { + $out .= substr($in, 0, $pos); + $in = substr($in, $pos); + $stx = (isset($buffer[3])) ? $buffer[3] : ''; + $code_block = ''; + } + else + { + // Already opened block, just append to the current block + $code_block .= substr($in, 0, $pos) . ((isset($buffer[2])) ? $buffer[2] : ''); + $in = substr($in, $pos); + } + + $in = substr($in, $tag_length); + $open++; + } + else + { + // Close the block + if ($open == 1) + { + $code_block .= substr($in, 0, $pos2); + + // Parse this code block + $out .= $this->bbcode_parse_code($stx, $code_block); + $code_block = ''; + $open--; + } + else if ($open) + { + // Close one open tag... add to the current code block + $code_block .= substr($in, 0, $pos2 + 7); + $open--; + } + else + { + // end code without opening code... will be always outside code block + $out .= substr($in, 0, $pos2 + 7); + } + + $in = substr($in, $pos2 + 7); + } + } + + // if now $code_block has contents we need to parse the remaining code while removing the last closing tag to match up. + if ($code_block) + { + $code_block = substr($code_block, 0, -7); + $out .= $this->bbcode_parse_code($stx, $code_block); + } return $out; } |