summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAndy Staudacher <andy.st@gmail.com>2009-08-29 22:31:23 -0700
committerAndy Staudacher <andy.st@gmail.com>2009-08-29 22:31:23 -0700
commit952c8856098dcfd9673d344fc71be85b303c8fb1 (patch)
tree4b024be4da15ff9c89c6ab299004977ac93eee51 /modules
parentb4b638be44375c93f5222c7b48ed547845d6d7e5 (diff)
Adding html::clean(), ::purify(), etc.
Diffstat (limited to 'modules')
-rw-r--r--modules/gallery/helpers/MY_html.php91
-rw-r--r--modules/gallery/tests/Html_Helper_Test.php55
-rw-r--r--modules/gallery/tests/Xss_Security_Test.php86
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 &lt;p &gt;world&lt;/p&gt;",
+ $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&#039;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() {