web拍手改造文書における誤りとその修正

本文書の対象

 本文書において問題とされている誤りは2005年6月8日の更新時に修正されている。よって、本文書の対象者は、6月5日から8日の間に問題文書に基づいてclap.cgiの改造を行った読者である。

6月5日に発生した問題

 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で設定されたログファイル名を使うようにしてある。

ログ修正プログラムについて

 注意点は、以下のとおり。

  1. このプログラムは、web拍手CGIの設置されているディレクトリにアップロードして、webブラウザから実行されることを想定している
  2. このプログラムを実行する前にclap.cgiの誤りを修正する
  3. プログラム一行目の#!/usr/bin/perlをサーバの環境に合わせて書き換える(clap.cgiの一行目と同じにすればよい)
  4. ファイルのロックとHTMLの表示にclapinit.cgi内のサブルーチンを用いているためclapinit.cgiが必要
  5. clapinit.cgiの名前を変更している場合は、7行目require './clapinit.cgi';を書き換える(clap.cgiでの設定値にあわせてやるとよい)
  6. 12行目の$backupfile = "backup.txt";で、一言メッセージファイルをバックアップする際に使用するファイル名を設定している。もし、web拍手の置かれたディレクトリにbackup.txtという名前のファイルがあるとそのファイルは上書きされてしまう。その場合は、他のファイルが使っていない別の名前に変更する
  7. プログラムをアップロード後、パーミッションを[755]に変更する
  8. このプログラムは、名前を変更しても動作する

 このプログラムはwebブラウザから実行する。aftercare.cgiをブラウザで開くことで、プログラムは実行される。

 このプログラムが行うことは次のとおり。

  1. 一言メッセージログファイルのバックアップを作成する(初期設定ではbackup.txt
  2. 一言メッセージログファイルを検査する
  3. 不正なデータが見つかった場合は誤りを修正し、正しいログファイルを作成する
  4. ログファイルに問題がない場合はなにもしないで終了する(ただしbackup.txtは作成される)

 backup.txtは、必要に応じ確保、削除していただきたい。ログファイルの修正後は、aftercare.cgiを削除してくださってかまいません(むしろ、削除しておくべきであると考えます)。

修正プログラムのダウンロード

 修正プログラムはzipにて圧縮されています。適切なツールで伸張後、ご利用願います。

 また、同梱の文書「readme.txt」も合わせてお読みくださいますようお願いいたします。

aftercare.cgiのコード

#!/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;

<  >

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

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