Ruby で CGI > 送受信_フォームデータの扱い> 問題
下記のようなフォーム要素を含み、文章と画像を載せることの出来る掲示板を作成してください
<textarea name="messe" cols="72" rows="6">何か書いてください</textarea> <input type="file" name="tenpu" value="">
♪
convert -geometry '160>x120>' in.jpg out.jpg参照 ⇒ Imagemagick のマニュアル
img = (画像データ)
infile = "p%08d" % rand(10**8) # 一時保存ファイル:ファイル名
outfile = "p%08d.jpg" % rand(10**8) # 出力画像ファイル:ファイル名
File.open(infile,"wb"){|f| f.print img } # 画像データを一時ファイルに保存
a = ["convert"] # Imagemagick 画像変換コマンド
a += ["-geometry","160>x120>"] # 横160px,縦120px を超える場合は縮小
a += [infile,outfile] # infile を outfile に変換する
system(*a) # 画像の変換を実行する
result = STDOUT.to_s.split(/#/).shift.chomp # 処理に失敗した場合のメッセージを拾いだす
Process.waitall # 処理が全て終わるのを待つ(注意:ruby1.7以上)
File.delete(infile) if FileTest.file?(infile) # 一時ファイルを削除する
cat in.jpg | convert -geometry '160>x120>' - out.jpg
img = (画像データ)
outfile = "p%08d.jpg" % rand(10**8)
open("|convert -geometry '160>x120>' - #{outfile}" , "wb"){|f| f.print img } rescue nil
result = STDOUT.to_s.split(/#/).shift.chomp
open
は、ファイル名の代わりにコマンドが書けるだけでなく、パイプの処理機能もあります。参照 ⇒ openrescue nil
は不要ですが、将来何らかの仕様変更があった場合に備えて、入れておきますsystem
やopen
でのコマンド処理に失敗した場合のエラーメッセージなどは、標準出力STDOUT
から拾いだすことができます
t = "%x" % ( Time.now.to_i*100 + Time.now.usec.to_i/10000 )
puts t
puts Time.at(t.hex/100)
36進数では、1/1000 秒単位でも8桁
def t36
t = Time.now.to_i*1000 + Time.now.usec.to_i/1000
seed = "0123456789abcdefghijklmnopqrstuvwxyz"
str = ""
while t > 0 do
str += seed[ t % seed.length ,1 ]
t /= seed.length
end
str.reverse
end
puts t36
# 時刻に復元↓
str = t36
seed = "0123456789abcdefghijklmnopqrstuvwxyz"
t = 0
n = 1
str.reverse!
while c = str.slice!(0) do
t += seed.index(c.chr)*n
n *= seed.length
end
puts Time.at(t/1000)
♪
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!(/&/,"&") # XSS 対策
@in["messe"].gsub!(/&#(\d{2,4});/){ "&#" + $1 + ";" } # XSS 対策(一部戻す)
@in["messe"].gsub!(/</,"<") # XSS 対策
@in["messe"].gsub!(/>/,">") # XSS 対策
@in["messe"].gsub!(/"/,""") # XSS 対策
@in["messe"].gsub!(/'/,"'") # XSS 対策
@in["messe"].gsub!(/\n/,"</p>\n<p>") # 改行があったら段落分け
@in["messe"].gsub!(/\t/," ") # タブの処理
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
以上です。