Ruby で CGI > 送受信_フォームデータの扱い> 問題
フォームから入力した文章をオウム返しに表示するCGIを作成してみてください
下記の手順でどうぞ
♪
uri
を元の文字列str
に戻すには、
str = uri.gsub(/\+/," ").gsub(/%[a-fA-F\d]{2}/){ $&[1,2].hex.chr }
str
の中の<を全て<に置き換えるには、str.gsub!(/</,"<")
str = str.gsub(/</,"<")
と、同じ結果となります。自分自身に代入し直すのがムダなので、!
を使います。ただし、どちらもstr
がnil
の場合はエラー(例外の発生)になるので注意。
♪
index.html:例えば、htmlファイルを下記のようにして、ファイル名 index.html とします。データの送り先は、parrot.cgi
<!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"> <title>オウム返し</title> </head> <body> <form action="parrot.cgi" method="GET"> 入力: <input type="text" name="messe" value="" tabindex="1" accesskey="1" size="72"> <input type="submit" name="botan" value="送信" tabindex="2" accesskey="2"> </form> </body> </html>
parrot.cgi:解説で使った例を、そのままコピーして使いました
#!/usr/local/bin/ruby -Ks
print <<HOGEHOGE
Content-Disposition: filename="parrot.txt"
Content-type: text/plain;charset=Shift_JIS
入力された文章:
HOGEHOGE
@in = Hash.new
for q in ENV['QUERY_STRING'].to_s.split(/[;&]/) do
key,val = q.split(/=/,2)
@in[key] = val.gsub(/\+/," ").gsub(/%[a-fA-F\d]{2}/){ $&[1,2].hex.chr } if val
end
print @in["messe"]
parrot.cgi:表示させるのは、一つの値だけで良いので、パターンマッチを使って簡略化できます
#!/usr/local/bin/ruby -Ks
print <<HOGEHOGE
Content-Disposition: filename="parrot.txt"
Content-type: text/plain;charset=Shift_JIS
入力された文章:
HOGEHOGE
if /messe=([^&]+)(&|\z)/ =~ ENV['QUERY_STRING'].to_s then
print $1.gsub(/\+/," ").gsub(/%[a-fA-F\d]{2}/){ $&[1,2].hex.chr }
end
[^&]
は&
以外の任意の一文字を表します(&|\z)
は、&
または\z
を意味します\z
は、文字列の終端を意味します$1
は直前の正規表現でマッチした部分の最初の( )
の中を表しますparrot.cgi:index.htmlを読み込んで、受信した一文を</body>の直前に挟み込みます
#!/usr/local/bin/ruby -Ks
@in = Hash.new
for q in ENV['QUERY_STRING'].to_s.split(/[;&]/) do
key,val = q.split(/=/,2)
@in[key] = val.gsub(/\+/," ").gsub(/%[a-fA-F\d]{2}/){ $&[1,2].hex.chr } if val
end
html = open("index.html"){|f| f.read } rescue "<html><body><h1>Error!</h1></body></html>"
html.sub!(/<\/body>/){ "<p>出力: #{ @in["messe"] }</p>\n" + $& }
print <<HOGEHOGE
Content-Disposition: filename="parrot.html"
Content-Length: #{ html.length }
Content-type: text/html;charset=Shift_JIS
HOGEHOGE
print html
parrot.cgi:XSS脆弱性対策として、入力された文字列を、置換してから表示させます。
#!/usr/local/bin/ruby -Ks
@in = Hash.new
for q in ENV['QUERY_STRING'].to_s.split(/[;&]/) do
key,val = q.split(/=/,2)
@in[key] = val.gsub(/\+/," ").gsub(/%[a-fA-F\d]{2}/){ $&[1,2].hex.chr } if val
end
if @in["messe"] then
@in["messe"].gsub!(/&/,"&")
@in["messe"].gsub!(/&#(\d{2,4});/){ "&#" + $1 + ";" }
@in["messe"].gsub!(/</,"<")
@in["messe"].gsub!(/>/,">")
@in["messe"].gsub!(/"/,""")
@in["messe"].gsub!(/'/,"'")
end
html = open("index.html"){|f| f.read } rescue "<html><body><h1>Error!</h1></body></html>"
html.sub!(/<\/body>/){ "<p>出力: #{ @in["messe"] }</p>\n" + $& }
print <<HOGEHOGE
Content-Disposition: filename="parrot.html"
Content-Length: #{ html.length }
Content-type: text/html;charset=Shift_JIS
HOGEHOGE
print html
@in["messe"].gsub!(/温泉/,"<span style=\"color:#f80;\">♨</span>")
なんて、追加しておくと、楽しいかもしれません以上です。