Perlスクリプトを改造しよう!

Perlスクリプトの改造

この度目出度く(?)@ホペで自作 CGI が使えるようになりました。うまく使えば、自作の掲示板などがかなり自由に設置できるわけです。

そこで色々なところから Perl スクリプトを借りてきて走らせたりしているわけですが、困ったことに、無料配布されている Perl スクリプトのほとんどは、まともな (validな) HTML を吐き出してはくれません(有料なら valid な HTML を吐くのかと言われると謎ですが)

そう言うわけで、少しでもまともな HTML を出力するように、Perl スクリプトを改造することになるわけです。

http-equiv ではなく、ホンモノを使え!

自作の 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 を目指して頑張りましょう。


HTMLむだ話

HTML鳩丸倶楽部

水無月ばけら, MINAZUKI Bakera
E-mail: bakera@star.email.ne.jp