本文書において問題とされている誤りは2005年6月8日の更新時に修正されている。よって、本文書の対象者は、6月5日から8日の間に問題文書に基づいてclap.cgiの改造を行った読者である。
6月5日に公開されたweb拍手改造文書「一言メッセージの書き込み時刻を記録する 簡単編」に、誤りが発見された。「時分秒を記録する」の項に掲載された改造コードのサンプルが間違っていた。
#---------------------------------------一言メッセージ処理
if ($hitokoto ne ''){
$mesdata = "$getdate<>$tohour:$min:$sec<>$hitokoto<>\n";
#---------------------------------------一言メッセージ処理
if ($hitokoto ne ''){
$mesdata = "$getdate:$min:$sec<>$tohour<>$hitokoto<>\n";
本来なら、変数$tohourの続きに書かれなければならない:$min:$secが、$getdateの続きに書かれてしまっていた。
この誤りにより発生する問題は次のとおりである。
kaiseki.cgiが一言メッセージログファイルに記録された一言メッセージデータを見つけられなくなるために、kaiseki.cgiは今日送られたメッセージに一言メッセージを表示できない。対象日の一言メッセージの絞り込みに、年月日をつなげた数値($getdateの内容)を用いているためである。
例をもって説明しよう。例えば、2005年6月5日12時15分30秒に書き込まれた一言メッセージは、次のように記録される。
20050605<>12<>一言メッセージ<>(改行)
6月5日の改造では、20050605<>12:15:30<>一言メッセージ<>(改行)と記録するように変更するつもりであったのだが、誤って20050605:15:30<>12<>一言メッセージ<>(改行)と記録するコードを書いてしまった。
kaiseki.cgiは、2005年6月5日に送信されたメッセージを絞り込むのに、行の最初に現れる値が20050605という文字列に完全一致する行だけを取り出すというやり方を用いているため、20050605:15:30<>12<>一言メッセージ<>(改行)となっている行のデータは、対象外と見なされてしまう。
この問題への対処法は、20050605:15:30<>12<>一言メッセージ<>(改行)の最初の値、20050605:15:30を正しく20050605に変更するということである。ただ、これは私のサイトのような弱小サイトならいざ知らず、多くのメッセージを受け取る大手サイトならば大変な手間であり、それに、この変更作業を行っている間に、新たなメッセージを受け取ってしまうという可能性もある。
なので、今回発生した問題に対処するためのプログラムを作成した。使用言語は、web拍手と同様Perlである。サーバ上の一言メッセージログファイルを処理できるよう、clapinit.cgiで設定されたログファイル名を使うようにしてある。
注意点は、以下のとおり。
#!/usr/bin/perl
をサーバの環境に合わせて書き換える(clap.cgiの一行目と同じにすればよい)require './clapinit.cgi';
を書き換える(clap.cgiでの設定値にあわせてやるとよい)$backupfile = "backup.txt";
で、一言メッセージファイルをバックアップする際に使用するファイル名を設定している。もし、web拍手の置かれたディレクトリにbackup.txtという名前のファイルがあるとそのファイルは上書きされてしまう。その場合は、他のファイルが使っていない別の名前に変更するこのプログラムはwebブラウザから実行する。aftercare.cgiをブラウザで開くことで、プログラムは実行される。
このプログラムが行うことは次のとおり。
backup.txt
)backup.txt
は作成される)backup.txtは、必要に応じ確保、削除していただきたい。ログファイルの修正後は、aftercare.cgiを削除してくださってかまいません(むしろ、削除しておくべきであると考えます)。
修正プログラムはzipにて圧縮されています。適切なツールで伸張後、ご利用願います。
また、同梱の文書「readme.txt」も合わせてお読みくださいますようお願いいたします。
#!/usr/bin/perl
# 外部ファイルを読み込みます。
# clapinit.cgiのファイル名を変更している場合は、
# 変更したファイル名にあわせて書き換えてください。
require './clapinit.cgi';
# バックアップファイル名
# もしファイル名称が他のdatファイルとかぶっているようでしたら、
# 以下のファイル名を変更してください。
$backupfile = "backup.txt";
# 処理の開始
# ファイルのロック
&lockon;
# 修正行数カウント用変数を初期化
$linecount = 0;
# 一言メッセージログファイルを読み込む
open(IN,"$mesfile");
@mesdata = <IN>;
close(IN);
# バックアップファイルを作成
open(OUTBK,">$backupfile");
print OUTBK @mesdata;
close(OUTBK);
# 修正作業完了メッセージ
$title = "修正作業の完了";
&header;
print "<body>\n<h1>修正作業が完了しました</h1>\n";
print "<ol>\n";
# 修正処理実行部分
# ログの行数を変数$jにセット
$j = $#mesdata;
# ログファイルを全行チェック
for ( $i=0 ; $i<=$j ; $i++ ){
# ログデータを区切り文字(<>)で分割
($logdate,$loghour,$logmes) = split(/<>/,$mesdata[$i]);
# 年月日に分秒が混じっていないかで分岐
# 時分秒の区切りに用いたコロン(:)の有無で判断している
if ($logdate =~/\d+:.+/){
# 修正行数にプラス1
$linecount++;
# 修正対象行を表示
print "<li>$logdate ($logmes)</li>\n";
# コロンの混じったデータをコロンで分割
($logdate,$logmin,$logsec) = split(/:/,$logdate);
# 新ログファイル用配列に修正データを追加
push (@newlogdata, "$logdate<>$loghour:$logmin:$logsec<>$logmes<>\n");
} else {
# ログデータが正しい場合は、
# そのまま新ログファイル用配列にデータを追加
push (@newlogdata, $mesdata[$i]);
}
}
# 修正対象行が0でない場合のみログファイルを書き換える
if ($linecount != 0){
open(OUT,">$mesfile");
print OUT @newlogdata;
close(OUT);
}
# ファイルのロックの終了
&lockoff;
# 修正作業完了メッセージの続き
print "</ol>\n";
if ($linecount == 0){
print "<p>修正対象のデータはありません。</p>\n";
print "<h2>$mesfileの内容</h2>\n";
} else {
print "<p>以上のデータに対する修正作業を完了しました。</p>\n";
print "<h2>修正後の$mesfileの内容</h2>\n";
}
# 修正済みログデータの表示
print "<pre>\n";
foreach (@newlogdata){
print "$_";
}
print "</pre>\n";
# お詫び文
print "<p>多大なご迷惑をおかけしましたことお詫び申\し上げます。以後このようなことのないよう、入念なチェックをおこなっていく所存です。</p>\n";
print "<p>今後ともかわらぬこととねへのごひいき、なにとぞよろしくお願いいたします。</p>\n";
print "<p>(修正前のログファイルが$backupfileとして作成されています。必要に応じて、確保、削除してください。)</p>\n";
print "<body>\n</html>\n";
exit;
< web拍手改造:一言メッセージの書き込み時刻を記録する 困難編 web拍手改造文書に誤りを発生させた背景について>