送受信_フォームデータの扱い-演習編

Problem4: 簡単画像掲示板を作ってみよう

下記のようなフォーム要素を含み、文章と画像を載せることの出来る掲示板を作成してください

<textarea name="messe" cols="72" rows="6">何か書いてください</textarea>
<input type="file" name="tenpu" value="">

画像掲示板表示の例

⇒ ヒント

Hint

受信画像の縮小方法

⇒ 答え

Solution

html ファイル:ファイル名 index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
  <meta http-equiv="Content-Style-Type" content="text/css" >
  <style type="text/css">
  <!--
    body{background-color:#fed;color:#348;margin:1em 5%;}
    p{margin:0em;padding:0.25em 0.5em;}
    img{border:outset #fed 2px;float:left;margin:0em 1em 0.5em 0em;}
    hr{clear:both;}
  -->
  </style>
  <title>画像掲示板</title>
</head>
<body>
<form action="bbs.cgi" method="POST" enctype="multipart/form-data">
<textarea            name="messe" cols="72" rows="6">何か書いてください</textarea>
<br>画像ファイル:
<input type="file"   name="tenpu" value="" size="36">
<input type="submit" name="btn"   value="送信">
</form>
</body>
</html>

CGIファイル:ファイル名 bbs.cgi

#!/usr/local/bin/ruby -Ks
@in = Hash.new
if /boundary=([\-\w]+)$/ =~ ENV['CONTENT_TYPE'].to_s then # データ送られてきた場合を判別
  boundary = $1                                      # データ境界の目印を変数boundaryに写し取る
  while data = STDIN.gets(boundary) do               # 入力を境界で区切って、変数dataに写し取る
    if /\A[\r\n]*[^\r\n]+name="(tenpu|messe)"/ =~ data then # データの最初含まれるname値で選別
      key = $1                                       # name 値
      data.sub!(/\A[\r\n]*/,"")                      # データ最初の空行を取り除く
      data.sub!(/[\r\n]*\-\-#{ boundary }\z/,"")     # データ終端のゴミを除去
      data = data.split(/\n\r?\n\s*/,2)[1]           # ヘッダ部分を切り落とす
      next unless data                               # データの中身が空っぽ(改行スペース含む)なら、スキップ
      @in[key] = data                                # データを写し取る
    end
  end
end
messe = ""
if @in["tenpu"] then                                # 添付画像があったら縮めて保存
  outfile = "img/p%08d.jpg" % rand(10**8)
  open("|convert -geometry '160>x120>' - #{outfile}" , "wb"){|f| f.print @in["tenpu"] } rescue nil
  messe += "<img src=\"#{ outfile }\">\n" if FileTest.file?(outfile)
end
if @in["messe"] && @in["messe"] != "" then           # メッセージ部分の処理
  @in["messe"].gsub!(/\r\n/,"\n")                    # 改行コード変換
  @in["messe"].gsub!(/\r/,"\n")                      # 改行コード変換
  @in["messe"].gsub!(/\f/,"\n")                      # 改行コード変換
  @in["messe"].gsub!(/\v/,"\n")                      # 改行コード変換
  @in["messe"].gsub!(/\n\n+/,"\n")                   # 余分な改行を潰す
  @in["messe"].gsub!(/\0/,"")                        # 隠し文字を潰す
  @in["messe"].gsub!(/&/,"&amp;")                    # XSS 対策
  @in["messe"].gsub!(/&amp;#(\d{2,4});/){ "&#" + $1 + ";" } # XSS 対策(一部戻す)
  @in["messe"].gsub!(/</,"&lt;")                     # XSS 対策
  @in["messe"].gsub!(/>/,"&gt;")                     # XSS 対策
  @in["messe"].gsub!(/"/,"&quot;")                   # XSS 対策
  @in["messe"].gsub!(/'/,"&#39;")                    # XSS 対策
  @in["messe"].gsub!(/\n/,"</p>\n<p>")               # 改行があったら段落分け
  @in["messe"].gsub!(/\t/,"&nbsp;&nbsp;")            # タブの処理
  messe += "<p>" + @in["messe"] + "</p>\n"
end
if messe != "" then
  messe += "<hr>\n"
  html = File.open("index.html"){|f| f.read } rescue "<html><body><h1>Error!</h1></body></html>"
  html.sub!(/<\/form>/){ $& + "\n" + messe }         # メッセージを挟み込む
  open("index.html","w"){|f| f.print html } rescue 0 # html ファイルを書き換える
end

puts "Location: ./index.html"                        # html ファイルへジャンプ
puts

以上です。

Last updated 04.Oct.2006 [ Home ] [ Up ] [ 質問メール ]
Copyright © 2005-2006 Shigeru Konno All Rights Reserved..