--- codefilter.module Mon Dec 3 16:53:33 2007
+++ codefilterFixed.module Mon Dec 3 16:53:35 2007
@@ -87,6 +87,92 @@ function codefilter_escape($text) {
}
/**
+ * A regex cannot easily find the end of a block as the terminating ?> may be within a string or multiline comment.
+ * Therefore, php blocks have to be looked at specially and an intelligent guess has to be made as to which ?> actually terminates
+ * the block. To do this, for each possible ending to a block, highlight_string is called to see if things after that ending are
+ * highlighted as non-php-code, and if so, then that must be the correct ending. Otherwise, we move onto the next possible ending
+ * and see what highlight_string thinks about ending there.
+ */
+function codefilter_prepare_php_block($text) {
+ $start_offset = 0;
+
+ while(true) {
+ // Find the next php block and the next mini block
+ $position_php = strpos($text, '', $position_php);
+ if($position_php_end === false)
+ $position_php = false;
+ }
+
+ $position_mini = strpos($text, '<%', $start_offset);
+ $position_mini_end = 0;
+ if($position_mini !== false) {
+ $position_mini_end = strpos($text, '%>', $position_mini);
+ if($position_mini_end === false)
+ $position_mini = false;
+ }
+
+ if($position_php === false && $position_mini === false)
+ break;
+
+ // Prepare to look at the next block
+ $position_start = $position_php;
+ $position_end = $position_php_end;
+ $position_starter = '';
+ if($position_php === false || ($position_mini !== false && $position_mini < $position_php)) {
+ $position_start = $position_mini;
+ $position_end = $position_mini_end;
+ $position_starter = '<%';
+ $position_ender = '%>';
+ }
+ $start_offset = $position_end;
+
+ while($position_end) {
+ // See what highlight_string thinks about ending the block here
+ $to_highlight = substr($text, $position_start + strlen($position_starter), $position_end - $position_start - strlen($position_starter));
+ $highlighted = highlight_string(' ?>', true);
+ /*
+ If the block to be highlighted is valid, then the first "?>" will be styled (?>)
+ and the second one will be unstyled (raw), so get the positions of the last styled and the last raw occurance of "?>"
+ and if the styled appears before the raw, then the block is valid. highlight_string has an odd bug where it can remove
+ single quotes (') from a piece of code when the code is invalid, so this is checked for. For example, this call:
+ highlight_string(" ?>");
+ Will remove the single quote, style the penultimate "?>" and leave the final "?>" raw.
+ */
+ $position_styled_close = strrpos($highlighted, '">?>');
+ $position_raw_close = strrpos($highlighted, '?>');
+ if ($position_styled_close !== false && $position_raw_close !== false && ($position_styled_close + 2) < $position_raw_close) {
+ if (substr_count($to_highlight, "'") == substr_count($highlighted, "'")) {
+ break;
+ }
+ }
+
+ // Move onto the next possible ending
+ $position_end = strpos($text, $position_ender, $position_end + 1);
+ }
+ if($position_end === false) {
+ // No more possible endings, but highlight_string hasn't been happy yet, so revert back to the first possible ending
+ $position_end = strpos($text, $position_ender, $position_start);
+ }
+
+ // We've found the ending, so mark this block
+ $before_code = substr($text, 0, $position_start);
+ $position_start = $position_start + strlen($position_starter);
+ $the_code = substr($text, $position_start, $position_end - $position_start);
+ $position_end = $position_end + strlen($position_ender);
+ $after_code = substr($text, $position_end);
+ $text = $before_code ."\xFEphp\xFF". codefilter_escape($the_code) ."\xFE/php\xFF";
+ $start_offset = strlen($text);
+ $text = $text . $after_code;
+ }
+
+ return $text;
+}
+
+/**
* Implementation of hook_filter()
*/
function codefilter_filter($op, $delta = 0, $format = -1, $text = '') {
@@ -101,7 +187,7 @@ function codefilter_filter($op, $delta =
// Note: we use the bytes 0xFE and 0xFF to replace < > during the filtering process.
// These bytes are not valid in UTF-8 data and thus least likely to cause problems.
$text = preg_replace('@(.+?)@se', "'\xFEcode\xFF'. codefilter_escape('\\1') .'\xFE/code\xFF'", $text);
- $text = preg_replace('@[\[<](\?php|%)(.+?)(\?|%)[\]>]@se', "'\xFEphp\xFF'. codefilter_escape('\\2') .'\xFE/php\xFF'", $text);
+ $text = codefilter_prepare_php_block($text);
return $text;
case 'process':