fork(3) download
  1. #coding: utf-8
  2. require "webrick"
  3.  
  4. include WEBrick
  5.  
  6. $thure_list = []
  7. (Thure = Struct.new(:res_list, :subj)).class_eval {
  8. def to_uri
  9. "/read?id=#{object_id}"
  10. end
  11.  
  12. def to_html(*ranges)
  13. buf = "<dl>"
  14. ranges.each {|range|
  15. res_list[range] and
  16. res_list[range].each {|res|
  17. buf << "<dt style='margin-top:10px;'>#{res.no} :#{res.name}:#{res.date} ID:#{res.hash}</dt>"
  18. buf << "<dd>#{res.text}</dd>"
  19. }
  20. }
  21. buf << "</dl>"
  22. buf << <<-FORM
  23. <form method='POST' action='/post'>
  24. <div>
  25. <input type='submit' value='書き込む'>
  26. 名前:<input type='text' name='name'>
  27. E-mail:<input type='text' name='mail'>
  28. </div>
  29. <textarea name='text'></textarea>
  30. <input type='hidden' name='id' value='#{object_id}'>
  31. </form>
  32. FORM
  33. end
  34. }
  35.  
  36. Res = Struct.new :no, :text, :name, :mail, :date, :hash
  37.  
  38. class String
  39. def nonempty?
  40. empty? ? nil: self
  41. end
  42. end
  43.  
  44. def get_thure(id)
  45. id = id.to_i
  46. thure = $thure_list.find {|t| t.object_id == id }
  47. thure or raise "スレッド(#{id})が見つかりません!"
  48. end
  49.  
  50. def put_error(resp, e)
  51. resp["Content-Type"] = "text/html"
  52. resp.body = <<-PAGE
  53. <html>
  54. <head><title>エラー</title></head>
  55. <body>
  56. <h1>エラー</h1>
  57. <p>#{e.to_s}</p>
  58. </body></html>
  59. PAGE
  60. end
  61.  
  62. 30.times {|i|
  63. $thure_list << Thure.new([], ["はじまりです","おわりだお","まピョーン☆", "アラシはいやづら"][(rand * 4).floor])
  64.  
  65.  
  66. 1.upto((rand * 1000).floor) {|n|
  67. $thure_list.last.res_list << Res.new(n,
  68. "はじまりなのです".chars.to_a.shuffle.join,
  69. "まろゆき".chars.to_a.shuffle.join, "sage", Time.now, "???")
  70. }
  71. }
  72.  
  73. $style = <<CSS
  74. <style>
  75. body {
  76. background:#93ff93;
  77. }
  78. </style>
  79. CSS
  80.  
  81. server = HTTPServer.new( Port: 8080 )
  82. server.mount_proc("/") {|req, resp|
  83. resp["Content-Type"] = "text/html"
  84. resp.body = <<-PAGE
  85. <html>
  86. <head>
  87. <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>
  88. <title>Aちゃんねる</title>
  89. #{$style}
  90. <style>
  91. body {
  92. background:#93ff93;
  93. }
  94. h1 { text-align: center; }
  95. body > div {
  96. margin: 20px auto 0 auto;
  97. padding: 5px;
  98. width: 90%;
  99. border:3px solid green;
  100. background: #23a710;
  101. }
  102. h2 {
  103. margin: -3px 0 30px 0;
  104. border:5px solid darkgreen;
  105. border-width: 0 0 0 10px;
  106. }
  107. textarea {
  108. width: 45em;
  109. height: 7em;
  110. }
  111. </style>
  112. </head>
  113. <body>
  114. <h1>アラシはいやづら</h1>
  115. <div>
  116. PAGE
  117. count = 0
  118. $thure_list[0..9].each {|t|
  119. resp.body << "<a href='#{t.to_uri}'>#{count += 1}</a>:<a href='##{t.object_id}'>#{t.subj}(#{t.res_list.size})</a>\n"
  120. }
  121. resp.body << "<hr>"
  122. $thure_list.size > 10 and
  123. $thure_list[10..-1].each {|t|
  124. resp.body << "<a href='#{t.to_uri}'>#{count += 1}:#{t.subj}(#{t.res_list.size})</a>\n"
  125. }
  126. resp.body << "</div>"
  127. $thure_list[0..10].each {|t|
  128. resp.body << "<div><a name='#{t.object_id}'></a><h2>#{t.subj}</h2>#{t.to_html(0..0, [1,t.res_list.size-9].max..-1)}"
  129. resp.body << "<div><a href='#{t.to_uri}&pos=%7c50'>最新50件</a></div></div>"
  130. }
  131. resp.body << <<-PAGE
  132. <div>
  133. <form method='POST' action='/post'>
  134. <div>
  135. <input type='submit' value='スレッドを立てる'>
  136. 主題:<input type='text' name='subj'>
  137. 名前:<input type='text' name='name'>
  138. E-mail:<input type='text' name='mail'>
  139. </div>
  140. <textarea name='text'></textarea>
  141. </form>
  142. </div>
  143. </body></html>
  144. PAGE
  145.  
  146. }
  147. server.mount_proc("/read") {|req, resp|
  148. resp["Content-Type"] = "text/html"
  149. begin
  150. id = req.query["id"].to_i
  151. thure = $thure_list.find {|t| t.object_id == id }
  152. resp.body = <<-PAGE
  153. <html>
  154. <head>
  155. <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>
  156. <title>Aちゃんねる</title>
  157. <style>
  158. body {
  159. background:#93ff93;
  160. }
  161. textarea {
  162. width: 45em;
  163. height: 7em;
  164. }
  165. </style>
  166. </head>
  167. <body>
  168. <h1>スレ:#{thure.subj}</h1>
  169. <div>ページ: 1
  170. #{
  171. s = ""
  172. 50.step(1000, 50) {|n|
  173. break if n > thure.res_list.size
  174. s << "<a href='?id=#{id}&pos=#{n-49}-#{n}'>-#{n}</a> "
  175. }
  176. s
  177. }
  178. </div>
  179. #{
  180. thure.to_html(*case req.query["pos"]
  181. when /\|(\d+)/ then [[thure.res_list.size-$1.to_i,0].max..-1]
  182. when /(\d+)(-(\d+))?/ then [$1.to_i..($3||$1).to_i]
  183. else [0..-1]
  184. end)
  185. }
  186. </body>
  187. </html>
  188. PAGE
  189. rescue => e
  190. put_error resp, e.to_s
  191. end
  192. }
  193. server.mount_proc("/post") {|req, resp|
  194. begin
  195. text = (req.query["text"]||"").nonempty? or raise "本文が入力されてません"
  196. name = (req.query["name"]||"").nonempty? || "名無しさん"
  197. mail = req.query["mail"]||""
  198. subj = req.query["subj"]||""
  199. subj.force_encoding "UTF-8"
  200. mail.force_encoding "UTF-8"
  201. name.force_encoding "UTF-8"
  202. text.force_encoding "UTF-8"
  203. res = Res.new(1, text, name, mail,
  204. Time.now, req.peeraddr.to_s.crypt("XX")[2..-1])
  205. if subj.empty?
  206. thure = get_thure req.query["id"]
  207. thure.res_list << res
  208. res.no = thure.res_list.size
  209. unless mail =~/sage/
  210. $thure_list.delete thure
  211. $thure_list.unshift thure
  212. end
  213. else
  214. $thure_list.unshift Thure.new([res], subj)
  215. end
  216. resp["Pragma"] = "no-cache"
  217. resp.set_redirect(HTTPStatus::MovedPermanently, '/')
  218. rescue => e
  219. put_error resp, e.to_s
  220. end
  221. }
  222.  
  223. trap(:INT) { server.shutdown }
  224. server.start
  225.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty