環境変数表示用のコードです。CGIの動作チェックなんかに便利かもしれません。
#!/usr/bin/perl
print <<"EOF";
Content-Type: text/html
<html>
<head>
<title>Environment Variables</title>
<style type="text/css">
h1 {
text-align: center;
}
table {
border-collapse: collapse;
margin: 0 auto;
padding: 0;
}
th {
font: bold 10pt sans-serif;
text-align: left;
color: #fff;
background: #666;
margin: 0;
padding: 5px 1em;
}
td {
font: normal 10pt sans-serif;
border-bottom: 1px dotted #666;
margin: 0;
padding: 5px 1em;
}
</style>
</head>
<body>
<h1>Environment Variables</h1>
<table>
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
EOF
foreach $key (sort keys %ENV) {
chomp($value = $ENV{$key});
$value =~ s/<[\/]*[a-zA-Z0-9]+>//g;
print <<"EOF";
<tr>
<td>$key</td>
<td>$value</td>
</tr>
EOF
}
print <<"EOF";
</tbody>
</table>
</body>
</html>
EOF
Perlにモジュールを追加するには、CPAN(Comprehensive Perl Archive Network)を使うと簡単で、管理しやすくなります。
> perl -MCPAN -e shell
初回起動時は初期設定が必要になりますが、ほとんどデフォルトのままリターンすれば大丈夫です。ミラーサーバは、日本のサーバを選びましょう。
モジュールの情報を見るには、iコマンドを使います。
cpan[0]> i DBD::mysql Strange distribution name [DBD::mysql] Bundle Bundle::DBD::mysql (CAPTTOFU/DBD-mysql-4.004.tar.gz) Module = DBD::mysql (CAPTTOFU/DBD-mysql-4.004.tar.gz) 2 items found
このモジュールをインストールしたければ、installコマンドを使います。
cpan[0]> install DBD::mysql
UTF-8でエンコードされたPerlスクリプトで、length()関数を使って文字数をカウントしようとすると、日本語1文字が3バイトなので、うまくカウントするのが大変です。そこでEncode.pmを使って文字列をデコードすると、簡単に文字数をカウントできます。
use Encode;
$str = "こんにちはHello";
$count = length($str);
print "「$str」は$countバイトです。\n";
$count = length(decode('utf-8', $str));
print "「$str」は$count文字です。\n";
このスクリプトの出力は次のようになります。
「こんにちはHello」は20バイトです。 「こんにちはHello」は10文字です。
改行コードはWindowsではCR+LF、Mac OS 9ではCR、Unix系OSではLFですが、Perlで\nと\rを組み合わせてそれぞれの改行コードにマッチさせようとするのは根本的に間違っています。
そこで、ASCIIコード(CRは\x0D、LFは\x0A)で置換します。詳細については大崎博基氏のWebサイトの「改行コードを統一する」がとても参考になりました。
$str =~ s/\x0D\x0A/<br \/>/g; $str =~ s/\x0D/<br \/>/g; $str =~ s/\x0A/<br \/>/g;
当サイトに設置しているBBSのプログラムをせっかくなので公開しておきます。400行ほどのPerlスクリプトですが、独自フォーマットのデータベースを作るよりもMySQLと連携させる方がずいぶん楽だと思いました。
BBSで大事なのはタグのエスケープで、セキュリティ対策としてきわめて重要な処理です。具体的には、小なり記号「<」と大なり記号「>」をそれぞれ実体参照の「<」と「>」に置換して、タグとして解釈されないようにします。また、ダブルクォート「"」とアンパサンド「&」も、ブラウザが特殊な値として解析しないように「"」と「&」に置換します。
エスケープする順番は、最初にアンパサンドをエスケープしてから、ほかの記号をエスケープします。
$text='<a href="http://example.net">foo</a>'
&escape_tag(\$text);
print "$text\n";
# &、<、>、"を実体参照に置換
sub escape_tag {
my $var = $_[0]; # reference
${$var} =~ s/&/&/g;
${$var} =~ s/</</g;
${$var} =~ s/>/>/g;
${$var} =~ s/"/"/g;
}
このコードの実行すると、$textのタグがエスケープされて次のようになります。
<a href="http://example.net">foo</a>
データベースには余計なデータを保存しないのが理想なので、エスケープ前のテキストを保存します。つまり、ブラウザに表示するときと、画面遷移時に値を持ち越すときだけタグをエスケープするようにします。これが案外ややこしい処理になりますが、手を抜かないようにしましょう。
データベースに値を登録するとき、バックスラッシュ(円記号)「\」をエスケープする必要があります。バックスラッシュのエスケープは、二重にエスケープすることになるので注意が必要です。「\」を登録するにはPerlで「\\\\」に置換して、そうすると実際は「\\」になっているので、データベースには「\」が登録されるという計算です。
# バックスラッシュをエスケープ
sub escape_backslash {
my $var = $_[0]; # reference
${$var} =~ s/\\/\\\\/g;
}
PerlからMySQLを使うにはDBIモジュールとDBD::mysqlモジュールが必要なので、CPANから最新版を入手します。