3

我想为来自各种来源的数据建立一个通用的消毒剂。我的意思是(在这个阶段)将 htmlspecialchars 应用于字符串。现在,来自这些源的数据可以是任何东西,从对象到数组再到字符串,都是嵌套的(而且很复杂),而且格式总是有点不同。

所以我想到了一个递归的 htmlspecialchars 函数,它适用于数组和对象,并且只将 htmlspecialchars 应用于字符串,但是我如何递归地遍历一个对象呢?

谢谢。

编辑:我想我应该提到这一点 - 我实际上正在构建一个严重依赖 JS 和 JSON 进行客户端-服务器通信的 RIA。服务器唯一要做的就是从数据库中获取数据并通过 JSON 将其返回给客户端,格式如下:

{"stat":"ok","data":{...}}

现在正如我所说,数据可以是任何东西,不仅来自字符串形式的数据库,还来自 XML 处理 JSON 的工作流程如下:

  1. 从 DB/XML 获取数据(源编码为 iso-8859-1)
  2. 将它们放入“数据”数组

  3. 使用递归从 iso-8859-1 转换为 utf-8

    private function utf8_encode_deep(&$input) {
    if (is_string($input)) {
        $input = $this -> str_encode_utf8($input);
    } else if (is_array($input)) {
        foreach ($input as &$value) {
            $this -> utf8_encode_deep($value);
        }
    
        unset($value);
    } else if (is_object($input)) {
        $vars = array_keys(get_object_vars($input));
    
        foreach ($vars as $var) {
            $this -> utf8_encode_deep($input -> $var);
        }
    }
    }
    
  4. 使用 PHPjson_encode将数据转换为 JSON

  5. 将数据发送(回显)到客户端

  6. 使用 JS 渲染数据(例如放入表格)

在这之间的某个地方,应该以某种方式对数据进行清理(在这个阶段只有 htmlspecialchars)。现在的问题应该是:在哪里消毒,使用什么方法?

4

4 回答 4

1

您只想在输出到 HTML 时转义。而且您无法将完整的数组或对象输出到 HTML 中,因此转义所有内容似乎无效。

由于您的 JSON 输出,您有一个间接级别。因此,您无法在 PHP 中决定数据用于什么上下文 - JSON 仍然是纯文本,而不是 HTML。

因此,要决定是否必须为 HTML 转义 JSON 中的任何数据,我们必须知道您的 Javascript 是如何使用 JSON 数据的。

示例:如果您的 JSON 被视为纯文本,并且包含类似的内容<b>BOLD</b>,那么在任何 HTML 中使用时的预期结果就是该文本,包括看起来像 HTML 标记的字符,但没有粗体排版。只有当您的 Javascript 客户端将此测试作为纯文本处理时才会发生这种情况,例如,它不会用于innerHTML()将其放置在页面上,因为这会激活 HTML 标记,而只会激活innerText()textContent()或任何其他方便的方法,例如 jQuery ( .text())。

另一方面,如果您希望 JSON 包含馈入的现成 HTML innerHTML(),那么您必须先转义此字符串,然后才能将其放入 JSON。但是,只有当您不想为其添加任何格式时,您才必须转义整个字符串。否则,您将处于使用模板将预定义格式与用户内容混合的情况:用户内容在放入 HTML 上下文时必须转义,但结果不能 - 否则 Javascript 无法将其放入innerHTML()并启用格式。

基本上,对数组或对象中的所有内容进行全局转义很可能是错误的,除非您知道 Javascript 将在 HTML 上下文中使用的所有内容。

于 2012-10-03T17:31:30.837 回答
1

您可以尝试以下方法

class MyClass {
    public $var1 = '<b>value 1</b>';
    public $var2 = '<b>value 2</b>';
    public $var3 = array('<b>value 3</b>');
}

$list = array();
$list[0]['nice'] = range("A", "C");
$list[0]['bad'] = array("<div>A</div>","<div>B</div>","<div>C</div>",new MyClass());
$list["<b>gloo</b>"] = array(new MyClass(),"<b>WOW</b>");

var_dump(__htmlspecialchars($list));

使用的功能

function __htmlspecialchars($data) {
    if (is_array($data)) {
        foreach ( $data as $key => $value ) {
            $data[htmlspecialchars($key)] = __htmlspecialchars($value);
        }
    } else if (is_object($data)) {
        $values = get_class_vars(get_class($data));
        foreach ( $values as $key => $value ) {
            $data->{htmlspecialchars($key)} = __htmlspecialchars($value);
        }
    } else {
        $data = htmlspecialchars($data);
    }
    return $data;
}

输出类似的东西

array
  0 => 
    array
      'nice' => 
        array
          0 => string 'A' (length=1)
          1 => string 'B' (length=1)
          2 => string 'C' (length=1)
      'bad' => 
        array
          0 => string '&lt;div&gt;A&lt;/div&gt;' (length=24)
          1 => string '&lt;div&gt;B&lt;/div&gt;' (length=24)
          2 => string '&lt;div&gt;C&lt;/div&gt;' (length=24)
          3 => 
            object(MyClass)[1]
              ...


    array
      0 => 
        object(MyClass)[2]
          public 'var1' => string '&lt;b&gt;value 1&lt;/b&gt;' (length=26)
          public 'var2' => string '&lt;b&gt;value 2&lt;/b&gt;' (length=26)
          public 'var3' => 
            array
              ...
于 2012-10-03T18:02:23.603 回答
0
function htmlrecursive($data){
    if (is_array($data) && count($data) > 1){
        foreach ($data as &$d){
            $d = htmlrecursive($d);
        }
    } else if (!is_array($data)){
        return htmlspecialchars($data);
    }
    else {
         return htmlspecialchars($data[0])
    }
}

htmlrecursive($array);
于 2012-10-03T17:29:31.250 回答
0

对于需要实现ArrayAccess 接口的对象,您可以进行数组遍历递归

还要检查这个问题Getting an object to work with array_walk_recursive in PHP

于 2012-10-03T17:32:00.570 回答