雨谷の日和

過去19年で2,600を超えるアニメの第1話だけは見続けた僕のお勧めアニメがハズレなはずがない

人狼BBS作成日記33

さて、パラメータを切り分けて使う際の注意点とともに、その為の処理を考えてみます。
まず、URL encoding の問題があります。
通常、ホームページのアドレスであるURLには、使える文字についての制限があります。半角英数字しか使えないというような感じの制限だと思って頂ければだいたいあっています。本当は他にもいくつかの記号も使えますし、半角記号の中には使えないものもあります。
例えば半角空白は、URLに含める文字としては不適切だということは容易にご想像頂けるかと思います。
あとは日本語の場合は、全角のひらがなやカタカナ、漢字とかもURLとして使う場合には問題がありそうですよね。
ところがパラメータにはそうしたURLとしては不適切な文字も値として含めたい場合があります。半角空白がパラメータ中で使えないとなると、かなり不便でしょう。
ということで、そういう文字を何らかの規則に基づいて、別の文字列に変換しておこうということが取り決められました。
その、変換のことをURL encodingと言うと思って頂ければだいたいあってます。


要するに、今回はまず、URL encodingされた文字列を、逆変換(decoding)して元の文字列を取り出す処理を考えます。
だいたい、以下のようになります。

$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ge;

一行目は、半角空白をdecodeしています。半角空白は「+」にencodeされていますので、それを元に戻すわけです。
二行目は、日本語の全角文字などをdecodeしています。そういう文字はバイナリの値を文字列で表したような形式にencodeされています。こんな感じですね→「%E3%81%82%E3%81%97%E3%81%8B」。
ですので、その文字列を元にバイナリに変換し直してやるわけです。


さて、これだけではまだこの値を使うには不十分です。
日本語の文字を表現するには、文字コードというものがあります。Shift_JISとかEUCとか、そういう奴ですね。送られてきた文字列が、そのどれなのかは分かりませんが、それをプログラムで扱いやすいものに変換するのが普通です。
文字コードの変換に良く使われているのがjcode.plというプログラムです。これを外部プログラムとして利用してみます。以下のようになります。

require './jcode.pl';
(中略)
&jcode'convert(*value,'euc');

上記は、受け取った文字列をEUCに変換しています。これで、日本語の文字もちゃんと扱えるようになります。


さて、最後に受け取った文字列について、セキュリティや互換性の考慮をすることにします。
入力された文字列には、どんな文字が含まれているか事前には想定し切れません。もしかすると、ユーザはHTMLのタグのようなものを入力してくるかもしれません。プログラムの動作にとって不適切な文字は、事前に排除する必要があります。また、改行のためのコードはユーザのパソコン環境によって異なりますから、それもプログラムで使う前に揃えておくのが良いでしょう。

$value =~ s/\r\n/\n/g;
$value =~ s/\r|\n/\n/g;
$value =~ s/</&lt;/g;
$value =~ s/>/&gt;/g;
$value =~ s/\"/&quot;/g;

上記ではまず、改行コードをLFに揃えています。改行コードは、WindowsならCRLF、UNIXならLF、MacintoshだとCR(OS Xになった今ではどうなんでしょうね)だったりと、異なります。これを揃えておく方が無難でしょう。
その次に、「<」「>」「"」の三つの文字を「&lt;」「&gt;」「&quot;」に変換しています。これは入力頂いた文字を掲示板のメッセージとして表示する際に、不適切なタグとして誤認識されることを防ぐ目的でこのようにしています。
こうしてしまうと、ユーザはHTMLタグを入力できなくなってしまいますが、セキュリティ上はその方が望ましいでしょう。もしも、一部のタグについては入力を許可するというような場合は、出力の前に再度、許可するタグだけを元に変換し直すというような処理を追加すれば良いかと思います。


ということで、長々と書いてしまいましたが、CGIプログラムにパラメータを渡す方法の詳細はこれでおしまいにします。間違ったことを書いているかもしれませんので、鵜呑みにはしないで下さい。
では次は、実際にこういった処理を使って実装を進めてみることにします。