... block? if (is_array($token) && $token[0] == T_INLINE_HTML) { $inline_html = $token[1]; // T_INLINE_HTML blocks can be split. Need to handle the case // where one token has "expr_append($inline_html); } // Note: This approach won't catch }i', $inline_html, $matches, PREG_OFFSET_CAPTURE)) { $last_match = array_pop($matches[0]); if (is_array($last_match)) { $closing_script_pos = $last_match[1]; } else { $closing_script_pos = $last_match; } } if (preg_match_all('{]*>}i', $inline_html, $matches, PREG_OFFSET_CAPTURE)) { $last_match = array_pop($matches[0]); if (is_array($last_match)) { $opening_script_pos = $last_match[1]; } else { $opening_script_pos = $last_match; } } if ($opening_script_pos != $closing_script_pos) { $in_script_block = $opening_script_pos > $closing_script_pos; } } $preceded_by_quote = preg_match('{[\'"]\s*$}i', $inline_html); $pos = false; if (($in_attribute || $in_attribute_js_context) && ($pos = strpos($inline_html, $delimiter)) !== false) { $in_attribute_js_context = false; $in_attribute = false; $href_attribute_start = false; } if (!$in_attribute_js_context || !$in_attribute) { $pos = ($pos === false) ? 0 : $pos; if (preg_match('{\bhref\s*=\s*(")javascript:[^"]*$}i', $inline_html, $matches, 0, $pos) || preg_match("{\bhref\s*=\s*(')javascript:[^']*$}i", $inline_html, $matches, 0, $pos) || preg_match("{\bon[a-z]+\s*=\s*(')[^']*$}i", $inline_html, $matches, 0, $pos) || preg_match('{\bon[a-z]+\s*=\s*(")[^"]*$}i', $inline_html, $matches, 0, $pos)) { $in_attribute_js_context = true; $in_attribute = true; $delimiter = $matches[1]; $inline_html = ""; } else if (preg_match('{\b([a-z]+)\s*=\s*(")([^"]*)$}i', $inline_html, $matches, 0, $pos) || preg_match("{\b([a-z]+)\s*=\s*(')([^']*)$}i", $inline_html, $matches, 0, $pos)) { $in_attribute = true; $delimiter = $matches[2]; $inline_html = ""; $href_attribute_start = strtolower($matches[1]) == "href" && empty($matches[3]); } } // Look and report each instance of < ? = ... ? > if (!is_array($token)) { // A single char token, e.g: ; ( ) if ($frame) { $frame->expr_append($token); } } else if ($token[0] == T_OPEN_TAG_WITH_ECHO) { // No need for a stack here - assume < ? = cannot be nested. $frame = self::_create_frame($token, $in_script_block, $href_attribute_start, $in_attribute_js_context, $in_attribute, $preceded_by_quote); $href_attribute_start = false; } else if ($frame && $token[0] == T_CLOSE_TAG) { // Store the < ? = ... ? > block that just ended here. $found[$view][] = $frame; $frame = null; } else if ($frame && $token[0] == T_VARIABLE) { $frame->expr_append($token[1]); if ($token[1] == '$theme') { if (self::_token_matches(array(T_OBJECT_OPERATOR, "->"), $tokens, $token_number + 1) && self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && in_array($tokens[$token_number + 2][1], array("thumb_proportion", "site_menu", "album_menu", "tag_menu", "photo_menu", "context_menu", "pager", "site_status", "messages", "album_blocks", "album_bottom", "album_top", "body_attributes", "credits", "dynamic_bottom", "dynamic_top", "footer", "head", "header_bottom", "header_top", "page_bottom", "page_top", "photo_blocks", "photo_bottom", "photo_top", "resize_bottom", "resize_top", "sidebar_blocks", "sidebar_bottom", "sidebar_top", "thumb_bottom", "thumb_info", "thumb_top", "movie_menu")) && self::_token_matches("(", $tokens, $token_number + 3)) { $method = $tokens[$token_number + 2][1]; $frame->expr_append("->$method("); $token_number += 3; $token = $tokens[$token_number]; $frame->is_safe_html(true); } else if (self::_token_matches(array(T_OBJECT_OPERATOR, "->"), $tokens, $token_number + 1) && self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && in_array($tokens[$token_number + 2][1], array("css", "script", "url")) && self::_token_matches("(", $tokens, $token_number + 3) && // Only allow constant strings here self::_token_matches(array(T_CONSTANT_ENCAPSED_STRING), $tokens, $token_number + 4)) { $method = $tokens[$token_number + 2][1]; $frame->expr_append("->$method("); $token_number += 4; $token = $tokens[$token_number]; $frame->is_safe_html(true); } } } else if ($frame && $token[0] == T_STRING) { $frame->expr_append($token[1]); // t() and t2() are special in that they're guaranteed to return a SafeString(). if (in_array($token[1], array("t", "t2"))) { if (self::_token_matches("(", $tokens, $token_number + 1)) { $frame->is_safe_html(true); $frame->expr_append("("); $token_number++; $token = $tokens[$token_number]; } } else if ($token[1] == "SafeString") { // Looking for SafeString::of(... if (self::_token_matches(array(T_DOUBLE_COLON, "::"), $tokens, $token_number + 1) && self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && in_array($tokens[$token_number + 2][1], array("of", "purify")) && self::_token_matches("(", $tokens, $token_number + 3)) { // Not checking for of_safe_html(). We want such calls to be marked dirty (thus reviewed). $frame->is_safe_html(true); $method = $tokens[$token_number + 2][1]; $frame->expr_append("::$method("); $token_number += 3; $token = $tokens[$token_number]; } } else if ($token[1] == "json_encode") { if (self::_token_matches("(", $tokens, $token_number + 1)) { $frame->is_safe_js(true); $frame->expr_append("("); $token_number++; $token = $tokens[$token_number]; } } else if ($token[1] == "url") { // url methods return safe HTML if (self::_token_matches(array(T_DOUBLE_COLON, "::"), $tokens, $token_number + 1) && self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && in_array($tokens[$token_number + 2][1], array("site", "current", "base", "file", "abs_site", "abs_current", "abs_file", "merge")) && self::_token_matches("(", $tokens, $token_number + 3)) { $frame->is_safe_html(true); $frame->is_safe_href_attr(true); $frame->is_safe_attr(true); $method = $tokens[$token_number + 2][1]; $frame->expr_append("::$method("); $token_number += 3; $token = $tokens[$token_number]; } } else if ($token[1] == "html") { if (self::_token_matches(array(T_DOUBLE_COLON, "::"), $tokens, $token_number + 1) && self::_token_matches(array(T_STRING), $tokens, $token_number + 2) && in_array($tokens[$token_number + 2][1], array("clean", "purify", "js_string", "clean_attribute")) && self::_token_matches("(", $tokens, $token_number + 3)) { // Not checking for mark_clean(). We want such calls to be marked dirty (thus reviewed). $method = $tokens[$token_number + 2][1]; $frame->expr_append("::$method("); $token_number += 3; $token = $tokens[$token_number]; if ("js_string" == $method) { $frame->is_safe_js(true); } else { $frame->is_safe_html(true); } if ("clean_attribute" == $method) { $frame->is_safe_attr(true); } } } } else if ($frame && $token[0] == T_OBJECT_OPERATOR) { $frame->expr_append($token[1]); if (self::_token_matches(array(T_STRING), $tokens, $token_number + 1) && in_array($tokens[$token_number + 1][1], array("for_js", "for_html", "purified_html", "for_html_attr")) && self::_token_matches("(", $tokens, $token_number + 2)) { $method = $tokens[$token_number + 1][1]; $frame->expr_append("$method("); $token_number += 2; $token = $tokens[$token_number]; if ("for_js" == $method) { $frame->is_safe_js(true); } else { $frame->is_safe_html(true); } if ("for_html_attr" == $method) { $frame->is_safe_attr(true); } } } else if ($frame) { $frame->expr_append($token[1]); } } } /* * Generate the report * * States for uses of < ? = X ? >: * DIRTY_JS: * In