簡體   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