□Perl 講座 特別編 > 記事削除

◆目印とパスワード

記事を削除すると言う事は、どう言うことでしょうか?削除したい記事を抜いた物を上書きすれば良いと言うことです。そこで、削除したい記事を特定する為の目印が必要になってきます。また、誰でも記事削除可能と言うのも困るわけで、管理者パスワードを設定してあげましょう!記事削除するサブルーチン名を『delete』として考えていきます。

>記事削除>第一段階

まず最初に変更しなくてはならないことは、目印と削除キーを入力する欄を作ってあげなくてはなりません。また、目印を何にするか?ですが・・・。記事番号を付けてその番号を目印にする方法もあるのですが、面倒くさいのでここでは、それぞれの記事に削除キー欄と削除ボタンとつけてあげる方法を取ります。そこで、まず各記事につけるわけですから、記事出力ルーチン(リピート部分)を改造しなければなりません。

#リピート部分プログラム
sub output {
    print <<"EOT";
<FORM action="bbs.cgi" method="POST">
<INPUT type="hidden" name="mode" value="delete">

投稿者:$name <INPUT type="text" name="pwd" size="10">
<INPUT type="submit" value="削除">
<BR>
E-mail:<A href="mailto:$email">$email</A><BR>
Homepage:<A href="$url" target="_blank">$url</A><BR>
投稿内容<BR>
$msr
<HR>
</FORM>
EOT
}

削除プログラム(サブルーチン)名をdeleteとしてますので、隠しパラメータmodeにdeleteの値を入れておきます。そして、メインルーチンに以下の条件を挿入します。

#メインルーチン
&decode;
if ($FORM{'mode'} eq 'write') { &write; }
if ($FORM{'mode'} eq 'delete') { &delete; }
&html;

modeの値がdeleteだったら、サブルーチンdeleteを呼び出しなさいと言う意味です。

>記事削除>第二段階

次に目印をつける作業はどうやってつけるかですが、今回はログ記事が最新記事から何番目か?と言うことを目印にします。勿論他のやり方でも構いません。何番目の記事かを判断するには、サブルーチンoutputが何回呼び出されたかをカウントしていけば値が得られるので、カウント数を$countとして数えてみましょう。

#メイン表示プログラム
sub html {

    #ヘッダの読込
    &header;

    #ログの読込
    open(IN,"$file") || &error("Can't open $file");
    @lines = <IN>;
    close(IN);
    #$countの初期化
    $count = 0;


    #ログ全部?
    foreach $line (@lines) {
        local($name,$email,$url,$msr) = split(/<>/,$line);
        #カウント処理
        $count = $count + 1;

        &output;
    }

    #フッタの読込
    &footer;
exit;
}

カウントした記事が何番目なのかを隠しパラメータcntに代入します。

#リピート部分プログラム
sub output {
    print <<"EOT";
<FORM action="bbs.cgi" method="POST">
<INPUT type="hidden" name="mode" value="delete">

<INPUT type="hidden" name="cnt" value="$count">
投稿者:$name <INPUT type="text" name="pwd" size="10">
<INPUT type="submit" value="削除">
<BR>
E-mail:<A href="mailto:$email">$email</A><BR>
Homepage:<A href="$url" target="_blank">$url</A><BR>
投稿内容<BR>
$msr
<HR>
</FORM>
EOT
}

これで目印がちゃんと付けられましたね!

>記事削除>第三段階

いよいよ、削除プログラムの作成です。
#記事削除プログラム
sub delete {

    #ファイルのオープン 予め$fileにログファイル名が代入されている物とします。
    open(IN,"$file") || &error("Can't open $file");
    open(OUT,">$temp") || &error("Can't write Temp File");

    #ログファイルを配列@linesに代入
    @lines = <IN>;
    #$countの初期化
    $count = 0;

    foreach $line (@lines) {
        $count = $count + 1;
        #目印が一緒でなければデータを記録
        if ($count != $FORM{'cnt'}) {
            push (@CS,$line);
        }
    }

    #ログの書込処理
    print OUT @CS;
    close(OUT);
    close(IN);
    rename($temp,$file) || &error("Rename Error");
    chmod (0666,$file);
    if (-e $temp) { unlink($temp); }

}

先にも述べましたが、このルーチンでは目印を確認して、目印が一致しない物をログとして書き残しています。ただここでは、説明を簡単にする為にこのような手法で説明していますが、これには閲覧中に書き込みがあった場合、違うログを削除してしまう危険性があります。ですから、本来目印にする物は不変の値にすることは必須条件となりますので覚えて置いてください。

>記事削除>最後に

大詰めです!最後に管理者パスワードが一致しているか?を認識させれば作業完了です。管理者パスワードを$passに事前に設定しておきます。それに対してサブルーチンdeleteの最初にif文で制限をかければ言い訳です。ここでは、パスワードは特に暗号化したりしてませんが、Perlでは暗号化する関数が用意されています。いずれ?執筆するであろう中級編にてその辺は説明いたしますので、ここではまず慣れる!と言うことで・・・。(^-^;;;(手抜き?!)

$file = "bbs.log"; #ログファイルの設定
$temp = "./temp.dat"; #テンポラリーファイル
$bgcolor = "#ffffff"; #掲示板の背景色設定
$home = "../indec.htm"; #戻り先URL
$pass = "webmaster"; #管理者パスワード

#記事削除プログラム
sub delete {

    if ($pass eq '') { &error("管理者パスワードを入力して下さい。"); }
    if ($pass ne $FORM{'pwd'}) { &error("Passwordが違います。"); }


    #ファイルのオープン 予め$fileにログファイル名が代入されている物とします。
    open(IN,"$file") || &error("Can't open $file");
    open(OUT,">$temp") || &error("Can't write Temp File");

    #ログファイルを配列@linesに代入
    @lines = <IN>;
    #$countの初期化
    $count = 0;

    foreach $line (@lines) {
        $count = $count + 1;
        #目印が一緒でなければデータを記録
        if ($count != $FORM{'cnt'}) {
            push @CS;
        }
    }

    #ログの書込処理
    print OUT @CS;
    close(OUT);
    close(IN);
    rename($temp,$file) || &error("Rename Error");
    chmod (0666,$file);
    if (-e $temp) { unlink($temp); }

}

□特別編 一緒に簡易掲示板を作ってみよう