diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/gallery/helpers/MY_html.php | 91 | ||||
-rw-r--r-- | modules/gallery/tests/Html_Helper_Test.php | 55 | ||||
-rw-r--r-- | modules/gallery/tests/Xss_Security_Test.php | 86 |
3 files changed, 182 insertions, 50 deletions
diff --git a/modules/gallery/helpers/MY_html.php b/modules/gallery/helpers/MY_html.php new file mode 100644 index 00000000..eb388811 --- /dev/null +++ b/modules/gallery/helpers/MY_html.php @@ -0,0 +1,91 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class html extends html_Core { + /** + * Returns a string that is safe to be used in HTML (XSS protection). + * + * If $html is a string, the returned string will be HTML escaped. + * If $html is a SafeString instance, the returned string may contain + * unescaped HTML which is assumed to be safe. + * + * Example:<pre> + * <div><?= html::clean($php_var) ?> + * </pre> + */ + static function clean($html) { + return new SafeString($html); + } + + /** + * Returns a string that is safe to be used in HTML (XSS protection), + * purifying (filtering) the given HTML to ensure that the result contains + * only non-malicious HTML. + * + * Example:<pre> + * <div><?= html::purify($item->title) ?> + * </pre> + */ + static function purify($html) { + return SafeString::purify($html); + } + + /** + * Flags the given string as safe to be used in HTML (free of malicious HTML/JS). + * + * Example:<pre> + * // Parameters to t() are automatically escaped by default. + * // If the parameter is marked as safe, it won't get escaped. + * t('Go <a href="%url">there</a>', + * array("url" => html::mark_safe(url::current()))) + * </pre> + */ + static function mark_safe($html) { + return SafeString::of_safe_html($html); + } + + /** + * Escapes the given string for use in JavaScript. + * + * Example:<pre> + * <script type="text/javascript>" + * var some_js_var = "<?= html::escape_for_js($php_var) ?>"; + * </script> + * </pre> + */ + static function escape_for_js($string) { + return SafeString::of($string)->for_js(); + } + + /** + * Returns a string safe for use in HTML element attributes. + * + * Assumes that the HTML element attribute is already + * delimited by single or double quotes + * + * Example:<pre> + * <a title="<?= html::clean_for_attribute($php_var) ?>">; + * </script> + * </pre> + * @return the string escaped for use in HTML attributes. + */ + static function clean_attribute($string) { + return self::clean($string)->for_html_attr(); + } +} diff --git a/modules/gallery/tests/Html_Helper_Test.php b/modules/gallery/tests/Html_Helper_Test.php new file mode 100644 index 00000000..4d934ad5 --- /dev/null +++ b/modules/gallery/tests/Html_Helper_Test.php @@ -0,0 +1,55 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class Html_Helper_Test extends Unit_Test_Case { + public function clean_test() { + $safe_string = html::clean("hello <p >world</p>"); + $this->assert_equal("hello <p >world</p>", + $safe_string); + $this->assert_true($safe_string instanceof SafeString); + } + + public function purify_test() { + $safe_string = html::purify("hello <p >world</p>"); + $this->assert_equal("hello <p>world</p>", + $safe_string); + $this->assert_true($safe_string instanceof SafeString); + } + + public function mark_safe_test() { + $safe_string = html::mark_safe("hello <p >world</p>"); + $this->assert_true($safe_string instanceof SafeString); + $safe_string_2 = html::clean($safe_string); + $this->assert_equal("hello <p >world</p>", + $safe_string_2); + } + + public function escape_for_js_test() { + $string = html::escape_for_js("hello's <p >world</p>"); + $this->assert_equal("hello\\'s <p >world<\\/p>", + $string); + } + + public function clean_attribute_test() { + $safe_string = SafeString::of_safe_html("hello's <p >world</p>"); + $safe_string = html::clean_attribute($safe_string); + $this->assert_equal("hello's <p >world</p>", + $safe_string); + } +}
\ No newline at end of file diff --git a/modules/gallery/tests/Xss_Security_Test.php b/modules/gallery/tests/Xss_Security_Test.php index a2d3d59b..8e5f8354 100644 --- a/modules/gallery/tests/Xss_Security_Test.php +++ b/modules/gallery/tests/Xss_Security_Test.php @@ -101,7 +101,7 @@ class Xss_Security_Test extends Unit_Test_Case { // 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_safestring(true); + $frame->is_safe_html(true); $frame->expr_append("("); $token_number++; @@ -111,9 +111,11 @@ class Xss_Security_Test extends Unit_Test_Case { // 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", "of_safe_html", "purify")) && + in_array($tokens[$token_number + 2][1], array("of", "purify")) && self::_token_matches("(", $tokens, $token_number + 3)) { - $frame->is_safestring(true); + // 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("); @@ -123,7 +125,7 @@ class Xss_Security_Test extends Unit_Test_Case { } } else if ($token[1] == "json_encode") { if (self::_token_matches("(", $tokens, $token_number + 1)) { - $frame->json_encode_called(true); + $frame->is_safe_js(true); $frame->expr_append("("); $token_number++; @@ -145,15 +147,34 @@ class Xss_Security_Test extends Unit_Test_Case { $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", "escape_for_js", "clean_attribute_test")) && + self::_token_matches("(", $tokens, $token_number + 3)) { + // Not checking for mark_safe(). 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 ("escape_for_js" == $method) { + $frame->is_safe_js(true); + } else { + $frame->is_safe_html(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")) && + 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("); @@ -161,11 +182,9 @@ class Xss_Security_Test extends Unit_Test_Case { $token = $tokens[$token_number]; if ("for_js" == $method) { - $frame->for_js_called(true); - } else if ("for_html" == $method) { - $frame->for_html_called(true); - } else if ("purified_html" == $method) { - $frame->purified_html_called(true); + $frame->is_safe_js(true); + } else { + $frame->is_safe_html(true); } } } else if ($frame) { @@ -199,12 +218,11 @@ class Xss_Security_Test extends Unit_Test_Case { $state = "DIRTY"; if ($frame->in_script_block()) { $state = "DIRTY_JS"; - if ($frame->for_js_called() || $frame->json_encode_called()) { + if ($frame->is_safe_js()) { $state = "CLEAN"; } } else { - if ($frame->is_safe_html() || $frame->is_safestring() || - $frame->purified_html_called() || $frame->for_html_called()) { + if ($frame->is_safe_html()) { $state = "CLEAN"; } } @@ -255,12 +273,8 @@ class Xss_Security_Test extends Unit_Test_Case { class Xss_Security_Test_Frame { private $_expr = ""; private $_in_script_block = false; - private $_is_safestring = false; - private $_for_js_called = false; - private $_for_html_called = false; - private $_purified_html_called = false; - private $_json_encode_called = false; private $_is_safe_html = false; + private $_is_safe_js = false; private $_line; function __construct($line_number, $in_script_block) { @@ -283,13 +297,6 @@ class Xss_Security_Test_Frame { return $this->_in_script_block; } - function is_safestring($new_val=NULL) { - if ($new_val !== NULL) { - $this->_is_safestring = (bool) $new_val; - } - return $this->_is_safestring; - } - function is_safe_html($new_val=NULL) { if ($new_val !== NULL) { $this->_is_safe_html = (bool) $new_val; @@ -297,32 +304,11 @@ class Xss_Security_Test_Frame { return $this->_is_safe_html; } - function json_encode_called($new_val=NULL) { - if ($new_val !== NULL) { - $this->_json_encode_called = (bool) $new_val; - } - return $this->_json_encode_called; - } - - function for_js_called($new_val=NULL) { - if ($new_val !== NULL) { - $this->_for_js_called = (bool) $new_val; - } - return $this->_for_js_called; - } - - function for_html_called($new_val=NULL) { - if ($new_val !== NULL) { - $this->_for_html_called = (bool) $new_val; - } - return $this->_for_html_called; - } - - function purified_html_called($new_val=NULL) { + function is_safe_js($new_val=NULL) { if ($new_val !== NULL) { - $this->_purified_html_called = (bool) $new_val; + $this->_is_safe_js = (bool) $new_val; } - return $this->_purified_html_called; + return $this->_is_safe_js; } function line() { |