前のブログで、SQLインジェクションのエスケープについてかいたので、同じような感じのはなしのURLのエンコードについての話。
むかし、どこだったかなあ。。の会社で、http://www.abcdefg.com/~12345のような、~がはいったサイトのとき、なんだったかの問題が起こるというバグがあったと思います。
で、そこの会社の掲示板だったか、コメントを書くところだったかに「単体テストレベル以下ですよ!」と、この問題について「??本当に知っていて書いてるの??」と思える書き込みがあった気がします(記憶違いかも。。。むかしのことなんではっきりしない)。
実は、この~(チルダです、みにくいですけど)、URLエンコード上の問題児で、単体テストでは、はじけないことがあるんですよ。。。
ところが、URLには、よく、つかわれますよね。あるサイトにおいて、そのユーザーのホームページをあらわすとき、(上記の例だと、abcdefg.comのサイトのユーザー12345さんのホーム)は、http://www.abcdefg.com/~12345なんで、このチルダがどーしてもでてきてしまうのです(前のブログ風に言うと、字種を制限したくても、制限できない)
で、なんで単体テストではじけないことがあるのか?
という説明の前に、どういう文字が、本来、エスケープになるのか?という話をします。
それは、以下のサイトにくわしいです。
付録D URLエンコーディング(URLエンコード または URLエスケープ)
http://www.kinet.or.jp/hiromin/cgi_introduction/appendix/url_encode.html
URLエンコーディングというのは、CGIなどで、値を送ったときに abc.cgi?username=%82%74%82%71%82%6b
とかなるような、%16進で現れるところのこと。
そして、
英数字はエンコーディングしないで、そのままの値
漢字は、エンコーディングする
とはっきりしてるからいいんだけど、チルダをふくむ記号においては
そのサイトによると(以下斜体は引用)
英数字以外でURLエンコーディングしなくても良い文字は以下になります。
- _ . ! ~ * ' ( )
っていうことで、チルダを含んでいます。だけど、
(Internet Explorerがエンコードしない文字) * - . @ _
さらに
(Netscape Navigator や Mozilla がエンコードしない文字) * - . _
(@に注目。ねすけは、エンコードする)
てなかんじで、チルダはエンコードされます。ただし、ライブラリとして提供されたとき、上記の理由により、チルダをエンコードしなくても、ルール違反ではありません。
このように、チルダの扱いは(というか、 - _ . ! ~ * ' ( )の扱いは)、一定ではありません。
そのため、チルダは、エンコードしない場合と、エンコードされる場合、どちらのケースもありうる(さらに1システム内で混在する場合もありえる)ということを意識して、システムを組んだり、テストをしたりしないといけません(つまり、チルダのテストは、必要ということ)。
ちなみに、なぜ混在するかというと、いくら自分たちでがんばっても、そのデータを送ってくれるのはブラウザです。世界中のブラウザを確認するわけには行きません。なので、外からの入力は、混在(両方ありえる)と考えておいたほうが無難でしょう。
ところが、仕様作成のときに、これをまったく意識しなかったり、どっちかに決めうちにして開発した場合、単体仕様書には、きめ打ちされて書いてあるか、意識されないで、その記述がないかのどっちかです。
きめうちの場合、単体テストは、どっちかのケースしかテストしません。反対側のケースは、仕様書に書いてないのですから。
記述がない場合も、単体テストでは、テストできないと考えたほうがいいでしょう。仕様書にかいてないのですから。
仕様書に書いてないものは、単体では、はじけません。
というわけで、はじめに書いた、単体テストレベル以下ですよ!」っていうのは疑問。
たぶん、単体は通ってる。これを意識した、結合、総合テストをしていない。
つまり、これは、結合テスト、ないしは総合テストで、チルダつきのURLを入れて、すべてのケースでうまくいくかのシナリオをだしてみないとわかんないことになります。
ということで、URLをフォームから入れたり、CGIの引数にする場合は、チルダのテストは、しといたほうがいいです。
URL以外のフォームでの入力の場合、 - _ . ! ~ * ' ( )のケースっていうのは、やっといたほうが、無難だと思います。