PHP:对象上的递归htmlspecialchars

时间:2012-10-03 17:26:49

标签: php json object recursion

我想为来自各种来源的数据建立一个通用的消毒剂。通过消毒我的意思是(在这个阶段)将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. 使用PHP的json_encode将数据转换为JSON

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

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

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

4 个答案:

答案 0 :(得分: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包含提供给innerHTML()的现成HTML,那么您必须在将此字符串放入JSON之前将其转义。但是,只有在您不想为其添加任何格式时,才必须转义整个字符串。否则,您处于使用模板将预定义格式与用户内容混合的情况:用户内容在放入HTML上下文时必须进行转义,但结果不得 - 否则Javascript无法将其放入innerHTML()并启用格式化。

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

答案 1 :(得分: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
              ...

答案 2 :(得分: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);

答案 3 :(得分:0)

对于需要实现The ArrayAccess interface的对象,您可以执行数组遍历递归

同时检查此问题Getting an object to work with array_walk_recursive in PHP