繁体   English   中英

PHP:对象上的递归htmlspecialchars

[英]PHP: Recursive htmlspecialchars on object

我想为来自各种来源的数据建立一个通用的消毒剂。 通过消毒我的意思是(在这个阶段)将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渲染数据(例如放入表格)

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

您只想在输出到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上下文中使用的所有内容。

您可以尝试以下方法

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
              ...
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);

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

另请检查此问题在PHP中使用array_walk_recursive获取对象

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM