フォームデコードなどの機能を持つ、CGI作成者のためのPerlモジュール。
CGIモジュールが肥大化し、動作が重くなっていったのを受け、フォームデコードなど一部の機能を切り出した、軽量なモジュールとしてPerlモジュール/CGI_Liteが作成されました。 これの名称を変更したものが、CGI::Liteモジュールです。
CGI_Liteはモジュールです。 このため、Perl4では使用できません。
かわりに、Perl4で使用では「cgi-lib.pl」ライブラリを使うことになります。 このライブラリは、「The cgi-lib.pl Homepage」から入手できます。
CGI_Liteは「アスキー」モードでファイルを作成するので、画像などバイナリファイルを受け取ると壊れることがあります。
binmodeコマンドで入出力をバイナリモードで行うように指示してやると、これを避けられるようです。 実際の改修は、下記の数行で済みます。
# "_parse_multipart_data" サブルーチン 985~987行
$directory = $self->{multipart_dir} || $self->{default_dir};
binmode STDIN; # この行を挿入する
while (1) {
# "_parse_multipart_data" サブルーチン 1076~1077行
open (++$handle, ">$full_path")
|| $self->_error ("Can't create file: $full_path!");
binmode $handle; # この行を挿入する
# "_create_handles" サブルーチン 1168行
binmode $handle; # この行を挿入する;
push (@{ $self->{all_handles} }, $handle);
なお、行番号はCGI_Lite v2.02に対応しています。 binmodeについては、perldocやPerl関数:binmodeなどで調べて下さい。
■ parse_form_dataを行ってもファイルが作成されない
次のようなケースが一般的です。
CGI_Liteを使った極めて簡単な例です。
#!/usr/local/bin/perl
use CGI::Lite;
# ファイル保存ディレクトリ関連
my $dir = './file';
unless (-d $dir) {
mkdir $dir, 0777 or die $!;
}
# フォームデコード
my $cgi=new CGI::Lite;
$cgi->add_timestamp(0);
$cgi->set_directory($dir) or die $!;
$cgi->set_platform ('Unix');
my %formdata = $cgi->parse_form_data();
# 結果データ$result生成
my $result = '';
if (%formdata) {
$result = "<hr>\n<table cellspacing=0 cellpadding=5 border=1>\n";
foreach (sort(keys(%formdata))) {
$result .= "<tr><td>$_</td><td>$formdata{$_}</td></tr>\n";
}
$result .= "</table>\n";
}
# ファイルリスト$list生成
my $list = '';
my $size = 0;
foreach my $path (sort(glob($dir.'/*'))) {
next unless (-f $path);
my $file = $& if ($path =~ /[^\/]+$/);
$list .= "\t<dd><b><a href='$path'>$file</a></b> (".sprintf("%dKBytes", ((stat($path))[7] + 1023) / 1024).")</dd>\n";
$size += (stat($path))[7];
}
$list = "<dl>\n\t<dt><B>ファイルリスト</B> (Total : ".sprintf("%dKBytes", ($size + 1023) / 1024).")\n".$list."</dl>\n";
# 出力
print <<EOD;
Content-type: text/html
<html>
<head><title>ファイルアップロード</title></head>
<body><h1>ファイルアップロード</h1>
<!-- リスト -->
<hr>$list<hr>
<!-- アップロードフォーム -->
<form action="Filer.cgi" ENCTYPE="multipart/form-data" method="post">
File : <input type="file" name="file"> <input type="submit">
</form>
<!-- 結果 -->
$result
<hr><center><a href="http://digit.que.ne.jp">©Walrus, Digit</a></center>
</body>
</html>
EOD
実際に設置する場合には、最低限下記を行ってサーバーの安全性を確保する必要があります。
ほとんどはファイル名に関するものです。 ファイル名は、下のようにあらかじめ変換ルーチンを指定すると、パース時に自動的にサブルーチンでの変換が行われます。
$cgi->filter_filename(sub {サブルーチン});
my %form = $cgi->parse_form_data();
まず、日本語のファイル名については、文字コードに注意する必要があります。 MachintoshやWindowsでは、ファイル名はSJISにした方が良いでしょう。 これを行わないと、OS側ではうまくファイル名を処理できなくなる可能性があります。
この他、半角カナ、機種依存文字(丸の中に1、や罫線その他)なども排除した方が良いです。 こうした文字は、Webで表示、ダウンロードする際にトラブルの原因になりがちです。 また、OSごとに禁則文字が違い、ポピュラーなところではMachintoshではファイル名に使える文字で、Windowsでは使えないものがあります。 これらも排除した方が良いでしょう。
また、.cgi、.pl、.exeなどは、アップロードしたファイルが設定次第ではCGIだと認識され、サーバー上で実行されてしまう可能性があります。 こうした拡張子は拒否するか、拡張子を削除してしまう方が良いでしょう。
ファイル名の他に、ほとんどのケースではファイルサイズを考える必要があるでしょう。 ファイルサイズについては、$ENV{CONTENT_LENGTH}を見て、おおよそのサイズで受信の可否を決めてしまうのが最も簡単です。
my $maxbytes = 51 * 1024; # 約50KBytesまで
if ($ENV{CONTENT_LENGTH} < $maxbytes) {
エラー処理
exit;
}
my %form = $cgi->parse_form_data();
実際には、フィールド名やその他のフォームデータを含めて所定サイズ以下、となるので許されるファイルサイズは指定値より僅かに少なくなります。 このため、上のスクリプトでは1KBytesの遊びを持たせていますが、ほとんどの場合無視できる程度でしょう。
「Perl for Newbie (Perl初心者の部屋)」に「CGI_Lite1.62について」というページがあります。
http://www.harukaze.net/~mishima/perl/index.html
ただし、同サイトでも書かれているようにCGI_Liteの最新版は1.9ですし、さらにCGI::Liteは2.0版です。 これらを使う際には、上のサイトで概要をつかんだ上で、詳細はやはり英語版をあたられるべきかと思います。
その数字はtimestampで、「$cgi->add_timestamp(n);」というメソッドで付け方を調整できます。nを0にするとつけない、1にするとつける、2にすると同名のファイルはタイムスタンプをファイル名にする、です。
CGI_Liteのドキュメントを確認して下さい。
Version1.9まではCGI_Liteというモジュール(ファイル名はCGI_Lite.pm)でしたが、2.0からはCGI::Lite(ファイルはCGI/Lite.pm)になりました。 どちらもCPANから入手できます。
Version1.9と、CGI::Lite v2.0はほとんど同じものです。 詳細やCGI_Liteからの移行方法はCGI::Liteをご覧下さい。
Internet ExplorerがエンコードされたURLを元にファイル名を作成しようとして、文字化けになるようです。 Internet ExplorerにエンコードしていないURLをリクエストさせるのが回避策になります。 ただし、エンコードされていないURLでのリクエストは、処理できなくて当然です。この回避策の使用は推奨しません。
このためには、CGIから出力するURLを次のようにします。
Windows上で動作しているAnHTTPdサーバと、同じくWindows上で動作しているInternet Explorer 5.5で上の回避策が動作することを確認しました。 この際、HTMLおよびURL中の日本語文字コードにはEUCを使用しました。 なお、前述の通り動作しなくて当然の方法ですので、他の環境で使う時は、その環境でつかわれるサーバと全てのクライアントに対して、問題がないか試験をして下さい。
CGI::LiteモジュールはCGI_Liteモジュールの後継になります。 CGI::Lite v2.0とCGI_Lite v1.9の違いは(ソースレベルで見ても)以下の3点だけです。
CGI_Lite]]に関する情報は、99%までそのままCGI::Liteにも適用できます。 なお、CGI::Lite 2.02版からは少しずつ修正が加わり始めています。
CGI_Liteを使用しているスクリプトを、CGI::Liteを使用するように変更するのは簡単です。 次のようにして下さい。
CGI_LiteからCGI::Liteへの切り替えは、通常、スクリプト中のCGI_Liteの文字列をCGI::Liteに全置換するだけで問題ありません。
なお、CGI_LiteによるファイルアップロードのサンプルとしてWalRackというCGIを公開しています。 これを、CGI::Liteに移行したものを、WalRack2として公開します。 両者のファイル構成と、WalRack.cgiスクリプトの記述を比較してみてください。
(こちらへお書きください)
コメントスパムがひどいためこのページのコメント欄を削除しました。コメントしたい方は暫定的に「掲示板」のページへお願いいたします。