1 | warn "Warning:#{caller[0].sub(/:in `.*'\z/, '')}: cgi-lib is deprecated after Ruby 1.8.1; use cgi instead"
|
---|
2 |
|
---|
3 | =begin
|
---|
4 |
|
---|
5 | = simple CGI support library
|
---|
6 |
|
---|
7 | = example
|
---|
8 |
|
---|
9 | == get form values
|
---|
10 |
|
---|
11 | require "cgi-lib.rb"
|
---|
12 | query = CGI.new
|
---|
13 | query['field'] # <== value of 'field'
|
---|
14 | query.keys # <== array of fields
|
---|
15 |
|
---|
16 | and query has Hash class methods
|
---|
17 |
|
---|
18 |
|
---|
19 | == get cookie values
|
---|
20 |
|
---|
21 | require "cgi-lib.rb"
|
---|
22 | query = CGI.new
|
---|
23 | query.cookie['name'] # <== cookie value of 'name'
|
---|
24 | query.cookie.keys # <== all cookie names
|
---|
25 |
|
---|
26 | and query.cookie has Hash class methods
|
---|
27 |
|
---|
28 |
|
---|
29 | == print HTTP header and HTML string to $>
|
---|
30 |
|
---|
31 | require "cgi-lib.rb"
|
---|
32 | CGI::print{
|
---|
33 | CGI::tag("HTML"){
|
---|
34 | CGI::tag("HEAD"){ CGI::tag("TITLE"){"TITLE"} } +
|
---|
35 | CGI::tag("BODY"){
|
---|
36 | CGI::tag("FORM", {"ACTION"=>"test.rb", "METHOD"=>"POST"}){
|
---|
37 | CGI::tag("INPUT", {"TYPE"=>"submit", "VALUE"=>"submit"})
|
---|
38 | } +
|
---|
39 | CGI::tag("HR")
|
---|
40 | }
|
---|
41 | }
|
---|
42 | }
|
---|
43 |
|
---|
44 |
|
---|
45 | == make raw cookie string
|
---|
46 |
|
---|
47 | require "cgi-lib.rb"
|
---|
48 | cookie1 = CGI::cookie({'name' => 'name',
|
---|
49 | 'value' => 'value',
|
---|
50 | 'path' => 'path', # optional
|
---|
51 | 'domain' => 'domain', # optional
|
---|
52 | 'expires' => Time.now, # optional
|
---|
53 | 'secure' => true # optional
|
---|
54 | })
|
---|
55 |
|
---|
56 | CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" }
|
---|
57 |
|
---|
58 |
|
---|
59 | == print HTTP header and string to $>
|
---|
60 |
|
---|
61 | require "cgi-lib.rb"
|
---|
62 | CGI::print{ "string" }
|
---|
63 | # == CGI::print("Content-Type: text/html"){ "string" }
|
---|
64 | CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" }
|
---|
65 |
|
---|
66 |
|
---|
67 | === NPH (no-parse-header) mode
|
---|
68 |
|
---|
69 | require "cgi-lib.rb"
|
---|
70 | CGI::print("nph"){ "string" }
|
---|
71 | # == CGI::print("nph", "Content-Type: text/html"){ "string" }
|
---|
72 | CGI::print("nph", "Content-Type: text/html", cookie1, cookie2){ "string" }
|
---|
73 |
|
---|
74 |
|
---|
75 | == make HTML tag string
|
---|
76 |
|
---|
77 | require "cgi-lib.rb"
|
---|
78 | CGI::tag("element", {"attribute_name"=>"attribute_value"}){"content"}
|
---|
79 |
|
---|
80 |
|
---|
81 | == make HTTP header string
|
---|
82 |
|
---|
83 | require "cgi-lib.rb"
|
---|
84 | CGI::header # == CGI::header("Content-Type: text/html")
|
---|
85 | CGI::header("Content-Type: text/html", cookie1, cookie2)
|
---|
86 |
|
---|
87 |
|
---|
88 | === NPH (no-parse-header) mode
|
---|
89 |
|
---|
90 | CGI::header("nph") # == CGI::header("nph", "Content-Type: text/html")
|
---|
91 | CGI::header("nph", "Content-Type: text/html", cookie1, cookie2)
|
---|
92 |
|
---|
93 |
|
---|
94 | == escape url encode
|
---|
95 |
|
---|
96 | require "cgi-lib.rb"
|
---|
97 | url_encoded_string = CGI::escape("string")
|
---|
98 |
|
---|
99 |
|
---|
100 | == unescape url encoded
|
---|
101 |
|
---|
102 | require "cgi-lib.rb"
|
---|
103 | string = CGI::unescape("url encoded string")
|
---|
104 |
|
---|
105 |
|
---|
106 | == escape HTML &"<>
|
---|
107 |
|
---|
108 | require "cgi-lib.rb"
|
---|
109 | CGI::escapeHTML("string")
|
---|
110 |
|
---|
111 |
|
---|
112 | =end
|
---|
113 |
|
---|
114 | require "delegate"
|
---|
115 |
|
---|
116 | class CGI < SimpleDelegator
|
---|
117 |
|
---|
118 | CR = "\015"
|
---|
119 | LF = "\012"
|
---|
120 | EOL = CR + LF
|
---|
121 |
|
---|
122 | RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
|
---|
123 | RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
|
---|
124 |
|
---|
125 | # make rfc1123 date string
|
---|
126 | def CGI::rfc1123_date(time)
|
---|
127 | t = time.clone.gmtime
|
---|
128 | return format("%s, %.2d %s %d %.2d:%.2d:%.2d GMT",
|
---|
129 | RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
|
---|
130 | t.hour, t.min, t.sec)
|
---|
131 | end
|
---|
132 |
|
---|
133 | # escape url encode
|
---|
134 | def CGI::escape(str)
|
---|
135 | str.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
|
---|
136 | end
|
---|
137 |
|
---|
138 | # unescape url encoded
|
---|
139 | def CGI::unescape(str)
|
---|
140 | str.gsub(/\+/, ' ').gsub(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") }
|
---|
141 | end
|
---|
142 |
|
---|
143 | # escape HTML
|
---|
144 | def CGI::escapeHTML(str)
|
---|
145 | str.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<")
|
---|
146 | end
|
---|
147 |
|
---|
148 | # offline mode. read name=value pairs on standard input.
|
---|
149 | def read_from_cmdline
|
---|
150 | require "shellwords.rb"
|
---|
151 | words = Shellwords.shellwords(
|
---|
152 | if not ARGV.empty?
|
---|
153 | ARGV.join(' ')
|
---|
154 | else
|
---|
155 | STDERR.print "(offline mode: enter name=value pairs on standard input)\n" if STDIN.tty?
|
---|
156 | readlines.join(' ').gsub(/\n/, '')
|
---|
157 | end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26'))
|
---|
158 |
|
---|
159 | if words.find{|x| x =~ /=/} then words.join('&') else words.join('+') end
|
---|
160 | end
|
---|
161 |
|
---|
162 | def initialize(input = $stdin)
|
---|
163 |
|
---|
164 | @inputs = {}
|
---|
165 | @cookie = {}
|
---|
166 |
|
---|
167 | case ENV['REQUEST_METHOD']
|
---|
168 | when "GET"
|
---|
169 | ENV['QUERY_STRING'] or ""
|
---|
170 | when "POST"
|
---|
171 | input.read(Integer(ENV['CONTENT_LENGTH'])) or ""
|
---|
172 | else
|
---|
173 | read_from_cmdline
|
---|
174 | end.split(/[&;]/).each do |x|
|
---|
175 | key, val = x.split(/=/,2).collect{|x|CGI::unescape(x)}
|
---|
176 | if @inputs.include?(key)
|
---|
177 | @inputs[key] += "\0" + (val or "")
|
---|
178 | else
|
---|
179 | @inputs[key] = (val or "")
|
---|
180 | end
|
---|
181 | end
|
---|
182 |
|
---|
183 | super(@inputs)
|
---|
184 |
|
---|
185 | if ENV.has_key?('HTTP_COOKIE') or ENV.has_key?('COOKIE')
|
---|
186 | (ENV['HTTP_COOKIE'] or ENV['COOKIE']).split(/; /).each do |x|
|
---|
187 | key, val = x.split(/=/,2)
|
---|
188 | key = CGI::unescape(key)
|
---|
189 | val = val.split(/&/).collect{|x|CGI::unescape(x)}.join("\0")
|
---|
190 | if @cookie.include?(key)
|
---|
191 | @cookie[key] += "\0" + val
|
---|
192 | else
|
---|
193 | @cookie[key] = val
|
---|
194 | end
|
---|
195 | end
|
---|
196 | end
|
---|
197 | end
|
---|
198 |
|
---|
199 | attr("inputs")
|
---|
200 | attr("cookie")
|
---|
201 |
|
---|
202 | # make HTML tag string
|
---|
203 | def CGI::tag(element, attributes = {})
|
---|
204 | "<" + escapeHTML(element) + attributes.collect{|name, value|
|
---|
205 | " " + escapeHTML(name) + '="' + escapeHTML(value) + '"'
|
---|
206 | }.to_s + ">" +
|
---|
207 | (iterator? ? yield.to_s + "</" + escapeHTML(element) + ">" : "")
|
---|
208 | end
|
---|
209 |
|
---|
210 | # make raw cookie string
|
---|
211 | def CGI::cookie(options)
|
---|
212 | "Set-Cookie: " + options['name'] + '=' + escape(options['value']) +
|
---|
213 | (options['domain'] ? '; domain=' + options['domain'] : '') +
|
---|
214 | (options['path'] ? '; path=' + options['path'] : '') +
|
---|
215 | (options['expires'] ? '; expires=' + rfc1123_date(options['expires']) : '') +
|
---|
216 | (options['secure'] ? '; secure' : '')
|
---|
217 | end
|
---|
218 |
|
---|
219 | # make HTTP header string
|
---|
220 | def CGI::header(*options)
|
---|
221 | if defined?(MOD_RUBY)
|
---|
222 | options.each{|option|
|
---|
223 | option.sub(/(.*?): (.*)/){
|
---|
224 | Apache::request.headers_out[$1] = $2
|
---|
225 | }
|
---|
226 | }
|
---|
227 | Apache::request.send_http_header
|
---|
228 | ''
|
---|
229 | else
|
---|
230 | if options.delete("nph") or (ENV['SERVER_SOFTWARE'] =~ /IIS/)
|
---|
231 | [(ENV['SERVER_PROTOCOL'] or "HTTP/1.0") + " 200 OK",
|
---|
232 | "Date: " + rfc1123_date(Time.now),
|
---|
233 | "Server: " + (ENV['SERVER_SOFTWARE'] or ""),
|
---|
234 | "Connection: close"] +
|
---|
235 | (options.empty? ? ["Content-Type: text/html"] : options)
|
---|
236 | else
|
---|
237 | options.empty? ? ["Content-Type: text/html"] : options
|
---|
238 | end.join(EOL) + EOL + EOL
|
---|
239 | end
|
---|
240 | end
|
---|
241 |
|
---|
242 | # print HTTP header and string to $>
|
---|
243 | def CGI::print(*options)
|
---|
244 | $>.print CGI::header(*options) + yield.to_s
|
---|
245 | end
|
---|
246 |
|
---|
247 | # print message to $>
|
---|
248 | def CGI::message(message, title = "", header = ["Content-Type: text/html"])
|
---|
249 | if message.kind_of?(Hash)
|
---|
250 | title = message['title']
|
---|
251 | header = message['header']
|
---|
252 | message = message['body']
|
---|
253 | end
|
---|
254 | CGI::print(*header){
|
---|
255 | CGI::tag("HTML"){
|
---|
256 | CGI::tag("HEAD"){ CGI.tag("TITLE"){ title } } +
|
---|
257 | CGI::tag("BODY"){ message }
|
---|
258 | }
|
---|
259 | }
|
---|
260 | true
|
---|
261 | end
|
---|
262 |
|
---|
263 | # print error message to $> and exit
|
---|
264 | def CGI::error
|
---|
265 | CGI::message({'title'=>'ERROR', 'body'=>
|
---|
266 | CGI::tag("PRE"){
|
---|
267 | "ERROR: " + CGI::tag("STRONG"){ escapeHTML($!.to_s) } + "\n" + escapeHTML([email protected]("\n"))
|
---|
268 | }
|
---|
269 | })
|
---|
270 | exit
|
---|
271 | end
|
---|
272 | end
|
---|