前回 は JSP でのデフォルト HTML エスケープを検証しました。今回は Velocity を見てみます。
デフォルトエスケープの設定
Velocity では ReferenceInsertionEventHandler を使ってデフォルトでの HTML エスケープを実現できます。このクラスは名前の通り参照がテンプレートに挿入される時にフックして値を操作することができます。
コード例です。完全なソースコードはこちらを参照してください。
public class MyRefrenceInsertionEventHandler
implements ReferenceInsertionEventHandler {
@Override
public Object referenceInsert(String reference, Object value) {
if (value == null) {
return null;
} else if (reference.endsWith("NoEscape")
|| reference.endsWith("NoEscape}")) {
return value;
} else if (value instanceof SafeHtml) {
return ((SafeHtml) value).getSafeHtmlValue();
} else {
return escape(value.toString());
}
}
}
ここでの処理は以下の通りです。
- 参照名が NoEscape で終わっていたらエスケープしない
- 値が SafeHtml を実装していたらエスケープしない
- それ以外の場合はエスケープする
JSP の ELResolver が EL の一部を受け取るのと違って、ReferenceInsertionEventHandler では完全な参照名を受け取れるので String 以外をエスケープできないなんてことはありません。
動作検証
JSP の時と同じモデルを使って動作を検証します。
WikiPage wikiPage = new WikiPage(
"<strong>Tokyo</strong>",
new WikiText("<strong>Tokyo</strong> is the capital of Japan."));
まず title の出力です。
エスケープできていますね。続いて WikiPage の出力。
WikiPage#toString() の結果をエスケープできています。前回の JSP はエスケープできていませんでした。
今度は明示的にエスケープを回避してみます。
ReferenceInsertionEventHandler で書いたように NoEscape で終わる参照名の場合はエスケープしません。
こちらも SafeHtml を実装している場合はエスケープしません。
まとめ
ReferenceInsertionEventHandler を使ってデフォルトでの HTML エスケープ、参照名とクラス定義による明示的なエスケープの回避ができました。完璧ですね。