CodeIgniterの学習 34 - htmlspecialcharsをh()で呼べるようにする
(08/11/30訂正)
CIにはform_prep()ってのがあったみたい。
でもh()の方が短いので、コメントアウトしてただのラッパーにしてみた。
そういえば、フォームヘルパの学習が足りていないな。
(08/12/15追記)
ちなみにform_prep()でエスケープするのは、formヘルパを使わずに、
俺みたいに自力でhtmlタグをビューに貼っている場合。
formヘルパ(form_input等)を使うと、内部で勝手にform_prep()を呼んでくれる。
CodeIgniter1.7以降はフォーム周りの仕様が変わり、デフォルト値のセットや、nameに配列が使える(hoge[]が使える)等
だいぶ仕様が良くなった(旧仕様もまだ使える)ので、まとめを書くつもりだがいつになるかは未定。
(以上追記おわり)
今日は俺俺ヘルパを移植することにする。
セキュリティー系、汎用系、俺俺系と、いろいろでCodeIgniter側の置き場所に悩むが、
とりあえず俺俺系は全て一つのヘルパ(cmn_helper.php)に寄せて、
後で適切なMY_.+_helper.phpに移動することにする。
まずは、CakePHPみたく h()で htmlspecialcharsを呼んで、ビュー側でHTMLエンティティ変換をするようにしてみる。
ソース
arrayが渡ってきたら、再帰的にエスケープする。オブジェクトは無視してNULLを返す。
application/helpers/cmn_helper.php
<?php if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); if ( ! function_exists( 'h' ) ) { // HTMLエンティティ変換 function h( $data , $charset = 'UTF-8' ) { //form_prep()のラッパに変更 /* if ( is_array( $data ) ) { $ret = array(); foreach( $data as $k => $v ) { $ret[] = h( $v , $charset ); } return $ret; }elseif ( is_object( $data ) ) { return NULL; }else { return htmlspecialchars( $data, ENT_QUOTES , $charset ); } */ if ( is_object( $data ) ) { return NULL; } $CI = get_instance(); $CI->load->helper('form'); return form_prep($data); } } /** * End of file cmn_helper.php */ /** * Location: ./application/helpers/cmn_helper.php */ ?>
system/application/config/autoload.phpでデフォルトで有効にする
$autoload['helper'] に cmn_helperを追加<?php //上略 $autoload['helper'] = array('cmn'); //下略 ?>
動作確認
適当なビューで動作確認してみる。
ちなみに元データは
<b>a</b><input type="text" value="bbb">"''''<script>window.alert('fuga');</sc r i pt>""<<< >>><button>aaa</button>
みたいなデータをCodeIgniterで作った画面上から登録している。
ここには載せていないが、
DBに格納する前に、xss_cleanを噛ましているので、
データベース上では、
<b>a</b><input type="text" value="bbb">"''''[removed]window.alert('fuga');[removed]""<<< >>><button>aaa</button>
と、inputタグ部分とscriptタグ部分が、
自動的にHTMLエンティティ変換とスクリプトタグ無効化の置換がなされて格納されている。
(system/libraries/Input.phpのxss_clean内でいろんなことが行われている。)
実験1:h()無しの場合
ビュー側ソース:
<input type="text" name="tmp_name" id="tmp_name" value="<?=$this->validation->tmp_name;?>" size="140" />
生成されるHTML:
<input type="text" name="tmp_name" id="tmp_name" value="<b>a</b><input type="text" value="bbb">"''''[removed]window.alert('fuga');[removed]""<<< >>><button>aaa</button>" size="140" />
うむ、ばっちり崩れている。
実験2:h()有りの場合
ビュー側ソース:
<input type="text" name="tmp_name" id="tmp_name" value="<?=h($this->validation->tmp_name);?>" size="140" />
生成されるHTML:
<input type="text" name="tmp_name" id="tmp_name" value="<b>a</b>&lt;input type="text" value="bbb"&gt;"''''[removed]window.alert&#40;'fuga'&#41;;[removed]""<<< >>><button>aaa</button>" size="140" />
おk
何が渡ってくるか信用出来ないから画面で最後にエスケープしました。ってお話。