簡體   English   中英

PHP 5.4.16 DOMDocument刪除了部分Javascript

[英]PHP 5.4.16 DOMDocument removes parts of Javascript

我嘗試將HTML頁面從遠程服務器加載到PHP腳本中,該腳本應使用DOMDocument類處理HTML。 但是我已經看到,DOMDocument類刪除了HTML頁面隨附的Javascript的某些部分。 有一些事情像:

<script type="text/javascript">
//...
function printJSPage() {
    var printwin=window.open('','haha','top=100,left=100,width=800,height=600');
    printwin.document.writeln(' <table border="0" cellspacing="5" cellpadding="0" width="100%">');
    printwin.document.writeln(' <tr>');
    printwin.document.writeln(' <td align="left" valign="bottom">');
    //...
    printwin.document.writeln('</td>');
    //...
}
</script>

但是DOMDocument改變了,即行

printwin.document.writeln('</td>');

printwin.document.writeln(' ');

以及其他很多事情(例如,最后一個腳本標記不再存在。結果,我得到了一個完整的銷毀頁面,無法進一步發送。

因此,我認為DOMDocument在Javascript代碼中的HTML標記方面存在問題,並嘗試更正該代碼以生成格式正確的文檔。 我可以阻止DOMDocument中的Javascript解析嗎?

PHP代碼片段為:

$stdin = file_get_contents('php://stdin');
$dom = new \DOMDocument();
@$dom->loadHTML($stdin);
return $dom->saveHTML();   // will produce wrong HTML
//return $stdin;           // will produce correct HTML

我已經存儲了兩個HTML版本,並與Meld進行了比較。

我也測試過

@$dom->loadXML($stdin);
return $dom->saveHTML();

但是我沒有從物體上得到任何東西。

這可能會有所幫助。 這個想法是用保證有效的HTML和唯一的字符串替換腳本內容,然后將其替換。

它將腳本標記內的所有內容替換為這些內容的MD5,然后將其替換回來。

$scriptContainer = [];
$str = preg_replace_callback ("#<script([^>]*)>(.*?)</script>#s", function ($matches) use (&$scriptContainer) {
     $scriptContainer[md5($matches[2])] = $matches[2];
        return "<script".$matches[1].">".md5($matches[2])."</script>";
    }, $str);
$dom = new \DOMDocument();
@$dom->loadHTML($str);
$final = strtr($dom->saveHTML(), $scriptContainer); 

由於使用str_replace(array_keys($scriptContainer), $scriptContainer, $dom->saveHTML())格式化數組的方式, strtr在這里非常方便。

我非常驚訝PHP無法正確解析HTML內容。 它似乎是在解析XML內容(這也是錯誤的,因為CDATA內容是解析的,而不是按字面值處理)。 但是就是這樣,如果您想要一個真正的文檔解析器,那么您應該考慮使用jsdom的Node.js解決方案

如果<script>中有<script> ,則以下(不是很聰明)的解決方案將處理該問題。 仍然存在一個問題:如果<script>標記不平衡,則解決方案將不起作用。 如果您的Javascript使用String.fromCharCode來打印String </script> ,則會發生這種情況。

$scriptContainer = array();

function getPosition($tag) {
    return $tag[0][1];
}

function getContent($tag) {
    return $tag[0][0];
}

function isStart($tag) {
    $x = getContent($tag);
    return ($x[0].$x[1] === "<s");
}

function isEnd($tag) {
    $x = getContent($tag);
    return ($x[0].$x[1] === "</");
}

function mask($str, $scripts) {
    global $scriptContainer;

    $res = "";
    $start = null;
    $stop = null;
    $idx = 0;

    $count = 0;
    foreach ($scripts as $tag) {

            if (isStart($tag)) {
                    $count++;
                    $start = ($start === null) ? $tag : $start;
            }

            if (isEnd($tag)) {
                    $count--;
                    $stop = ($count == 0) ? $tag : $stop;
            }

            if ($start !== null && $stop !== null) {
                    $res .= substr($str, $idx, getPosition($start) - $idx);
                    $res .= getContent($start);
                    $code = substr($str, getPosition($start) + strlen(getContent($start)), getPosition($stop) - getPosition($start) - strlen(getContent($start)));
                    $hash = md5($code);
                    $res .= $hash;
                    $res .= getContent($stop);

                    $scriptContainer[$hash] = $code;

                    $idx = getPosition($stop) + strlen(getContent($stop));
                    $start = null;
                    $stop = null;
            }
    }

    $res .= substr($str, $idx);
    return $res;
}

preg_match_all("#\<script[^\>]*\>|\<\/script\>#s", $html, $scripts, PREG_OFFSET_CAPTURE|PREG_SET_ORDER);
$html = mask($html, $scripts);

libxml_use_internal_errors(true);
$dom = new DOMDocument();
$dom->loadHTML($html);
libxml_use_internal_errors(false);

// handle some things within DOM

echo strtr($dom->saveHTML(), $scriptContainer);

如果將preg_match_all的“ script”字符串替換為“ style”,則還可以屏蔽CSS樣式,該樣式也可以包含標簽名稱(即,在注釋中)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM