web拍手改造

さまざまな情報を取得する

 web拍手は基本的に誰が拍手をくれたか、わからないようになっている。どこの誰が、どんなブラウザで、またどのページに用意されたボタンから送ってくれたのか、こうしたことは一切記録されないから、送るほうとしては気楽だし、受けるほうにしてもその気楽さを壊したくはないと思っている。けれど、ときにはもう少し情報が欲しいと思うこともある。例えば私は、拍手をくれた人がどのページ経由で拍手を送ってくれたのか、ずっと知りたいと思っていた。私はこのサイトの他にBlogも持っていて、その両方で同じCGIを共用しているから、どちらの読者さんが拍手をくださってるのかわからないということが少し歯がゆかった。

 しかし、こうした情報を得ることはできるのだろうか? できるのである。それには、環境変数というものを知る必要がある。

環境変数とは?

 環境変数について詳しくお知りになりたい場合は、cgi 環境変数あたりをキーワードにして調べてくださると早いと思うが、えっと、どうも私にはうまく説明できないな。サーバやCGI、そしてアクセスしてきたクライアントの情報をCGIプログラムが知るための方法があるのだよ。それがCGI環境変数。今回利用するのは、特にクライアントに関する情報だ。CGI環境変数でもって、クライアントの利用しているIPやリモートホスト名、あるいはブラウザ種別、どのページからきたか(リファラ)を知ろうというわけだ。

 Perlを用いたCGIの場合、環境変数は%ENVという連想配列(ハッシュ)に格納されている。これにキーとなる文字列(添え字)を与えて、値を取り出すわけだ。例えば、こんな風にする。

リモートホスト名
$ENV{'REMOTE_HOST'}
リモートホストのIPアドレス
$ENV{'REMOTE_ADDR'}
ブラウザ名称
$ENV{'HTTP_USER_AGENT'}
リファラ
$ENV{'HTTP_REFERER'}

 CGI環境変数で得られる情報は他にもたくさんあるのだが、とりあえず今回の改造では以上の四つもあれば充分だろう。他にどんな情報が得られるか知りたいという方は、「環境変数」 Perl講座を参照されるとよいと思う。

得られた情報をどこに記録するべきか

 情報を取得できるということはわかった。では、これをどこに記録したらよいだろう。もちろんログファイルに記録するわけだが、できればあまりログには手を加えたくない。改造範囲が広くなるからだ。となると、これら情報は一言メッセージとして記録すればよいのではないか。もちろん、すべてのメッセージにこれら情報を加えるといっているわけではない。ほら、web拍手には特徴がある。一般的にweb拍手の一番最初の拍手は、メッセージなしでやってくる。これは、ページには拍手ボタンだけが置かれていることが多いという、そういう事情のためだ。そう、一度目の拍手でかつメッセージがない場合、知りたい情報をメッセージとして記録してしまえばいいのだよ。

 上でメッセージがない場合って書いたのは、なんらかのやり方でメッセージを第一回目から送る人がいないとも限らんからね(そしてそれは可能だ)。せっかくメッセージがあるのに、そいつを上書きしてしまったりしたら申し訳なくて仕方がない。だから、メッセージがない場合っていう条件が必要なわけだ。

条件判定はどのようにするか

 ポリシーが決まったところで、では具体的にどう書いたらいいか考えよう。今回の条件は、拍手が一度目でかつメッセージがない場合だった。この条件を調べるには、過去の改造が参考になる。

 拍手の回数については、web拍手改造:連投規制を緩和するを参考にするとしよう。そう、拍手の回数が記録される変数、$kaisuuを参照するというわけだ。

 $kaisuuは一度目の拍手では送られてこない。というのは、readme.txtに例示されているフォームを見てもらえばわかるのだが、ここには回数を通知するための要素が記載されていないからだ。

<form action=『clap.cgiのパス』 method=post target=_blank>
<input type=submit value=web拍手ボタン>
</form>

 案内のとおりにweb拍手を設置しているなら、一度目の拍手では回数が送られない。つまり、$kaisuuは未定義であるというわけだ。

 ここでPerlというプログラム言語の柔軟さが役に立つ。Perlでは未定義値は常に偽と判定されるのだ。例えばifで条件判定しようという場合、未定義の値がやってくると、さらに加えていうならば0や長さ0の文字列がやってくると、それらはすべて偽と判断される。ただ、今回の場合は$kaisuuが未定義つまり偽である場合に真としたいわけで、じゃあこういうときにはどうしたらいいんだろう。もちろんやり方がある。Perlでは、!を使うことで真偽を逆転させられるのだ。ifの真偽判定をする際に、変数$kaisuuの前に!を付けてやると、未定義がきたら真となる。

 じゃあ、一言メッセージの場合も同じようにしてやればいいのかというと、今度はちょっと事情が違う。一言メッセージについては、web拍手改造:一言メッセージコールバック機能をつけるを参照しよう。一言メッセージは$hitokotoという変数に入っているといっていた。つまり、これが空である場合に真としてやればよいとわかる。

 さっき少しいっていた。Perlにおいては長さ0の文字列、つまり空のメッセージは偽として判定される。ということは、さっき$kaisuuでやったように!を使って真偽を反転すればいいのかといえば、今回は少し違うのだ。というのは、Perlでは0も偽とされるという事情に関係する。つまり、0一文字のメッセージが送られてきた場合が問題になるのだ。って、そんなの気にしなくていいような気もするんだが、でも、まあ、どんなに短くてもメッセージだから。この変はきちんとやったほうがいいだろうしさ。

 以上、判定の基準は決まった。$kaisuuが偽で$hitokotoが長さ0の文字列の場合に環境変数を記録するわけだ。これをPerlで書けば次のようになる。

if (!($kaisuu) and $hitokoto eq '') { }

 では、これから実際の改造に取り掛かろう。

CGIを改造する

 今回改造するのは、clap.cgiだ。さっき決めた判定条件に基づき、一言メッセージに環境変数を記録するのが目的だ。私は、リファラを記録することにした。そのため、以下にはリファラを記録する場合の例が示される。改造をされる場合には、自分にとって必要な情報を、適宜選択して書き換えていただきたい。

 変更箇所は、clap.cgiの115行目、一言メッセージの直前だ。一言メッセージをログに記録する直前で、必要な情報を一言メッセージに押し込めるのだ。ただ、ここでご注意いただきたいのは、一言メッセージにコールバック機能をつけている場合だ。この改造がなされていると、単純に$hitokotoに環境変数を押し込めてしまうとまずいことになる。環境変数が、拍手をくれた方にコールバックされてしまうからだ。なので、$hitokotoの内容をログに記録する専用の変数に移してやることにする。私はその変数の名前を$hitokoto_logとした。

改造例

オリジナル
#---------ログ上書き保存
open(OUT,">$logfile");
print OUT @logdata;
close(OUT);

#---------------------------------------一言メッセージ処理
if ($hitokoto ne ''){

$mesdata = "$getdate<>$tohour<>$hitokoto<>\n";

open(OUT,">>$mesfile");
print OUT $mesdata;
close(OUT);
}
改造後
#---------ログ上書き保存
open(OUT,">$logfile");
print OUT @logdata;
close(OUT);

#----------はじめてのポスト時、リファラの取得
my $hitokoto_log = $hitokoto;
if (!($kaisuu) and $hitokoto eq '') {
    $hitokoto_log = $ENV{'HTTP_REFERER'};
}

#---------------------------------------一言メッセージ処理
if ($hitokoto_log ne ''){

$mesdata = "$getdate<>$tohour<>$hitokoto_log<>\n";

open(OUT,">>$mesfile");
print OUT $mesdata;
close(OUT);
}

 変更及び追加された箇所は強調されている。ここで特に注意していただきたいのは、一言メッセージの記録されるところ、二ヶ所ほど$hitokoto$hitokoto_logに書き換えられている。この変更を忘れると、環境変数の記録はまったくされなくなる。例えばifの判定の修正を忘れると、なんせもともとの$hitokotoは空なんだから記録処理そのものがおこなわれないし、その次の記録部分の変更を忘れると、空の$hitokotoが、つまりは拍手の寄せられた時刻だけが記載されて、メッセージは空で記録されることになる。

 この二ヶ所の変更は特に忘れやすく、はまりやすいところであると思うので、改造される場合には是非気をつけていただきたい。というか、私が改造時に忘れたのだ。なんかうまく記録されないので変だと思ったら、ifの判定条件を修正するの忘れていたという落ち。皆様においては、私の二の轍を踏まれないよう、お気をつけいただきたい。

改造アドバンス

 今回やったような、一言メッセージに環境変数を記録するというやり方がいやだという場合には、ログに記録する項目数を増やす必要がある。これをすると、記録された情報を表示させるため、kaiseki.cgiの改造が必要になる。また、一言メッセージが送られない場合には拍手の回数しか記録されないため、こうした情報は残らない。ログに記録する条件を変更するか、あるいはこれら情報のみを記録するログを新たに用意するか、いずれにせよ改造は大変そうだ。

 メッセージログの項目数を増やす場合には、web拍手改造:一言メッセージの書き込み時刻を記録する 困難編が参考になるかと思う。新たにログを用意する場合には……、参考になる情報は書いてないなあ。ちょっと大変そうだからあんまり手を出したくないので、よっぽどの要望のないかぎりはこれからも書かれることはないと思う。


<   >

わたしの愛した機械へ トップページに戻る

公開日:2007.07.14
最終更新日:2007.07.14
webmaster@kototone.jp
Creative Commons License
こととねは、クリエイティブ・コモンズ・ライセンス(表示 - 継承 2.1 日本)の下でライセンスされています。