手塩に掛けて (?) 育ててきた BBS CGI スクリプトを紹介します。
この Perl CGI は、KENT-EWB さんのフリーソフト YY-BOARD の Ver.3.4 (2000/08/15) をベースに taitai studio さんが改造した YY Board PLUS (2000/10/06 - もう配布されていない) を、さらに改造したものです。さんざん手を加えてしてしまったので、今さらベースのバージョンを上げるつもりも気力もまったくありません。日本語ライブラリ jcode.pl は、うたしろ かずま さん によるものです。
しかし、<font> タグなどから CSS スタイルへの移行、付属 jcode.pl の最新バージョン採用など、(たぶん)充分に「現代的」なものになっています。
コードのスタイルで原作と違う点は、use strict qw(vars refs) して、PHP のように変数のスコープを厳格にしていること。それに伴って、変数のリファレンス機構も使っています。
ダウンロード前に、必ず Readme ファイル を読んでください。左記 Readme ファイルは下のダウンロードファイルに同梱されているのと同じものです (同梱版のみをアップデートすることもあるかも知れません)。原作に著作権と利用規定がありますので、それを守ってお使いください。 |
デンクス・カウンタ とでも呼んで (読んで?) ください。
DENX-COUNTER は GNU General Public License (八田真行さんによる参考訳はこちら) に則って配布します。
シンプルなアクセスカウンタがほしくて、一から作りました。この Perl CGI は、カウント値を JavaScript の変数定義文として返してきますので、カウンタを設置したいページに、カウント要求とそれを表示する JavaScriptを書いて表示させます。
DENX-COUNTER では 2種類のロック方式が選択できる。 UNIX/Linux (WinNT系にもあるらしい) の備える flock() を利用して datファイル自体をロックする方式と、ロックファイルを使用した方式で、これらは設定ファイル config.pl の $lock_meth によって設定できる。お勧めするのは確実且つ速い flock の方だが、サーバが flock() を封じている場合にはロックファイル方式を使うしかない。
ただし、ロックファイル方式を用いる場合、ひとつ注意がある。 denxcount.cgi は HTTPセッションの一意な ID (PHPのセッションID 相当) をロックファイルに書き込んで、それが確かに現在のプロセスによって作られたロックファイルかどうかを確認して初めて、実際に datファイルに書き込みを行う。この「一意なID」は Apache の mod_unique_id モジュールを通じて発生される。つまり、Apache に mod_unique_id.so (または同等の機能) がロードされていなければ、セッションID を得ることができない。それでも動くことは動くが、ファイルロックの信頼性は薄れてしまう。
mod_unique_id をロードするには、サーバのグローバル設定ファイルが自由になるなら、httpd.conf に下記のような定義を追加すればよい;
LoadModule unique_id_module modules/mod_unique_id.so
自由にならない場合は、少々信頼性が落ちるが、 denxcount.cgi の filelock ファンクション序盤の my $id = $ENV{'UNIQUE_ID'}; を
my $id = $$;
に書き換えて、 CGI のプロセスID で代用していただくしかない。
DENX-COUNT は、出力すべきレスポンスに日本語が含まれる (= config.pl で $use_jp が 0 でない) 場合にだけ、 denxcount.cgi ファイル自体の文字エンコードを判定して、 HTTPヘッダの Content-Type に与える charset 属性を変更する。ファイルの文字コード判定には、かつては Jcode モジュールを使うのが常套手段だったが、 Perl 5.8.0 からは Jcode の機能が Encode モジュールとして Perl に標準搭載されたため、後者の Encode::Guess モジュールを使うことにした。つまり、$use_jp を 1 にした場合には、 denxcount.cgi は Perl 5.8.0 以降でないと動かない。
(ここからはほとんど自分のための覚え書き)
Perlモジュールのロードには use を使うのが通常だが、このように if 節など条件によってロードするかしないかを分岐させるには適していない。というのは、 use は暗黙的に BEGIN{ } ブロックで囲またものとして扱われるので、スクリプトファイルがパースされる一番初期の段階で、全ての use ... が「拾い読み」されるからだ (perldoc の perlmod 参照)。つまり、
if(! $use_jp){ use Encode::Guess qw(euc-jp shiftjis); }
といったコードは意味を成さない。
この目的を達成するには、 use を require と import に機能分解して下記のように書けばよい;
if(! $use_jp){ require Encode::Guess; import Encode::Guess qw(euc-jp shiftjis); }
文字コード判定自体には、スクリプト内にハードコーディングした文字列を guess_encoding() で判定させているのだが、euc-jp, shiftjis, utf8 の 3つとも間違いなく判定するための文字列として、 「あいうえ美乳」 に行き着いた。これは決してふざけているわけでなく、根拠と実験の結果だ。ただ、「美乳にあい収入増」で utf8 の判定に失敗して「あいうえ美乳」でなぜ成功するのかは分からない。やっぱりちょっとふざけているか...
Perl のモジュールインストール手順についての記述があちこちのページに散らばってしまったので、ここでまとめておく。
主に 2通りの方法がある。
例えば Time::HiRes というモジュールが必要な時、下記のようにコマンドしてみる。
user$ perl -MTime::HiRes -e 'print "\n";'
`Cant't locate Time/HiRes ...' とエラー表示が出たら、そのモジュールはインストールされていない。
CPAN シェルを初めて使用する場合は、最初に10個くらいの質問に答えることになる (ほぼ言いなりで良い)。実は、CPAN シェルを使えば、 yum や apt ばりに CPAN サイトからモジュールソースが簡単に取得/インストールできるので、個々にダウンロードするという手間も省ける。CPAN シェルでモジュールの有無を調べるには以下のようにする;
root# perl -MCPAN -e shell cpan> i Time::HiRes
i コマンドはモジュールの情報を見るものだが、INST_FILE の項目が (not installed) になったものは、未インストールだということを表している。 INST_FILE に何らかのバージョンが表示されたら、そのモジュールはインストール済み。
CPANシェルで行う方法、RPMなどディストリビューションのバイナリパッケージでインストールする方法、ソースからインストールする方法の 3つがある。優先順位としては、ディストリビューション標準のパッケージ => CPANシェル => ソースインストール、の順になるだろう。
yum の使えるディストリビューションなら、まず、それらしいパッケージが配布されているかどうか調べてみて、あれば yum でパッケージインストールする。例えば、DBD::Pg がパッケージとして存在するかどうか調べたいとすると;
root# yum list perl-* |grep DBD
また、yum には search という命令があり、それを使うと、引数がパッケージのサマリーやパッケージャ、パッケージ名などにマッチするものをリストアップしてくれる。運が良ければ、お目当てのモジュールの実装する特有のファンクションやメソッドでヒットすることもある;
root# yum search DBD root# yum search gettimeofday Time::HiResはこれでもヒットした
あれば、あとは通常通りに yum install ... するだけだ。
Time::HiRes を例に採ると;
root# perl -MCPAN -e shell まず、モジュールの依存関係を満たすために必要な関連モジュールもインストールするよう CPAN に指示 cpan> o conf prerequisites_policy follow ダウンロード及びインストール cpan> install Time::HiRes 確認 cpan> i Time::HiRes
まずは兎も角 CPAN Search でモジュールを検索して、当該のモジュールページの右上にある `Download: ....tar.gz' リンクからソースアーカイブをダウンロードする。インストールの一般的共通的な流れは以下 (詳しくはそれぞれのソースに付属する README などを参照)。モジュールソースを解凍してソースディレクトリへ cd して、
user$ perl Makefile.PL user$ make user$ make test user$ su root# make install
ちなみに、Perl 以外の外部ライブラリの助けを必要とするモジュールの場合、コンパイルの際に LD_LIBRARY_PATH などの環境変数が参照され、そこに当該のライブラリがないとコンパイルに失敗することがある。例えば、DBD-Pg (DBIモジュール用のPostgreSQLドライバモジュール) をインストールする際に、前記を行おうとする当のターミナル自体で、事前に以下のような事前コマンドを発行しておかなければならなかった経験がある。パスは各自確認していただかなくてはならない;
user$ POSTGRES_HOME=/usr/local/pgsql; \
PG_LIB=/usr/local/pgsql/lib; \
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PG_LIB"; \
export POSTGRES_HOME PG_LIB LD_LIBRARY_PATH
シェルスクリプトでなく Perl スクリプトを使いたくなる時の大きな理由のひとつは、超強力な正規表現があるからだろう。
久しぶりに perldoc を読み直していたら、 Perl正規表現の基本が非常に分かりやすく説明された perlrequick (「Perl正規表現クイックスタート」。あるいは「早わかり」, 「ことはじめ」, 「正規表現入門」といったところか) という素晴らしいドキュメントがあるではないか。これは perlretut - Perl正規表現チュートリアル の抜粋版として書かれたもののようで、必要最低限の事柄がよく整理されていて、入門にはもちろん、基本知識の再確認やブラッシュアップにも最適だ。小難しい拡張機能に手を伸ばすより先に、基本的な事柄をこいつでしっかりと頭に叩き込んでおこう。日本語らしい日本語訳がまだインターネット上に見つからなかったので和訳させていただいた。
「perlrequick - Perl正規表現クイックスタート」 は次のページにある。
DocBook で作ったので、元SGML が必要な方は こちら でどうぞ。