2004-09-07
_ [tDiary] URI エンコード
アクセスログの中に、yahoo のキャッシュページからのアクセスがあった。
http://www.noroi.jp/?year=2003%3Bcategory=COMP
みたいなやつだ。これって、実際に辿ってみると、カテゴリの画面じゃなく最新の画面が出る。さらに、
http://www.noroi.jp/%3Fyear=2003%3Bcategory=COMP
なんてのもあり、こいつは 404 になる。これはこういうものなのか? %xx のデコードはどこでするんだ? パラメータの分解はデコードの前? 後?
ruby にはまだ手が出せないので、perl を使ってみる。
#!/usr/bin/perl
use CGI;
my $q = new CGI;
print $q->header(-type => 'text/plain');
print $_, "\n",' ', $q->param($_), "\n" foreach ($q->param);
こんなやつ。これで試してみても、エンコードしたままだと分解されない。これって tDaiay の問題じゃなかったんだ。tdiary-devel で質問しちゃったよ。ああ…
(URI)とりあえず以下の URI の 2.2 と 2.3 がその回答を示しているかと。<br>http://rfc.net/rfc2396.html#s2.2.<br>'?' は reserved だから '%3f' とは意味が違ってるってことではないかと。<br>RFC によれば、本当は '%3b' もエラーにならなきゃいけないけど、この部分は CGI 側の処理なので HTTP サーバーがハンドリングするのは無理かと。<br>(そういう意味では perl の CGI module は RFC 違反かと。)
「;」はデリミタっつう reserved character なのだから、<br>yahoo の escape 処理がマズいんではないの?<br>perl の CGI module も悪いわけではないです。<br>セパレータという機能を正に escape して渡したい場合だってあるわけで、それをエラーにしちゃマズいです。<br><br>つうことで、「yahoo が莫迦」で納得してしまいました。
おっと、'%3b' は ';' だったのか。(をぃ)<br>てっきり '&' だと思って書いてたですよ。<br><br>ところで、'%3b' はセパレータ機能*ではない*のだから perl CGI mod でそれがセパレータとして機能してしまうというのはいかがなものかと。<br>name「year」は value「2003;category=COMP」である、として扱わなきゃいけないんだよねぇ?
「分解されない」ってのが、セパレータとして機能しないという意味なので、<br>perl CGI.pm も、ruby cgi.rb も間違ってません。<br>ちなみに、; も & もセパレータです。<br>上のスクリプトを、http://www.noroi.jp/cgi-bin/sep.cgi に置いてあるので試してみてください。
なるほど。「分解されない」の意味をよく理解していなかったようなので、perl に問題がないというのは了解です。<br>けど、name「year」が value「2003;category=COMP」の時に name「year」が value「2003」と同じ動作をするという tDiary の動作は何か違っているのではないでしょか?
『value「2003%253Bcategory=COMP」の時に』かな。# unescape されてちゃう?<br>チェックを緩めにしてるのはワザとでしょう。<br>厳密にすることによるメリットって思いつかないし、私でもこうすると思うです。
あれ、されなかった。
デメリットを思いついてしまった。<br><br>Yahoo の crawler は、セミコロンを escape してアクセスしてくるため、<br>Yahoo の検索DB に間違った情報、たとえば最新ページの情報を<br>カテゴリ画面のURIに記録してしまっている。<br>Yahoo の検索結果画面からのアクセスは wrapper が使われており、<br>そいつもセミコロンを escape してしまうため、必ず最新ページへのアクセスになる。<br><br>エラーにしとけば、少しは思い直すかも?
> 『value「2003%253Bcategory=COMP」の時に』かな。<br><br>あたし的には、元記事の URI で、CGI 内部で受け取った value を RFC 通りに unescape したと仮定した時の値の事を書いたつもりだったので、value「2003;category=COMP」で良いかな?と。
> エラーにしとけば、少しは思い直すかも?<br><br>そうねー。<br>それに今のままだと、<br><br> http://www.noroi.jp/?year=A<br><br>でも最新ページに行ってしまうかな?っとね。
とりあえず、search_control.rb という「日付指定ページ以外は記録しないでね」プラグインを入れて逃げてしまいました。<br>エラーを返すためには、もっと ruby を使えるようにならないと…
あぁ、ruby についてはあたしもまったくさっぱりです。