3

私の問題

リッチ テキスト エディター (現時点では FCK 1.6) に貼り付けられた HTML をクリーンアップしたい。クリーニングは、タグのホワイトリスト (およびおそらく属性を持つ別のリスト) に基づいている必要があります。これは主に XSS を防ぐためではなく、見苦しい HTML を削除するためです。

現在、サーバー上でそれを行う方法は見当たらないので、JavaScript で行う必要があると思います。

現在のアイデア

jquery-clean プラグインを見つけましたが、私が見る限り、正規表現を使用して作業を行っており、安全ではないことがわかっています

他の JS ベースのソリューションを見つけられなかったので、jQuery を使用して自分で実装し始めました。貼り付けた html ( ) の jQuery バージョンを作成し$(pastedHtml)、結果のツリーをトラバースして、ホワイトリストに一致しない各要素を削除することで機能しますtagName

私の質問

  • これはもっと良いですか?
  • 貼り付けられたコンテンツを適切に表現するために jQuery を信頼できますか (一致しない終了タグと what-have-you がある可能性があります)。
  • 私が見つけられなかったより良い解決策はすでにありますか?

アップデート

これは私の現在のjQueryベースのソリューションです(詳細であり、広範囲にテストされていません):

function clean(element, whitelist, replacerTagName) {
    // Use div if no replace tag was specified
    replacerTagName = replacerTagName || "div";

    // Accept anything that jQuery accepts
    var jq = $(element);    

    // Create a a copy of the current element, but without its children
    var clone = jq.clone();
    clone.children().remove();

    // Wrap the copy in a dummy parent to be able to search with jQuery selectors
    // 1)
    var wrapper = $('<div/>').append(clone);

    // Check if the element is not on the whitelist by searching with the 'not' selector
    var invalidElement = wrapper.find(':not(' + whitelist + ')');

    // If the element wasn't on the whitelist, replace it.
    if (invalidElement.length > 0) {
       var el = $('<' + replacerTagName + '/>'); 
       el.text(invalidElement.text()); 
       invalidElement.replaceWith(el);   
    }

    // Extract the (maybe replaced) element
    var cleanElement = $(wrapper.children().first());

    // Recursively clean the children of the original element and
    // append them to the cleaned element
    var children = jq.children();
    if (children.length > 0) {
        children.each(function(_index, thechild) {
                          var cleaned = clean(thechild, whitelist, replacerTagName);
                          cleanElement.append(cleaned);
                      });
      } 
    return cleanElement;
}

私はいくつかの点について疑問に思っています (コード内のコメントを参照してください)。

  1. jQuery の ":not" と一致させるために、ダミーの親で要素をラップする必要がありますか?
  2. これは、新しいノードを作成するための推奨される方法ですか?
4

1 に答える 1

2

ブラウザーの HTML 修正機能を活用すると (たとえば、リッチ テキストをinnerHTML空の にコピーしdivて、結果の DOM ツリーを取得する)、HTML が有効であることが保証されます (修正方法はブラウザーによって多少異なります)。とにかく、これはおそらくリッチエディターによって行われますが。

jQuery 独自の text-top DOM 変換もおそらく安全ですが、明らかに遅いので、私はそれを避けます。

jQuery セレクター エンジンに基づくホワイトリストの使用は、子を保持しながら要素を削除するとドキュメントが無効になる可能性があるため、やや注意が必要な場合があります。そのため、ブラウザーは DOM ツリーを変更して修正し、無効な要素を繰り返し処理しようとするスクリプトを混乱させる可能性があります。 . (たとえば、 and は許可しますが、許可ulliませんol。スクリプトはリストのルート要素を削除します。裸の要素は無効であるため、ブラウザはそれらを再度liラップします。これはクリーニング スクリプトによって見落とされます。) 不要な要素をすべての子要素と一緒に破棄すると、問題はありません。ulul

于 2011-03-17T17:51:43.193 に答える