http://www.mbx.jp/index.cgi
#! /usr/local/bin/ruby -EUTF-8
# -*- mode:ruby; coding:utf-8 -*-

#----------------#
# 外部ライブラリ #
#----------------#
require 'fileutils'
require 'cgi'

#------------------#
# 表示に関する設定 #
#------------------#
CGI.accept_charset=("UTF-8")
c = CGI.new

SITE_TITLE       = "SHINSHIBA - Bulletin Board System"
HOME_PAGE        = "http://sv3.mbx.jp/macavity"

BODY_BGCOLOR     = "#d0ffff"
BODY_TEXT_COLOR  = "#000000"
BASEFONT_SIZE    = "4"

PAGE_TITLE       = "電子掲示板"
TITLE_FONT_COLOR = "#006666"
TITLE_FONT_SIZE  = "6"

NAME_HEADING     = "名前(N):"
NAME_SIZE        = "40"
NAME_TEXT        = CGI.escapeHTML(c['NAME_TEXT'])
NAME_NOTES       = "―名前かタイトル(必須)―"

LINK_HEADING     = "連絡先(L):"
LINK_SIZE        = "40"
LINK_TEXT        = CGI.escapeHTML(c['LINK_TEXT'])
LINK_NOTES       = "―メールかURL(任意)―"

MESSAGE_HEADING  = "メッセージ(M):"
MESSAGE_COLS     = "80"
MESSAGE_ROWS     = "3"
MESSAGE_TEXT     = CGI.escapeHTML(c['MESSAGE_TEXT'])
MESSAGE_NOTES    = "※ 全体をpreタグで囲むには整形済みをチェック。"

PREFORMATTED     = CGI.escapeHTML(c['PREFORMATTED'])

#------------------#
# 制御に関する設定 #
#------------------#
SUBMIT           = CGI.escapeHTML(c['SUBMIT'])
UNIQUE_ID        = CGI.escapeHTML(c['UNIQUE_ID'])
CURRENT_PAGE     = CGI.escapeHTML(c['CURRENT_PAGE'])
REQUESTED_PAGE   = CGI.escapeHTML(c['p'])
HTTP_ERROR       = "Status: 403 Forbidden\nContent-type: text/html\n\n"

FORM_ACTION      = "./test/"
POST_BOX         = "./post_box"
WORK_DIR         = "#{POST_BOX}/#{c.remote_addr}"
WORK_FILE        = "#{WORK_DIR}/#{UNIQUE_ID}.txt"

LOG_DIR          = "./log_dir"
LOG_FILE         = "#{LOG_DIR}/log_file.txt"

#--------#
# 前処理 #
#--------#
unposted = false
pastlog = ""

if CURRENT_PAGE.empty? then
   if REQUESTED_PAGE.empty? then
      CURRENT_PAGE = 1
   elsif ( /^([0-9])+$/ =~ REQUESTED_PAGE ) then
      CURRENT_PAGE = REQUESTED_PAGE.to_i
   else
      CURRENT_PAGE = 0
   end
else
   CURRENT_PAGE = CURRENT_PAGE.to_i
end
if CURRENT_PAGE == 0 then
   unposted = true # 403エラー
end

if SUBMIT == " 確認(S) " then
   #------------------------------------#
   # ログの更新と読込、一時ファイル削除 #
   #------------------------------------#
   if File.exist?(WORK_FILE) then
      File.open(WORK_FILE, mode = "r"){ |f|
         pastlog = f.read
      }
      if File.exist?(LOG_FILE) then
         File.open(LOG_FILE, mode = "r+"){ |f|
            f.flock(File::LOCK_EX)
            pastlog << f.read
            f.seek(0)
            f.puts pastlog
            f.flock(File::LOCK_UN)
         }
      else
         unposted = true # 403エラー
      end
      File.unlink(WORK_FILE)
      NAME_TEXT = ""
      LINK_TEXT = ""
      MESSAGE_TEXT = ""
      PREFORMATTED = ""
      CURRENT_PAGE = 1
   else
      unposted = true # 403エラー
   end
elsif SUBMIT == " 戻る(B) " then
   #--------------------#
   # 一時ファイルの削除 #
   #--------------------#
   if File.exist?(WORK_FILE) then
      File.unlink(WORK_FILE)
   end
   #----------------#
   # 過去ログ再読込 #
   #----------------#
   if File.exist?(LOG_FILE) then
      File.open(LOG_FILE, mode = "r"){ |f|
         pastlog = f.read
      }
   else
      unposted = true # 403エラー
   end
elsif File.exist?(LOG_FILE) then
   #--------------#
   # 過去ログ読込 #
   #--------------#
   File.open(LOG_FILE, mode = "r"){ |f|
      pastlog = f.read
   }
else
   #------------#
   # ログ初期化 #
   #------------#
   FileUtils.mkdir_p(LOG_DIR, :mode => 0700)
   File.open(LOG_FILE, mode = "w", perm = 0644){ |f|
      f.puts "これ以下の記事はありません。"
   }
   pastlog = "電子掲示板のログファイルを新規作成しました。<br>"
end

Articles = pastlog.scan(/<!--End of Article-->/).size
if Articles == 0 then
   LastPage = 1
else
   LastPage = (Articles - 1) / 10 + 1
end

if CURRENT_PAGE > LastPage then
   unposted = true # 403エラー
end

if CURRENT_PAGE > 1 then
   Previous = CURRENT_PAGE - 1
else
   Previous = nil
end
if CURRENT_PAGE < LastPage then
   Next = CURRENT_PAGE + 1
else
   Next = nil
end

if unposted == false then

   NAVIGATION = "[ <a href=\"#{HOME_PAGE}\" target=\"_top\">Home</a> ]"
   if Previous then
      NAVIGATION << "[ <a href=\"./?p=#{Previous}\" target=\"_top\">前</a> ]"
   else
      NAVIGATION << "[ 前 ]"
   end
   if Next then
      NAVIGATION << "[ <a href=\"./?p=#{Next}\" target=\"_top\">次</a> ]"
   else
      NAVIGATION << "[ 次 ]"
   end

   #------------#
   # HTMLの出力 #
   #------------#
   puts c.header
   print <<"EOS"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>#{SITE_TITLE}</title>
      <link rel="canonical" href="#{HOME_PAGE}">
   </head>
   <body bgcolor="#{BODY_BGCOLOR}" text="#{BODY_TEXT_COLOR}">
      <basefont size="#{BASEFONT_SIZE}">
      <p>#{NAVIGATION}</p>
      <div align="center">
         <font size="#{TITLE_FONT_SIZE}" color="#{TITLE_FONT_COLOR}">
            <b>#{PAGE_TITLE}</b>
         </font>
      </div>
      <hr>
      <form method="post" action="#{FORM_ACTION}">
         <table border="0" summary="Posted column">
            <tr>
               <td>#{NAME_HEADING}</td>
               <td>
                  <input type="hidden" name="NAME_HEADING" value="#{NAME_HEADING}">
                  <input type="hidden" name="NAME_SIZE" value="#{NAME_SIZE}">
                  <input type="text" name="NAME_TEXT" size="#{NAME_SIZE}" value="#{NAME_TEXT}" accesskey="n" tabindex="1">
                  <small>#{NAME_NOTES}</small><br>
               </td>
            </tr>
            <tr>
               <td>#{LINK_HEADING}</td>
               <td>
                  <input type="hidden" name="LINK_HEADING" value="#{LINK_HEADING}">
                  <input type="hidden" name="LINK_SIZE" value="#{LINK_SIZE}">
                  <input type="text" name="LINK_TEXT" size="#{LINK_SIZE}" value="#{LINK_TEXT}" accesskey="l" tabindex="2">
                  <small>#{LINK_NOTES}</small><br>
               </td>
            </tr>
            <tr>
               <td colspan="2">#{MESSAGE_HEADING}<small>#{MESSAGE_NOTES}</small></td>
            </tr>
            <tr>
               <td colspan="2">
                  <input type="hidden" name="MESSAGE_HEADING" value="#{MESSAGE_HEADING}">
                  <input type="hidden" name="MESSAGE_COLS" value="#{MESSAGE_COLS}">
                  <input type="hidden" name="MESSAGE_ROWS" value="#{MESSAGE_ROWS}">
                  <textarea cols="#{MESSAGE_COLS}" rows="#{MESSAGE_ROWS}" name="MESSAGE_TEXT" accesskey="m" tabindex="3">#{MESSAGE_TEXT}</textarea>
                  <input type="checkbox" name="PREFORMATTED" value="checked" #{PREFORMATTED} accesskey="p" tabindex="4">整形済み(P)
               </td>
            </tr>
         </table>
         <p>
            <input type="hidden" name="SITE_TITLE" value="#{SITE_TITLE}">
            <input type="hidden" name="HOME_PAGE" value="#{HOME_PAGE}">
            <input type="hidden" name="BODY_BGCOLOR" value="#{BODY_BGCOLOR}">
            <input type="hidden" name="BODY_TEXT_COLOR" value="#{BODY_TEXT_COLOR}">
            <input type="hidden" name="BASEFONT_SIZE" value="#{BASEFONT_SIZE}">
            <input type="hidden" name="PAGE_TITLE" value="#{PAGE_TITLE}">
            <input type="hidden" name="TITLE_FONT_COLOR" value="#{TITLE_FONT_COLOR}">
            <input type="hidden" name="TITLE_FONT_SIZE" value="#{TITLE_FONT_SIZE}">
            <input type="submit" name="SUBMIT" value=" 確認(S) " accesskey="s" tabindex="5">(プレビュー表示へ)
         </p>
      </form>
      <hr>
EOS
   array = pastlog.split("<!--End of Article-->")
   count = 1
   array.each_slice(10){|a|
      if count == CURRENT_PAGE then
         puts a.join
         break
      end
      count += 1
   }
   print <<"EOS"
   <p>#{NAVIGATION}</p>
   </body>
</html>
EOS
else
   print HTTP_ERROR
end