この度目出度く(?)@ホペで自作 CGI が使えるようになりました。うまく使えば、自作の掲示板などがかなり自由に設置できるわけです。
そこで色々なところから Perl スクリプトを借りてきて走らせたりしているわけですが、困ったことに、無料配布されている Perl スクリプトのほとんどは、まともな (validな) HTML を吐き出してはくれません(有料なら valid な HTML を吐くのかと言われると謎ですが)。
そう言うわけで、少しでもまともな HTML を出力するように、Perl スクリプトを改造することになるわけです。
自作の CGI を使うと、かなり自由に HTTP応答ヘッダを出力することが出来ます。これは実に素晴らしい事なのですが、ほとんどのスクリプト作者は HTTP レスポンスヘッダを軽視しています。
なんと言ってもたまげるのは、こんなスクリプトを平気で配布している人がいることです(しかも多い)。
print<<"_EOF_"; Content-Type: text/html <HTML> <META http-equiv="Content-Type" content="text/html; charset=EUC-JP"> <META http-equiv="Pragma" content="no-cache"> ... _EOF_
どうも META http-equiv の意味が分かっていないのではないかと思うのですが、いかがでしょうか。
META http-equiv="Content-Type" の記述は、HTTP応答ヘッダの Content-Type フィールドの代わりになるものです。本当は HTTP応答ヘッダに書きたいところなのに、HTTP応答ヘッダに手をつけることが出来ないので仕方なく META を使っているわけです。
CGI では、わざわざ META http-equiv を使う必要はありません。本物の HTTP 応答ヘッダを出力すれば良いのです。
そんなわけで、上記のスクリプトは書き直します。せっかくですので Content-Language も出力することにして、こんな感じにしてみましょう。
print<<"_EOF_"; Content-Type: text/html; charset=EUC-JP Content-Language: ja Pragma: no-cache Cache-Control: no-cache <HTML lang="ja"> ...
META を出力する必要は全くありません。なお、Pragma: no-cache は Cache-Control: no-cache に取って代わられていますが、HTTP/1.0 との互換のために Pragma フィールドも残してあります。
なお、Content-Style-Type や Keywords なども HTTP 応答ヘッダに含めて構わないはずなのですが、何となく読んでくれないユーザーエージェントが多そうな気がするので、META で文書インスタンスの中に書いておくことにしています。何となくですが。
HTML4 では、CGI の作者に対し、パラメータの区切りに ; を使えるようにすることを推奨しています。詳しくは HTML4.01 B.2.2 を見てください。
となれば当然、我々はこの期待に応えたくなるわけです。応えようではありませんか。
パラメータを処理するルーチンは、多くの場合、以下のようになっています。もちろん変数名は違っていることもありますし、宣言されていないこともあるでしょうが……。
my($pair,$buffer); if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } my(@pairs) = split(/&/,$buffer); #ここでパラメータを分割している。 foreach $pair (@pairs) { my($name,$value) = split(/=/,$pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $FORM{$name} = &change_code($value); }
これを次のように改造します。
my($pair,$buffer); if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } my(@pairs) = split(/[&;]/,$buffer); #区切りに ; を追加。 foreach $pair (@pairs) { my($name,$value) = split(/=/,$pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $FORM{$name} = &change_code($value); }
/&/
を /[&;]/
とするわけです。これだけで区切りに ; が使えるようになります。
フォームデータの中に ; が含まれているとまずいのではないか、と思うかも知れませんが、心配は無用です。; は危険な文字ですので、application/x-www-form-urlencoded によってエンコードされて送られてくるはずです。
なお、POST メソッドのみで処理する場合はこの改造は必要ありません。
その他、一般配布されているスクリプトの吐き出す HTML には好ましくないものが多いようです。TABLE や BLOCKQUOTE を濫用していたり、ご丁寧にも FONT size="?" の吐き出す数字を調整できるようになっていたりするのです(文字サイズを調整したいなら、ブラウザの文字サイズの設定を変えましょう。サーバーに負荷をかけることもなく、数秒で出来ます)。
しかしまあ、その辺りはとにかく頑張って改造するしかありません。正しい HTML を吐き出す CGI を目指して頑張りましょう。