3.5. 掲示板完成(バグ無し版)


やっと問題の起こらない(はず)の掲示板の完成です。
一応形だけできた状態(2章)から結構かかりましたね。
このようにプログラミングとは特例のような事を常に考えなければなりません。
それを行わないとセキュリティーホールと言われるものができてしまったりします。
特にCGIはネットワークを通じてたくさんの人が扱うので注意が必要です。
と、年寄りのお説教みたいのはさておいてプログラムを見てみましょ。

-- プログラム 始まり -- bbs2.cgi

#!/usr/local/bin/ruby

print "Content-type: text/html\n\n"

require "cgi-lib"

input = CGI.new

require "kconv"



#初期設定

CR = "\015"

LF = "\012"

EOL = CR + LF

BR = "<br>"

FILENAME = "bbs2.log"

LOCKFILENAME = "bbs2.log.lock"

MAXLOG = 10

$log = []



#ファイルロッククラス作成

class FileLockDir

  def lock(lockdir)

    begin

      Dir.mkdir(lockdir)

      lockflag = true

    rescue Errno::EEXIST

      lockflag = false

    end

    return(lockflag)

  end



  def unlock(lockdir)

    begin

      Dir.rmdir(lockdir)

      lockflag = true

    rescue

      lockflag = false

    end

    return(lockflag)

  end

end



#ログファイルの読みこみ関数

def read_log_file

  c = 0

  begin

    fh = open(FILENAME)

  rescue Errno::ENOENT

    return

  end



  fh.each{|l|

    $log[c] = l

    c += 1

    if c >= MAXLOG

      break

    end

  }

  fh.close

end



#ログファイルの書き込み関数

def write_log_file(writedata)

  $log.unshift("#{writedata}\n")

  c = 0

  fh = open(FILENAME, "w")

  $log.each{|l|

    fh.print l

    c += 1

    if c >= MAXLOG

      break

    end

  }

  fh.close

end







#ファイルロッククラスの初期化

fillock = FileLockDir.new



#フォームからのデータ読みこみと日本語変換と改行の変換

if input["senddata"]

  senddata = Kconv.tosjis(input["senddata"])

  senddata.gsub!(/#{EOL}/, BR)

  senddata.gsub!(/#{CR}/, BR)

  senddata.gsub!(/#{LF}/, BR)

end



#ログファイルの読みこみ関数を呼び出す

read_log_file



#書き込みがあったら

if senddata

#ファイルロック設定

  if !(fillock.lock(LOCKFILENAME)) 

    print <<EOF;

<html><body>

他の人が書き込み中です。<br>しばらく待ってからもう一度書いて下さい。

</body></html>

EOF

  end



#ログファイルの書き込み関数を呼び出し

  write_log_file(senddata)



#ファイルロック解除

  fillock.unlock(LOCKFILENAME)

end



#HTMLの表示

print <<EOF;

<html>

<body>

<form method="POST">

<textarea name="senddata" cols="80" rows="10"></textarea>

<input type="submit" value="送信">

</form> 

<hr>

EOF



$log.each{|l|

  print "#{l}\n<hr>\n"

}



print <<EOF;

</body>

</html>

EOF



-- プログラム 終わり --

ずいぶんと長いプログラムになっちゃいましたね。
でもほとんどが今までにやってきたことをくっつけているだけなので説明しなければならない部分はそんなにはないと思います。
でも長くても関数、クラスを使っているので比較的見やすくなっていると思います。
プログラムが見やすくなるというのは関数や、クラスを使う事の一番のいい部分かもしれませんね。

たいていの部分はすでに説明が終わっているので飛ばしながら説明します。

1行目から5行目まではモジュールの呼び出しなどのお決まりです。
7行目から15行目までは定数の設定や配列の初期化などを行っています。
17行目から38行目はファイルのロックを行うクラスの作成です。詳しくは「3.4. クラスを作ってみよう」を参照して下さい。
40行目から57行目はログの読みのみの関数を作成しています。
59行目から72行目はログの書き込みの関数を作成しています。
ログの読みこみ書き込みの関数に関して「3.1. 日本語の変換と関数の作成」を参照して下さい。

76行目はクラスの初期化を行い、filelockという名で利用できるようにしています。
79行目から85行目はフォームからのデータ読みこみと日本語変換と改行の変換を行っています。「3.1. 日本語の変換と関数の作成」を参照して下さい。
88行目でログファイルの読みこみ関数を呼び出しています。
91行目でsenddataが存在していたら
92行目でファイルのロックを行って失敗したらメッセージを出して終了
成功したら101行目以降を実行で
102行目でログファイルの書き込み関数を呼び出しを行います。
105行目で先に作ってあったロックファイルの削除を行います。
106行目で91行のifの終わりです。ここの部分がロックを書けてファイルの書きこみを行っています。

108行目以降でHTMLの表示で119から121行目でログの表示を行っています。

今回は大体の部分はすでに説明が終わっていたので、流れだけをさらっと説明しました。
どうでしょうか。
掲示板もいろいろと考えて作るとちょっと面倒になってしまいます。
HTMLをいじることでこの掲示板に色をつけたり、表示形式を変えたりすることでさまざまな形の掲示板に変えることが出来ます。
が、ここではCGIとrubyの説明に絞りたいのでその説明は行いません。
今回の話しはいろいろと面倒なものが出てきてしまったので次回はもっと楽なものに取り組みたいと思います。


今回使った命令など

| | メニュー戻る | 次 |

LinkExchange Japan
LinkExchange Japan Member