Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

introduce global function raw() to mark text as not-to-be-escaped

to remove ambiguity over what parts of built forms are escaped and
and which are not, and increase security in everything else that
prints html, run everything supplied by the application through h()
to escape html.

since there may be instances where html should be printed, like in
flash_errors(), introduce a global function raw() that can be used
to protect a string until it hits the helpers, where it will be
recognized as a raw object and not run through h().  most things
that did h() now do raw_or_h().

note that the raw object must continue all the way through to the
helper, so doing

    $this->add_flash_error(raw("<b>error:</b> ") . $somevar)

does nothing, because the Raw object will get __toString()'d right
away and get seen as a normal string when it gets to the helper,
which will run h() on it.  the entire argument must be the raw
object with your own html protection done on the parts you need it:

    $this->add_flash_error(raw("<b>error:</b> " . h($somevar)))
  • Loading branch information...
commit 565979cfac2abc37d8b625d65b756a773e205c83 1 parent 5d269e3
@jcs authored
View
17 lib/helpers/form_common.php
@@ -34,7 +34,8 @@ protected function output_form_around_closure($url_or_obj,
print "<form"
. $this->options_to_s($options)
. " action=\""
- . $this->html_helper->link_from_obj_or_string($url_or_obj) . "\""
+ . h($this->html_helper->link_from_obj_or_string($url_or_obj))
+ . "\""
. ">";
if (strtolower($options["method"]) != "get")
@@ -45,7 +46,7 @@ protected function output_form_around_closure($url_or_obj,
. "\""
. " />";
- print Utils::to_s($this, $form_content);
+ print Utils::to_s($this, $form_content, $this->controller);
print "</form>";
@@ -81,9 +82,9 @@ protected function options_for_select($choices, $selected) {
else
$is_selected = false;
- $str .= "<option value=\"" . h($key) . "\""
+ $str .= "<option value=\"" . raw_or_h($key) . "\""
. ($is_selected ? " selected" : "")
- . ">" . h($val) . "</option>";
+ . ">" . raw_or_h($val) . "</option>";
}
return $str;
@@ -97,23 +98,23 @@ protected function options_to_s($options) {
$opts_s = "";
foreach ($options as $k => $v)
- $opts_s .= " " . $k . "=\"" . $v . "\"";
+ $opts_s .= " " . $k . "=\"" . raw_or_h($v) . "\"";
return $opts_s;
}
/* for each attribute in a form_for() object that has errors, output a div
* around it that should be styled to stand out */
- protected function wrap_field_with_errors($field, $html) {
+ protected function wrap_field_with_errors($field, $field_html) {
if (!$this->form_object)
throw new HalfMoonExceptions("wrap_field_with_errors called when "
. "no form object");
if ($this->form_object->errors &&
$this->form_object->errors->on($field))
- return "<div class=\"fieldWithErrors\">" . $html . "</div>";
+ return "<div class=\"fieldWithErrors\">" . $field_html . "</div>";
else
- return $html;
+ return $field_html;
}
}
View
2  lib/helpers/form_helper.php
@@ -90,7 +90,7 @@ public function check_box($field, $options = array(), $checked_value = 1,
return "<input"
. " type=\"hidden\" "
- . " name=\"" . $options["name"] . "\""
+ . " name=\"" . h($options["name"]) . "\""
. " value=\"" . h($unchecked_value) . "\""
. " />"
. $this->wrap_field_with_errors($field,
View
10 lib/helpers/form_tag_helper.php
@@ -44,7 +44,7 @@ public function check_box_tag($field, $value = 1, $checked = false,
$options["type"] = "checkbox";
if (!isset($options["value"]))
- $options["value"] = h($value);
+ $options["value"] = $value;
if ($checked)
$options["checked"] = "checked";
@@ -112,12 +112,12 @@ public function radio_button_tag($field, $value, $checked = false,
$options["type"] = "radio";
if (!isset($options["value"]))
- $options["value"] = h($value);
+ $options["value"] = $value;
if ($checked)
$options["checked"] = "checked";
- return "<input " . $this->options_to_s($options) . " />";
+ return "<input" . $this->options_to_s($options) . " />";
}
/* create a <select> box with options */
@@ -155,7 +155,7 @@ public function text_area_tag($field, $content = null, $options = array()) {
}
return "<textarea " . $this->options_to_s($options) . ">"
- . h($content)
+ . raw_or_h($content)
. "</textarea>";
}
@@ -166,7 +166,7 @@ public function text_field_tag($field, $value = null, $options = array()) {
if (!isset($options["type"]))
$options["type"] = "text";
- $options["value"] = h($value);
+ $options["value"] = $value;
return "<input" . $this->options_to_s($options) . " />";
}
View
25 lib/helpers/global_helper.php
@@ -15,4 +15,29 @@ function array_last(&$array) {
return $array[count($array) - 1];
}
+/* html helpers escape html with h() everywhere, but for instances where raw
+ * html needs to be printed, send it with raw("text") and it will not get
+ * escaped */
+class Raw {
+ public $raw;
+ public function __construct($text) {
+ $this->raw = $text;
+ }
+ public function __toString() {
+ return $this->raw;
+ }
+}
+
+/* return a Raw object */
+function raw($text) {
+ return new Raw($text);
+}
+
+function raw_or_h($text) {
+ if (is_object($text) && get_class($text) == "Raw")
+ return (string)$text;
+ else
+ return h($text);
+}
+
?>
View
46 lib/helpers/html_helper.php
@@ -11,7 +11,7 @@ public function button_to($text, $obj_or_url, $options = array()) {
if (!isset($options["method"]))
$options["method"] = "post";
- return "<input type=\"button\" value=\"" . $text . "\" "
+ return "<input type=\"button\" value=\"" . raw_or_h($text) . "\" "
. $this->options_for_link($options,
$this->link_from_obj_or_string($obj_or_url))
. " />";
@@ -28,8 +28,8 @@ public function button_to_function($label, $options = array()) {
$options["html_options"]["type"] = "button";
return "<input"
- . " value=\"" . $label . "\""
- . " onclick=\"" . $options["onclick"] . "\""
+ . " value=\"" . raw_or_h($label) . "\""
+ . " onclick=\"" . raw_or_h($options["onclick"]) . "\""
. $this->options_for_link($options["html_options"])
. " />";
}
@@ -52,14 +52,15 @@ public function error_messages_for($obj, $obj_name = "", $obj_prefix = "") {
$html = "<p>"
. "<div class=\"flash-error\">"
. "<strong>" . $obj->errors->size() . " "
- . \ActiveRecord\Utils::pluralize_if($obj->errors->size(),
- "error")
- . " prohibited " . $obj_prefix . " " . $obj_name . " from "
- . "being " . ($obj->is_new_record() ? "created" : "saved")
+ . h(\ActiveRecord\Utils::pluralize_if($obj->errors->size(),
+ "error"))
+ . " prohibited " . raw_or_h($obj_prefix) . " "
+ . raw_or_h($obj_name) . " from being "
+ . ($obj->is_new_record() ? "created" : "saved")
. ":</strong><br />\n";
foreach ($obj->errors as $err)
- $html .= $err . "<br />";
+ $html .= raw_or_h($err) . "<br />";
$html .= "</div>"
. "</p>";
@@ -75,7 +76,9 @@ public function flash_errors() {
if (isset($_SESSION["flash_errors"]) &&
count((array)$_SESSION["flash_errors"])) {
$html = "<div class=\"flash-error\">"
- . implode("<br />\n", (array)$_SESSION["flash_errors"])
+ . implode("<br />\n", array_map(function($e) {
+ return raw_or_h($e); },
+ (array)$_SESSION["flash_errors"]))
. "</div>";
/* clear out for the next view */
@@ -91,8 +94,11 @@ public function flash_notices() {
if (isset($_SESSION["flash_notices"]) &&
count((array)$_SESSION["flash_notices"])) {
+ /* not escaped */
$html = "<div class=\"flash-notice\">"
- . implode("<br />\n", (array)$_SESSION["flash_notices"])
+ . implode("<br />\n", array_map(function($e) {
+ return raw_or_h($e); },
+ (array)$_SESSION["flash_notices"]))
. "</div>";
/* clear out for the next view */
@@ -128,8 +134,9 @@ public function javascript_include_tag($files) {
. "/public/javascripts/" . $file_value);
}
- $out .= "<script type=\"text/javascript\" src=\"/javascripts/"
- . $file_value . "\"></script>\n";
+ $out .= "<script type=\"text/javascript\" src=\""
+ . h("/javascripts/" . $file_value)
+ . "\"></script>\n";
}
}
@@ -191,8 +198,10 @@ public function link_from_obj_or_string($thing) {
/* create an <a href> tag for a given url or object (defaulting to
* the (table)/show/(id) */
public function link_to($text, $obj_or_url, $options = array()) {
- return "<a href=\"" . $this->link_from_obj_or_string($obj_or_url)
- . "\"" . $this->options_for_link($options) . ">" . $text . "</a>";
+ return "<a href=\""
+ . raw_or_h($this->link_from_obj_or_string($obj_or_url)) . "\""
+ . $this->options_for_link($options) . ">" . raw_or_h($text)
+ . "</a>";
}
public function options_for_link($options = array(),
@@ -273,11 +282,12 @@ public function stylesheet_link_tag($files, $options = array()) {
if (isset($options["xml"]))
$out .= "<?xml-stylesheet type=\"text/css\" "
- . "href=\"/stylesheets/" . $file_value . "\" ?" . ">\n";
+ . "href=\"" . h("/stylesheets/" . $file_value)
+ . "\" ?" . ">\n";
else
- $out .= "<link href=\"/stylesheets/" . $file_value . "\" "
- . "media=\"screen\" rel=\"stylesheet\" "
- . "type=\"text/css\"/>\n";
+ $out .= "<link href=\"/" . h("stylesheets/"
+ . $file_value) . "\" media=\"screen\" "
+ . "rel=\"stylesheet\" type=\"text/css\"/>\n";
}
}
View
2  lib/helpers/prototype_helper.php
@@ -39,7 +39,7 @@ public function link_to_function($text, $javascript, $options = array()) {
if (!isset($options["href"]))
$options["href"] = "#";
- return "<a href=\"" . $options["href"] . "\""
+ return "<a href=\"" . raw_or_h($options["href"]) . "\""
. $this->html_helper->options_for_link($options) . ">" . $text
. "</a>";
}
View
16 test/RawTest.php
@@ -0,0 +1,16 @@
+<?php
+
+require(__DIR__ . "/../lib/halfmoon.php");
+
+class RawTest extends PHPUnit_Framework_TestCase {
+ public function testRaw() {
+ $str = "<b>this is some text</b>";
+
+ $this->assertEquals("&lt;b&gt;this is some text&lt;/b&gt;",
+ h($str));
+
+ $this->assertEquals("<b>this is some text</b>", (string)raw($str));
+ }
+}
+
+?>
Please sign in to comment.
Something went wrong with that request. Please try again.