rubysl-cgi 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,198 @@
1
+ class CGI
2
+ @@accept_charset="UTF-8" unless defined?(@@accept_charset)
3
+ # URL-encode a string.
4
+ # url_encoded_string = CGI::escape("'Stop!' said Fred")
5
+ # # => "%27Stop%21%27+said+Fred"
6
+ def CGI::escape(string)
7
+ encoding = string.encoding
8
+ string.dup.force_encoding('ASCII-8BIT').gsub(/([^ a-zA-Z0-9_.-]+)/) do
9
+ '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
10
+ end.tr(' ', '+').force_encoding(encoding)
11
+ end
12
+
13
+ # URL-decode a string with encoding(optional).
14
+ # string = CGI::unescape("%27Stop%21%27+said+Fred")
15
+ # # => "'Stop!' said Fred"
16
+ def CGI::unescape(string,encoding=@@accept_charset)
17
+ str=string.tr('+', ' ').force_encoding(Encoding::ASCII_8BIT).gsub(/((?:%[0-9a-fA-F]{2})+)/) do
18
+ [$1.delete('%')].pack('H*')
19
+ end.force_encoding(encoding)
20
+ str.valid_encoding? ? str : str.force_encoding(string.encoding)
21
+ end
22
+
23
+ # The set of special characters and their escaped values
24
+ TABLE_FOR_ESCAPE_HTML__ = {
25
+ "'" => ''',
26
+ '&' => '&',
27
+ '"' => '"',
28
+ '<' => '&lt;',
29
+ '>' => '&gt;',
30
+ }
31
+
32
+ # Escape special characters in HTML, namely &\"<>
33
+ # CGI::escapeHTML('Usage: foo "bar" <baz>')
34
+ # # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
35
+ def CGI::escapeHTML(string)
36
+ string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
37
+ end
38
+
39
+ # Unescape a string that has been HTML-escaped
40
+ # CGI::unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
41
+ # # => "Usage: foo \"bar\" <baz>"
42
+ def CGI::unescapeHTML(string)
43
+ enc = string.encoding
44
+ if [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].include?(enc)
45
+ return string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
46
+ case $1.encode("US-ASCII")
47
+ when 'apos' then "'".encode(enc)
48
+ when 'amp' then '&'.encode(enc)
49
+ when 'quot' then '"'.encode(enc)
50
+ when 'gt' then '>'.encode(enc)
51
+ when 'lt' then '<'.encode(enc)
52
+ when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
53
+ when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
54
+ end
55
+ end
56
+ end
57
+ asciicompat = Encoding.compatible?(string, "a")
58
+ string.gsub(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
59
+ match = $1.dup
60
+ case match
61
+ when 'apos' then "'"
62
+ when 'amp' then '&'
63
+ when 'quot' then '"'
64
+ when 'gt' then '>'
65
+ when 'lt' then '<'
66
+ when /\A#0*(\d+)\z/
67
+ n = $1.to_i
68
+ if enc == Encoding::UTF_8 or
69
+ enc == Encoding::ISO_8859_1 && n < 256 or
70
+ asciicompat && n < 128
71
+ n.chr(enc)
72
+ else
73
+ "&##{$1};"
74
+ end
75
+ when /\A#x([0-9a-f]+)\z/i
76
+ n = $1.hex
77
+ if enc == Encoding::UTF_8 or
78
+ enc == Encoding::ISO_8859_1 && n < 256 or
79
+ asciicompat && n < 128
80
+ n.chr(enc)
81
+ else
82
+ "&#x#{$1};"
83
+ end
84
+ else
85
+ "&#{match};"
86
+ end
87
+ end
88
+ end
89
+
90
+ # Synonym for CGI::escapeHTML(str)
91
+ def CGI::escape_html(str)
92
+ escapeHTML(str)
93
+ end
94
+
95
+ # Synonym for CGI::unescapeHTML(str)
96
+ def CGI::unescape_html(str)
97
+ unescapeHTML(str)
98
+ end
99
+
100
+ # Escape only the tags of certain HTML elements in +string+.
101
+ #
102
+ # Takes an element or elements or array of elements. Each element
103
+ # is specified by the name of the element, without angle brackets.
104
+ # This matches both the start and the end tag of that element.
105
+ # The attribute list of the open tag will also be escaped (for
106
+ # instance, the double-quotes surrounding attribute values).
107
+ #
108
+ # print CGI::escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
109
+ # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
110
+ #
111
+ # print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
112
+ # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
113
+ def CGI::escapeElement(string, *elements)
114
+ elements = elements[0] if elements[0].kind_of?(Array)
115
+ unless elements.empty?
116
+ string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
117
+ CGI::escapeHTML($&)
118
+ end
119
+ else
120
+ string
121
+ end
122
+ end
123
+
124
+ # Undo escaping such as that done by CGI::escapeElement()
125
+ #
126
+ # print CGI::unescapeElement(
127
+ # CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
128
+ # # "&lt;BR&gt;<A HREF="url"></A>"
129
+ #
130
+ # print CGI::unescapeElement(
131
+ # CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
132
+ # # "&lt;BR&gt;<A HREF="url"></A>"
133
+ def CGI::unescapeElement(string, *elements)
134
+ elements = elements[0] if elements[0].kind_of?(Array)
135
+ unless elements.empty?
136
+ string.gsub(/&lt;\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?&gt;/i) do
137
+ CGI::unescapeHTML($&)
138
+ end
139
+ else
140
+ string
141
+ end
142
+ end
143
+
144
+ # Synonym for CGI::escapeElement(str)
145
+ def CGI::escape_element(str)
146
+ escapeElement(str)
147
+ end
148
+
149
+ # Synonym for CGI::unescapeElement(str)
150
+ def CGI::unescape_element(str)
151
+ unescapeElement(str)
152
+ end
153
+
154
+ # Abbreviated day-of-week names specified by RFC 822
155
+ RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
156
+
157
+ # Abbreviated month names specified by RFC 822
158
+ RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
159
+
160
+ # Format a +Time+ object as a String using the format specified by RFC 1123.
161
+ #
162
+ # CGI::rfc1123_date(Time.now)
163
+ # # Sat, 01 Jan 2000 00:00:00 GMT
164
+ def CGI::rfc1123_date(time)
165
+ t = time.clone.gmtime
166
+ return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
167
+ RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
168
+ t.hour, t.min, t.sec)
169
+ end
170
+
171
+ # Prettify (indent) an HTML string.
172
+ #
173
+ # +string+ is the HTML string to indent. +shift+ is the indentation
174
+ # unit to use; it defaults to two spaces.
175
+ #
176
+ # print CGI::pretty("<HTML><BODY></BODY></HTML>")
177
+ # # <HTML>
178
+ # # <BODY>
179
+ # # </BODY>
180
+ # # </HTML>
181
+ #
182
+ # print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
183
+ # # <HTML>
184
+ # # <BODY>
185
+ # # </BODY>
186
+ # # </HTML>
187
+ #
188
+ def CGI::pretty(string, shift = " ")
189
+ lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\0\n")
190
+ end_pos = 0
191
+ while end_pos = lines.index(/^<\/(\w+)/, end_pos)
192
+ element = $1.dup
193
+ start_pos = lines.rindex(/^\s*<#{element}/i, end_pos)
194
+ lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__"
195
+ end
196
+ lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
197
+ end
198
+ end
@@ -1,41 +1,33 @@
1
- #
1
+ #
2
2
  # cgi.rb - cgi support library
3
- #
3
+ #
4
4
  # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
5
- #
5
+ #
6
6
  # Copyright (C) 2000 Information-technology Promotion Agency, Japan
7
7
  #
8
8
  # Author: Wakou Aoyama <wakou@ruby-lang.org>
9
9
  #
10
- # Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
11
- #
12
- # == Overview
10
+ # Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
13
11
  #
14
- # The Common Gateway Interface (CGI) is a simple protocol
15
- # for passing an HTTP request from a web server to a
16
- # standalone program, and returning the output to the web
17
- # browser. Basically, a CGI program is called with the
18
- # parameters of the request passed in either in the
19
- # environment (GET) or via $stdin (POST), and everything
20
- # it prints to $stdout is returned to the client.
21
- #
22
- # This file holds the +CGI+ class. This class provides
23
- # functionality for retrieving HTTP request parameters,
24
- # managing cookies, and generating HTML output. See the
25
- # class documentation for more details and examples of use.
26
- #
27
- # The file cgi/session.rb provides session management
28
- # functionality; see that file for more details.
29
- #
30
- # See http://www.w3.org/CGI/ for more information on the CGI
31
- # protocol.
32
12
 
33
- raise "Please, use ruby 1.5.4 or later." if RUBY_VERSION < "1.5.4"
13
+ raise "Please, use ruby 1.9.0 or later." if RUBY_VERSION < "1.9.0"
34
14
 
35
- require 'English'
36
-
37
- # CGI class. See documentation for the file cgi.rb for an overview
38
- # of the CGI protocol.
15
+ # == Overview
16
+ #
17
+ # The Common Gateway Interface (CGI) is a simple protocol for passing an HTTP
18
+ # request from a web server to a standalone program, and returning the output
19
+ # to the web browser. Basically, a CGI program is called with the parameters
20
+ # of the request passed in either in the environment (GET) or via $stdin
21
+ # (POST), and everything it prints to $stdout is returned to the client.
22
+ #
23
+ # This file holds the CGI class. This class provides functionality for
24
+ # retrieving HTTP request parameters, managing cookies, and generating HTML
25
+ # output.
26
+ #
27
+ # The file CGI::Session provides session management functionality; see that
28
+ # class for more details.
29
+ #
30
+ # See http://www.w3.org/CGI/ for more information on the CGI protocol.
39
31
  #
40
32
  # == Introduction
41
33
  #
@@ -77,18 +69,18 @@ require 'English'
77
69
  #
78
70
  #
79
71
  # For each of these variables, there is a corresponding attribute with the
80
- # same name, except all lower case and without a preceding HTTP_.
72
+ # same name, except all lower case and without a preceding HTTP_.
81
73
  # +content_length+ and +server_port+ are integers; the rest are strings.
82
74
  #
83
75
  # === Parameters
84
76
  #
85
77
  # The method #params() returns a hash of all parameters in the request as
86
78
  # name/value-list pairs, where the value-list is an Array of one or more
87
- # values. The CGI object itself also behaves as a hash of parameter names
88
- # to values, but only returns a single value (as a String) for each
79
+ # values. The CGI object itself also behaves as a hash of parameter names
80
+ # to values, but only returns a single value (as a String) for each
89
81
  # parameter name.
90
82
  #
91
- # For instance, suppose the request contains the parameter
83
+ # For instance, suppose the request contains the parameter
92
84
  # "favourite_colours" with the multiple values "blue" and "green". The
93
85
  # following behaviour would occur:
94
86
  #
@@ -107,7 +99,7 @@ require 'English'
107
99
  #
108
100
  # === Multipart requests
109
101
  #
110
- # If a request's method is POST and its content type is multipart/form-data,
102
+ # If a request's method is POST and its content type is multipart/form-data,
111
103
  # then it may contain uploaded files. These are stored by the QueryExtension
112
104
  # module in the parameters of the request. The parameter name is the name
113
105
  # attribute of the file input field, as usual. However, the value is not
@@ -130,7 +122,7 @@ require 'English'
130
122
  #
131
123
  # The simplest way to send output to the HTTP client is using the #out() method.
132
124
  # This takes the HTTP headers as a hash parameter, and the body content
133
- # via a block. The headers can be generated as a string using the #header()
125
+ # via a block. The headers can be generated as a string using the #http_header()
134
126
  # method. The output stream can be written directly to using the #print()
135
127
  # method.
136
128
  #
@@ -138,7 +130,7 @@ require 'English'
138
130
  #
139
131
  # Each HTML element has a corresponding method for generating that
140
132
  # element as a String. The name of this method is the same as that
141
- # of the element, all lowercase. The attributes of the element are
133
+ # of the element, all lowercase. The attributes of the element are
142
134
  # passed in as a hash, and the body as a no-argument block that evaluates
143
135
  # to a String. The HTML generation module knows which elements are
144
136
  # always empty, and silently drops any passed-in body. It also knows
@@ -152,57 +144,57 @@ require 'English'
152
144
  # as arguments, rather than via a hash.
153
145
  #
154
146
  # == Examples of use
155
- #
147
+ #
156
148
  # === Get form values
157
- #
149
+ #
158
150
  # require "cgi"
159
151
  # cgi = CGI.new
160
152
  # value = cgi['field_name'] # <== value string for 'field_name'
161
153
  # # if not 'field_name' included, then return "".
162
154
  # fields = cgi.keys # <== array of field names
163
- #
155
+ #
164
156
  # # returns true if form has 'field_name'
165
157
  # cgi.has_key?('field_name')
166
158
  # cgi.has_key?('field_name')
167
159
  # cgi.include?('field_name')
168
- #
169
- # CAUTION! cgi['field_name'] returned an Array with the old
160
+ #
161
+ # CAUTION! cgi['field_name'] returned an Array with the old
170
162
  # cgi.rb(included in ruby 1.6)
171
- #
163
+ #
172
164
  # === Get form values as hash
173
- #
165
+ #
174
166
  # require "cgi"
175
167
  # cgi = CGI.new
176
168
  # params = cgi.params
177
- #
169
+ #
178
170
  # cgi.params is a hash.
179
- #
171
+ #
180
172
  # cgi.params['new_field_name'] = ["value"] # add new param
181
173
  # cgi.params['field_name'] = ["new_value"] # change value
182
174
  # cgi.params.delete('field_name') # delete param
183
175
  # cgi.params.clear # delete all params
184
- #
185
- #
176
+ #
177
+ #
186
178
  # === Save form values to file
187
- #
179
+ #
188
180
  # require "pstore"
189
181
  # db = PStore.new("query.db")
190
182
  # db.transaction do
191
183
  # db["params"] = cgi.params
192
184
  # end
193
- #
194
- #
185
+ #
186
+ #
195
187
  # === Restore form values from file
196
- #
188
+ #
197
189
  # require "pstore"
198
190
  # db = PStore.new("query.db")
199
191
  # db.transaction do
200
192
  # cgi.params = db["params"]
201
193
  # end
202
- #
203
- #
194
+ #
195
+ #
204
196
  # === Get multipart form values
205
- #
197
+ #
206
198
  # require "cgi"
207
199
  # cgi = CGI.new
208
200
  # value = cgi['field_name'] # <== value string for 'field_name'
@@ -210,2124 +202,77 @@ require 'English'
210
202
  # value.local_path # <== path to local file of value
211
203
  # value.original_filename # <== original filename of value
212
204
  # value.content_type # <== content_type of value
213
- #
205
+ #
214
206
  # and value has StringIO or Tempfile class methods.
215
- #
207
+ #
216
208
  # === Get cookie values
217
- #
209
+ #
218
210
  # require "cgi"
219
211
  # cgi = CGI.new
220
212
  # values = cgi.cookies['name'] # <== array of 'name'
221
213
  # # if not 'name' included, then return [].
222
214
  # names = cgi.cookies.keys # <== array of cookie names
223
- #
215
+ #
224
216
  # and cgi.cookies is a hash.
225
- #
217
+ #
226
218
  # === Get cookie objects
227
- #
219
+ #
228
220
  # require "cgi"
229
221
  # cgi = CGI.new
230
222
  # for name, cookie in cgi.cookies
231
223
  # cookie.expires = Time.now + 30
232
224
  # end
233
225
  # cgi.out("cookie" => cgi.cookies) {"string"}
234
- #
226
+ #
235
227
  # cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
236
- #
228
+ #
237
229
  # require "cgi"
238
230
  # cgi = CGI.new
239
231
  # cgi.cookies['name'].expires = Time.now + 30
240
232
  # cgi.out("cookie" => cgi.cookies['name']) {"string"}
241
- #
233
+ #
242
234
  # === Print http header and html string to $DEFAULT_OUTPUT ($>)
243
- #
235
+ #
244
236
  # require "cgi"
245
- # cgi = CGI.new("html3") # add HTML generation methods
246
- # cgi.out() do
247
- # cgi.html() do
248
- # cgi.head{ cgi.title{"TITLE"} } +
249
- # cgi.body() do
250
- # cgi.form() do
251
- # cgi.textarea("get_text") +
252
- # cgi.br +
253
- # cgi.submit
237
+ # cgi = CGI.new("html4") # add HTML generation methods
238
+ # cgi.out do
239
+ # cgi.html do
240
+ # cgi.head do
241
+ # cgi.title { "TITLE" }
242
+ # end +
243
+ # cgi.body do
244
+ # cgi.form("ACTION" => "uri") do
245
+ # cgi.p do
246
+ # cgi.textarea("get_text") +
247
+ # cgi.br +
248
+ # cgi.submit
249
+ # end
254
250
  # end +
255
- # cgi.pre() do
251
+ # cgi.pre do
256
252
  # CGI::escapeHTML(
257
- # "params: " + cgi.params.inspect + "\n" +
258
- # "cookies: " + cgi.cookies.inspect + "\n" +
259
- # ENV.collect() do |key, value|
260
- # key + " --> " + value + "\n"
253
+ # "params: #{cgi.params.inspect}\n" +
254
+ # "cookies: #{cgi.cookies.inspect}\n" +
255
+ # ENV.collect do |key, value|
256
+ # "#{key} --> #{value}\n"
261
257
  # end.join("")
262
258
  # )
263
259
  # end
264
260
  # end
265
261
  # end
266
262
  # end
267
- #
263
+ #
268
264
  # # add HTML generation methods
269
265
  # CGI.new("html3") # html3.2
270
266
  # CGI.new("html4") # html4.01 (Strict)
271
267
  # CGI.new("html4Tr") # html4.01 Transitional
272
268
  # CGI.new("html4Fr") # html4.01 Frameset
269
+ # CGI.new("html5") # html5
273
270
  #
274
- class CGI
275
-
276
- # :stopdoc:
277
-
278
- # String for carriage return
279
- CR = "\015"
280
-
281
- # String for linefeed
282
- LF = "\012"
283
-
284
- # Standard internet newline sequence
285
- EOL = CR + LF
286
-
287
- REVISION = '$Id: cgi.rb 17817 2008-07-02 10:06:58Z shyouhei $' #:nodoc:
288
-
289
- NEEDS_BINMODE = true if /WIN/ni.match(RUBY_PLATFORM)
290
-
291
- # Path separators in different environments.
292
- PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
293
-
294
- # HTTP status codes.
295
- HTTP_STATUS = {
296
- "OK" => "200 OK",
297
- "PARTIAL_CONTENT" => "206 Partial Content",
298
- "MULTIPLE_CHOICES" => "300 Multiple Choices",
299
- "MOVED" => "301 Moved Permanently",
300
- "REDIRECT" => "302 Found",
301
- "NOT_MODIFIED" => "304 Not Modified",
302
- "BAD_REQUEST" => "400 Bad Request",
303
- "AUTH_REQUIRED" => "401 Authorization Required",
304
- "FORBIDDEN" => "403 Forbidden",
305
- "NOT_FOUND" => "404 Not Found",
306
- "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
307
- "NOT_ACCEPTABLE" => "406 Not Acceptable",
308
- "LENGTH_REQUIRED" => "411 Length Required",
309
- "PRECONDITION_FAILED" => "412 Rrecondition Failed",
310
- "SERVER_ERROR" => "500 Internal Server Error",
311
- "NOT_IMPLEMENTED" => "501 Method Not Implemented",
312
- "BAD_GATEWAY" => "502 Bad Gateway",
313
- "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"
314
- }
315
-
316
- # Abbreviated day-of-week names specified by RFC 822
317
- RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
318
-
319
- # Abbreviated month names specified by RFC 822
320
- RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
321
-
322
- # :startdoc:
323
-
324
- def env_table
325
- ENV
326
- end
327
-
328
- def stdinput
329
- $stdin
330
- end
331
-
332
- def stdoutput
333
- $DEFAULT_OUTPUT
334
- end
335
-
336
- private :env_table, :stdinput, :stdoutput
337
-
338
- # URL-encode a string.
339
- # url_encoded_string = CGI::escape("'Stop!' said Fred")
340
- # # => "%27Stop%21%27+said+Fred"
341
- def CGI::escape(string)
342
- string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
343
- '%' + $1.unpack('H2' * $1.size).join('%').upcase
344
- end.tr(' ', '+')
345
- end
346
-
347
-
348
- # URL-decode a string.
349
- # string = CGI::unescape("%27Stop%21%27+said+Fred")
350
- # # => "'Stop!' said Fred"
351
- def CGI::unescape(string)
352
- string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
353
- [$1.delete('%')].pack('H*')
354
- end
355
- end
356
-
357
-
358
- # Escape special characters in HTML, namely &\"<>
359
- # CGI::escapeHTML('Usage: foo "bar" <baz>')
360
- # # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
361
- def CGI::escapeHTML(string)
362
- string.gsub(/&/n, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
363
- end
364
-
365
-
366
- # Unescape a string that has been HTML-escaped
367
- # CGI::unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
368
- # # => "Usage: foo \"bar\" <baz>"
369
- def CGI::unescapeHTML(string)
370
- string.gsub(/&(amp|quot|gt|lt|\#[0-9]+|\#x[0-9A-Fa-f]+);/n) do
371
- match = $1.dup
372
- case match
373
- when 'amp' then '&'
374
- when 'quot' then '"'
375
- when 'gt' then '>'
376
- when 'lt' then '<'
377
- when /\A#0*(\d+)\z/n then
378
- if Integer($1) < 256
379
- Integer($1).chr
380
- else
381
- if Integer($1) < 65536 and ($KCODE[0] == ?u or $KCODE[0] == ?U)
382
- [Integer($1)].pack("U")
383
- else
384
- "&##{$1};"
385
- end
386
- end
387
- when /\A#x([0-9a-f]+)\z/ni then
388
- if $1.hex < 256
389
- $1.hex.chr
390
- else
391
- if $1.hex < 65536 and ($KCODE[0] == ?u or $KCODE[0] == ?U)
392
- [$1.hex].pack("U")
393
- else
394
- "&#x#{$1};"
395
- end
396
- end
397
- else
398
- "&#{match};"
399
- end
400
- end
401
- end
402
-
403
-
404
- # Escape only the tags of certain HTML elements in +string+.
405
- #
406
- # Takes an element or elements or array of elements. Each element
407
- # is specified by the name of the element, without angle brackets.
408
- # This matches both the start and the end tag of that element.
409
- # The attribute list of the open tag will also be escaped (for
410
- # instance, the double-quotes surrounding attribute values).
411
- #
412
- # print CGI::escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
413
- # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
414
- #
415
- # print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
416
- # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
417
- def CGI::escapeElement(string, *elements)
418
- elements = elements[0] if elements[0].kind_of?(Array)
419
- unless elements.empty?
420
- string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/ni) do
421
- CGI::escapeHTML($&)
422
- end
423
- else
424
- string
425
- end
426
- end
427
-
428
-
429
- # Undo escaping such as that done by CGI::escapeElement()
430
- #
431
- # print CGI::unescapeElement(
432
- # CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
433
- # # "&lt;BR&gt;<A HREF="url"></A>"
434
- #
435
- # print CGI::unescapeElement(
436
- # CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
437
- # # "&lt;BR&gt;<A HREF="url"></A>"
438
- def CGI::unescapeElement(string, *elements)
439
- elements = elements[0] if elements[0].kind_of?(Array)
440
- unless elements.empty?
441
- string.gsub(/&lt;\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?&gt;/ni) do
442
- CGI::unescapeHTML($&)
443
- end
444
- else
445
- string
446
- end
447
- end
448
-
449
-
450
- # Format a +Time+ object as a String using the format specified by RFC 1123.
451
- #
452
- # CGI::rfc1123_date(Time.now)
453
- # # Sat, 01 Jan 2000 00:00:00 GMT
454
- def CGI::rfc1123_date(time)
455
- t = time.clone.gmtime
456
- return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
457
- RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
458
- t.hour, t.min, t.sec)
459
- end
460
-
461
-
462
- # Create an HTTP header block as a string.
463
- #
464
- # Includes the empty line that ends the header block.
465
- #
466
- # +options+ can be a string specifying the Content-Type (defaults
467
- # to text/html), or a hash of header key/value pairs. The following
468
- # header keys are recognized:
469
- #
470
- # type:: the Content-Type header. Defaults to "text/html"
471
- # charset:: the charset of the body, appended to the Content-Type header.
472
- # nph:: a boolean value. If true, prepend protocol string and status code, and
473
- # date; and sets default values for "server" and "connection" if not
474
- # explicitly set.
475
- # status:: the HTTP status code, returned as the Status header. See the
476
- # list of available status codes below.
477
- # server:: the server software, returned as the Server header.
478
- # connection:: the connection type, returned as the Connection header (for
479
- # instance, "close".
480
- # length:: the length of the content that will be sent, returned as the
481
- # Content-Length header.
482
- # language:: the language of the content, returned as the Content-Language
483
- # header.
484
- # expires:: the time on which the current content expires, as a +Time+
485
- # object, returned as the Expires header.
486
- # cookie:: a cookie or cookies, returned as one or more Set-Cookie headers.
487
- # The value can be the literal string of the cookie; a CGI::Cookie
488
- # object; an Array of literal cookie strings or Cookie objects; or a
489
- # hash all of whose values are literal cookie strings or Cookie objects.
490
- # These cookies are in addition to the cookies held in the
491
- # @output_cookies field.
492
- #
493
- # Other header lines can also be set; they are appended as key: value.
494
- #
495
- # header
496
- # # Content-Type: text/html
497
- #
498
- # header("text/plain")
499
- # # Content-Type: text/plain
500
- #
501
- # header("nph" => true,
502
- # "status" => "OK", # == "200 OK"
503
- # # "status" => "200 GOOD",
504
- # "server" => ENV['SERVER_SOFTWARE'],
505
- # "connection" => "close",
506
- # "type" => "text/html",
507
- # "charset" => "iso-2022-jp",
508
- # # Content-Type: text/html; charset=iso-2022-jp
509
- # "length" => 103,
510
- # "language" => "ja",
511
- # "expires" => Time.now + 30,
512
- # "cookie" => [cookie1, cookie2],
513
- # "my_header1" => "my_value"
514
- # "my_header2" => "my_value")
515
- #
516
- # The status codes are:
517
- #
518
- # "OK" --> "200 OK"
519
- # "PARTIAL_CONTENT" --> "206 Partial Content"
520
- # "MULTIPLE_CHOICES" --> "300 Multiple Choices"
521
- # "MOVED" --> "301 Moved Permanently"
522
- # "REDIRECT" --> "302 Found"
523
- # "NOT_MODIFIED" --> "304 Not Modified"
524
- # "BAD_REQUEST" --> "400 Bad Request"
525
- # "AUTH_REQUIRED" --> "401 Authorization Required"
526
- # "FORBIDDEN" --> "403 Forbidden"
527
- # "NOT_FOUND" --> "404 Not Found"
528
- # "METHOD_NOT_ALLOWED" --> "405 Method Not Allowed"
529
- # "NOT_ACCEPTABLE" --> "406 Not Acceptable"
530
- # "LENGTH_REQUIRED" --> "411 Length Required"
531
- # "PRECONDITION_FAILED" --> "412 Precondition Failed"
532
- # "SERVER_ERROR" --> "500 Internal Server Error"
533
- # "NOT_IMPLEMENTED" --> "501 Method Not Implemented"
534
- # "BAD_GATEWAY" --> "502 Bad Gateway"
535
- # "VARIANT_ALSO_VARIES" --> "506 Variant Also Negotiates"
536
- #
537
- # This method does not perform charset conversion.
538
- #
539
- def header(options = "text/html")
540
-
541
- buf = ""
542
-
543
- case options
544
- when String
545
- options = { "type" => options }
546
- when Hash
547
- options = options.dup
548
- end
549
-
550
- unless options.has_key?("type")
551
- options["type"] = "text/html"
552
- end
553
-
554
- if options.has_key?("charset")
555
- options["type"] += "; charset=" + options.delete("charset")
556
- end
557
-
558
- options.delete("nph") if defined?(MOD_RUBY)
559
- if options.delete("nph") or
560
- (/IIS\/(\d+)/n.match(env_table['SERVER_SOFTWARE']) and $1.to_i < 5)
561
- buf += (env_table["SERVER_PROTOCOL"] or "HTTP/1.0") + " " +
562
- (HTTP_STATUS[options["status"]] or options["status"] or "200 OK") +
563
- EOL +
564
- "Date: " + CGI::rfc1123_date(Time.now) + EOL
565
-
566
- unless options.has_key?("server")
567
- options["server"] = (env_table['SERVER_SOFTWARE'] or "")
568
- end
569
-
570
- unless options.has_key?("connection")
571
- options["connection"] = "close"
572
- end
573
-
574
- options.delete("status")
575
- end
576
-
577
- if options.has_key?("status")
578
- buf += "Status: " +
579
- (HTTP_STATUS[options["status"]] or options["status"]) + EOL
580
- options.delete("status")
581
- end
582
-
583
- if options.has_key?("server")
584
- buf += "Server: " + options.delete("server") + EOL
585
- end
586
-
587
- if options.has_key?("connection")
588
- buf += "Connection: " + options.delete("connection") + EOL
589
- end
590
-
591
- buf += "Content-Type: " + options.delete("type") + EOL
592
-
593
- if options.has_key?("length")
594
- buf += "Content-Length: " + options.delete("length").to_s + EOL
595
- end
596
-
597
- if options.has_key?("language")
598
- buf += "Content-Language: " + options.delete("language") + EOL
599
- end
600
-
601
- if options.has_key?("expires")
602
- buf += "Expires: " + CGI::rfc1123_date( options.delete("expires") ) + EOL
603
- end
604
-
605
- if options.has_key?("cookie")
606
- if options["cookie"].kind_of?(String) or
607
- options["cookie"].kind_of?(Cookie)
608
- buf += "Set-Cookie: " + options.delete("cookie").to_s + EOL
609
- elsif options["cookie"].kind_of?(Array)
610
- options.delete("cookie").each{|cookie|
611
- buf += "Set-Cookie: " + cookie.to_s + EOL
612
- }
613
- elsif options["cookie"].kind_of?(Hash)
614
- options.delete("cookie").each_value{|cookie|
615
- buf += "Set-Cookie: " + cookie.to_s + EOL
616
- }
617
- end
618
- end
619
- if @output_cookies
620
- for cookie in @output_cookies
621
- buf += "Set-Cookie: " + cookie.to_s + EOL
622
- end
623
- end
624
-
625
- options.each{|key, value|
626
- buf += key + ": " + value.to_s + EOL
627
- }
628
-
629
- if defined?(MOD_RUBY)
630
- table = Apache::request.headers_out
631
- buf.scan(/([^:]+): (.+)#{EOL}/n){ |name, value|
632
- warn sprintf("name:%s value:%s\n", name, value) if $DEBUG
633
- case name
634
- when 'Set-Cookie'
635
- table.add(name, value)
636
- when /^status$/ni
637
- Apache::request.status_line = value
638
- Apache::request.status = value.to_i
639
- when /^content-type$/ni
640
- Apache::request.content_type = value
641
- when /^content-encoding$/ni
642
- Apache::request.content_encoding = value
643
- when /^location$/ni
644
- if Apache::request.status == 200
645
- Apache::request.status = 302
646
- end
647
- Apache::request.headers_out[name] = value
648
- else
649
- Apache::request.headers_out[name] = value
650
- end
651
- }
652
- Apache::request.send_http_header
653
- ''
654
- else
655
- buf + EOL
656
- end
657
-
658
- end # header()
659
-
660
-
661
- # Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
662
- #
663
- # The header is provided by +options+, as for #header().
664
- # The body of the document is that returned by the passed-
665
- # in block. This block takes no arguments. It is required.
666
- #
667
- # cgi = CGI.new
668
- # cgi.out{ "string" }
669
- # # Content-Type: text/html
670
- # # Content-Length: 6
671
- # #
672
- # # string
673
- #
674
- # cgi.out("text/plain") { "string" }
675
- # # Content-Type: text/plain
676
- # # Content-Length: 6
677
- # #
678
- # # string
679
- #
680
- # cgi.out("nph" => true,
681
- # "status" => "OK", # == "200 OK"
682
- # "server" => ENV['SERVER_SOFTWARE'],
683
- # "connection" => "close",
684
- # "type" => "text/html",
685
- # "charset" => "iso-2022-jp",
686
- # # Content-Type: text/html; charset=iso-2022-jp
687
- # "language" => "ja",
688
- # "expires" => Time.now + (3600 * 24 * 30),
689
- # "cookie" => [cookie1, cookie2],
690
- # "my_header1" => "my_value",
691
- # "my_header2" => "my_value") { "string" }
692
- #
693
- # Content-Length is automatically calculated from the size of
694
- # the String returned by the content block.
695
- #
696
- # If ENV['REQUEST_METHOD'] == "HEAD", then only the header
697
- # is outputted (the content block is still required, but it
698
- # is ignored).
699
- #
700
- # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then
701
- # the content is converted to this charset, and the language is set
702
- # to "ja".
703
- def out(options = "text/html") # :yield:
704
-
705
- options = { "type" => options } if options.kind_of?(String)
706
- content = yield
707
-
708
- if options.has_key?("charset")
709
- require "nkf"
710
- case options["charset"]
711
- when /iso-2022-jp/ni
712
- content = NKF::nkf('-m0 -x -j', content)
713
- options["language"] = "ja" unless options.has_key?("language")
714
- when /euc-jp/ni
715
- content = NKF::nkf('-m0 -x -e', content)
716
- options["language"] = "ja" unless options.has_key?("language")
717
- when /shift_jis/ni
718
- content = NKF::nkf('-m0 -x -s', content)
719
- options["language"] = "ja" unless options.has_key?("language")
720
- end
721
- end
722
-
723
- options["length"] = content.length.to_s
724
- output = stdoutput
725
- output.binmode if defined? output.binmode
726
- output.print header(options)
727
- output.print content unless "HEAD" == env_table['REQUEST_METHOD']
728
- end
729
-
730
-
731
- # Print an argument or list of arguments to the default output stream
732
- #
733
- # cgi = CGI.new
734
- # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
735
- def print(*options)
736
- stdoutput.print(*options)
737
- end
738
-
739
- require "delegate"
740
-
741
- # Class representing an HTTP cookie.
742
- #
743
- # In addition to its specific fields and methods, a Cookie instance
744
- # is a delegator to the array of its values.
745
- #
746
- # See RFC 2965.
747
- #
748
- # == Examples of use
749
- # cookie1 = CGI::Cookie::new("name", "value1", "value2", ...)
750
- # cookie1 = CGI::Cookie::new("name" => "name", "value" => "value")
751
- # cookie1 = CGI::Cookie::new('name' => 'name',
752
- # 'value' => ['value1', 'value2', ...],
753
- # 'path' => 'path', # optional
754
- # 'domain' => 'domain', # optional
755
- # 'expires' => Time.now, # optional
756
- # 'secure' => true # optional
757
- # )
758
- #
759
- # cgi.out("cookie" => [cookie1, cookie2]) { "string" }
760
- #
761
- # name = cookie1.name
762
- # values = cookie1.value
763
- # path = cookie1.path
764
- # domain = cookie1.domain
765
- # expires = cookie1.expires
766
- # secure = cookie1.secure
767
- #
768
- # cookie1.name = 'name'
769
- # cookie1.value = ['value1', 'value2', ...]
770
- # cookie1.path = 'path'
771
- # cookie1.domain = 'domain'
772
- # cookie1.expires = Time.now + 30
773
- # cookie1.secure = true
774
- class Cookie < DelegateClass(Array)
775
-
776
- # Create a new CGI::Cookie object.
777
- #
778
- # The contents of the cookie can be specified as a +name+ and one
779
- # or more +value+ arguments. Alternatively, the contents can
780
- # be specified as a single hash argument. The possible keywords of
781
- # this hash are as follows:
782
- #
783
- # name:: the name of the cookie. Required.
784
- # value:: the cookie's value or list of values.
785
- # path:: the path for which this cookie applies. Defaults to the
786
- # base directory of the CGI script.
787
- # domain:: the domain for which this cookie applies.
788
- # expires:: the time at which this cookie expires, as a +Time+ object.
789
- # secure:: whether this cookie is a secure cookie or not (default to
790
- # false). Secure cookies are only transmitted to HTTPS
791
- # servers.
792
- #
793
- # These keywords correspond to attributes of the cookie object.
794
- def initialize(name = "", *value)
795
- if name.kind_of?(String)
796
- @name = name
797
- @value = value
798
- %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
799
- @path = ($1 or "")
800
- @secure = false
801
- return super(@value)
802
- end
803
-
804
- options = name
805
- unless options.has_key?("name")
806
- raise ArgumentError, "`name' required"
807
- end
808
-
809
- @name = options["name"]
810
- @value = Array(options["value"])
811
- # simple support for IE
812
- if options["path"]
813
- @path = options["path"]
814
- else
815
- %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
816
- @path = ($1 or "")
817
- end
818
- @domain = options["domain"]
819
- @expires = options["expires"]
820
- @secure = options["secure"] == true ? true : false
821
-
822
- super(@value)
823
- end
824
-
825
- attr_accessor("name", "path", "domain", "expires")
826
- attr_reader("secure")
827
-
828
- def value=(val)
829
- @value = Array(val)
830
- replace(@value)
831
- end
832
-
833
- def value
834
- @value
835
- end
836
-
837
- # Set whether the Cookie is a secure cookie or not.
838
- #
839
- # +val+ must be a boolean.
840
- def secure=(val)
841
- @secure = val if val == true or val == false
842
- @secure
843
- end
844
-
845
- # Convert the Cookie to its string representation.
846
- def to_s
847
- buf = ""
848
- buf += @name + '='
849
-
850
- if @value.kind_of?(String)
851
- buf += CGI::escape(@value)
852
- else
853
- buf += @value.collect{|v| CGI::escape(v) }.join("&")
854
- end
855
-
856
- if @domain
857
- buf += '; domain=' + @domain
858
- end
859
-
860
- if @path
861
- buf += '; path=' + @path
862
- end
863
-
864
- if @expires
865
- buf += '; expires=' + CGI::rfc1123_date(@expires)
866
- end
867
-
868
- if @secure == true
869
- buf += '; secure'
870
- end
871
-
872
- buf
873
- end
874
-
875
- end # class Cookie
876
-
877
-
878
- # Parse a raw cookie string into a hash of cookie-name=>Cookie
879
- # pairs.
880
- #
881
- # cookies = CGI::Cookie::parse("raw_cookie_string")
882
- # # { "name1" => cookie1, "name2" => cookie2, ... }
883
- #
884
- def Cookie::parse(raw_cookie)
885
- cookies = Hash.new([])
886
- return cookies unless raw_cookie
887
-
888
- raw_cookie.split(/[;,]\s?/).each do |pairs|
889
- name, values = pairs.split('=',2)
890
- next unless name and values
891
- name = CGI::unescape(name)
892
- values ||= ""
893
- values = values.split('&').collect{|v| CGI::unescape(v) }
894
- if cookies.has_key?(name)
895
- values = cookies[name].value + values
896
- end
897
- cookies[name] = Cookie::new(name, *values)
898
- end
899
-
900
- cookies
901
- end
902
-
903
- # Parse an HTTP query string into a hash of key=>value pairs.
904
- #
905
- # params = CGI::parse("query_string")
906
- # # {"name1" => ["value1", "value2", ...],
907
- # # "name2" => ["value1", "value2", ...], ... }
908
- #
909
- def CGI::parse(query)
910
- params = Hash.new([].freeze)
911
271
 
912
- query.split(/[&;]/n).each do |pairs|
913
- key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) }
914
- if params.has_key?(key)
915
- params[key].push(value)
916
- else
917
- params[key] = [value]
918
- end
919
- end
920
-
921
- params
922
- end
923
-
924
- # Mixin module. It provides the follow functionality groups:
925
- #
926
- # 1. Access to CGI environment variables as methods. See
927
- # documentation to the CGI class for a list of these variables.
928
- #
929
- # 2. Access to cookies, including the cookies attribute.
930
- #
931
- # 3. Access to parameters, including the params attribute, and overloading
932
- # [] to perform parameter value lookup by key.
933
- #
934
- # 4. The initialize_query method, for initialising the above
935
- # mechanisms, handling multipart forms, and allowing the
936
- # class to be used in "offline" mode.
937
- #
938
- module QueryExtension
939
-
940
- %w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
941
- define_method(env.sub(/^HTTP_/n, '').downcase) do
942
- (val = env_table[env]) && Integer(val)
943
- end
944
- end
945
-
946
- %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
947
- PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
948
- REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
949
- SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
950
-
951
- HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
952
- HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
953
- HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
954
- define_method(env.sub(/^HTTP_/n, '').downcase) do
955
- env_table[env]
956
- end
957
- end
958
-
959
- # Get the raw cookies as a string.
960
- def raw_cookie
961
- env_table["HTTP_COOKIE"]
962
- end
963
-
964
- # Get the raw RFC2965 cookies as a string.
965
- def raw_cookie2
966
- env_table["HTTP_COOKIE2"]
967
- end
968
-
969
- # Get the cookies as a hash of cookie-name=>Cookie pairs.
970
- attr_accessor("cookies")
971
-
972
- # Get the parameters as a hash of name=>values pairs, where
973
- # values is an Array.
974
- attr("params")
975
-
976
- # Set all the parameters.
977
- def params=(hash)
978
- @params.clear
979
- @params.update(hash)
980
- end
981
-
982
- def read_multipart(boundary, content_length)
983
- params = Hash.new([])
984
- boundary = "--" + boundary
985
- quoted_boundary = Regexp.quote(boundary)
986
- buf = ""
987
- bufsize = 10 * 1024
988
- boundary_end=""
989
-
990
- # start multipart/form-data
991
- stdinput.binmode if defined? stdinput.binmode
992
- boundary_size = boundary.size + EOL.size
993
- content_length -= boundary_size
994
- status = stdinput.read(boundary_size)
995
- if nil == status
996
- raise EOFError, "no content body"
997
- elsif boundary + EOL != status
998
- raise EOFError, "bad content body"
999
- end
1000
-
1001
- loop do
1002
- head = nil
1003
- if 10240 < content_length
1004
- require "tempfile"
1005
- body = Tempfile.new("CGI")
1006
- else
1007
- begin
1008
- require "stringio"
1009
- body = StringIO.new
1010
- rescue LoadError
1011
- require "tempfile"
1012
- body = Tempfile.new("CGI")
1013
- end
1014
- end
1015
- body.binmode if defined? body.binmode
1016
-
1017
- until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
1018
-
1019
- if (not head) and /#{EOL}#{EOL}/n.match(buf)
1020
- buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
1021
- head = $1.dup
1022
- ""
1023
- end
1024
- next
1025
- end
1026
-
1027
- if head and ( (EOL + boundary + EOL).size < buf.size )
1028
- body.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
1029
- buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
1030
- end
1031
-
1032
- c = if bufsize < content_length
1033
- stdinput.read(bufsize)
1034
- else
1035
- stdinput.read(content_length)
1036
- end
1037
- if c.nil? || c.empty?
1038
- raise EOFError, "bad content body"
1039
- end
1040
- buf.concat(c)
1041
- content_length -= c.size
1042
- end
1043
-
1044
- buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
1045
- body.print $1
1046
- if "--" == $2
1047
- content_length = -1
1048
- end
1049
- boundary_end = $2.dup
1050
- ""
1051
- end
1052
-
1053
- body.rewind
1054
-
1055
- /Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;\s]*))/ni.match(head)
1056
- filename = ($1 or $2 or "")
1057
- if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
1058
- /Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
1059
- (not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
1060
- filename = CGI::unescape(filename)
1061
- end
1062
-
1063
- /Content-Type: ([\s]*)/ni.match(head)
1064
- content_type = ($1 or "")
1065
-
1066
- (class << body; self; end).class_eval do
1067
- alias local_path path
1068
- define_method(:original_filename) {filename.dup.taint}
1069
- define_method(:content_type) {content_type.dup.taint}
1070
- end
1071
-
1072
- /Content-Disposition:.* name="?([^\";\s]*)"?/ni.match(head)
1073
- name = $1.dup
1074
-
1075
- if params.has_key?(name)
1076
- params[name].push(body)
1077
- else
1078
- params[name] = [body]
1079
- end
1080
- break if buf.size == 0
1081
- break if content_length == -1
1082
- end
1083
- raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
1084
-
1085
- params
1086
- end # read_multipart
1087
- private :read_multipart
1088
-
1089
- # offline mode. read name=value pairs on standard input.
1090
- def read_from_cmdline
1091
- require "shellwords"
1092
-
1093
- string = unless ARGV.empty?
1094
- ARGV.join(' ')
1095
- else
1096
- if STDIN.tty?
1097
- STDERR.print(
1098
- %|(offline mode: enter name=value pairs on standard input)\n|
1099
- )
1100
- end
1101
- readlines.join(' ').gsub(/\n/n, '')
1102
- end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26')
1103
-
1104
- words = Shellwords.shellwords(string)
1105
-
1106
- if words.find{|x| /=/n.match(x) }
1107
- words.join('&')
1108
- else
1109
- words.join('+')
1110
- end
1111
- end
1112
- private :read_from_cmdline
1113
-
1114
- # Initialize the data from the query.
1115
- #
1116
- # Handles multipart forms (in particular, forms that involve file uploads).
1117
- # Reads query parameters in the @params field, and cookies into @cookies.
1118
- def initialize_query()
1119
- if ("POST" == env_table['REQUEST_METHOD']) and
1120
- %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(env_table['CONTENT_TYPE'])
1121
- boundary = $1.dup
1122
- @multipart = true
1123
- @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
1124
- else
1125
- @multipart = false
1126
- @params = CGI::parse(
1127
- case env_table['REQUEST_METHOD']
1128
- when "GET", "HEAD"
1129
- if defined?(MOD_RUBY)
1130
- Apache::request.args or ""
1131
- else
1132
- env_table['QUERY_STRING'] or ""
1133
- end
1134
- when "POST"
1135
- stdinput.binmode if defined? stdinput.binmode
1136
- stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
1137
- else
1138
- read_from_cmdline
1139
- end
1140
- )
1141
- end
1142
-
1143
- @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
1144
- end
1145
- private :initialize_query
1146
-
1147
- def multipart?
1148
- @multipart
1149
- end
1150
-
1151
- module Value # :nodoc:
1152
- def set_params(params)
1153
- @params = params
1154
- end
1155
- def [](idx, *args)
1156
- if args.size == 0
1157
- warn "#{caller(1)[0]}:CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key']"
1158
- @params[idx]
1159
- else
1160
- super[idx,*args]
1161
- end
1162
- end
1163
- def first
1164
- warn "#{caller(1)[0]}:CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key']"
1165
- self
1166
- end
1167
- alias last first
1168
- def to_a
1169
- @params || [self]
1170
- end
1171
- alias to_ary to_a # to be rhs of multiple assignment
1172
- end
1173
-
1174
- # Get the value for the parameter with a given key.
1175
- #
1176
- # If the parameter has multiple values, only the first will be
1177
- # retrieved; use #params() to get the array of values.
1178
- def [](key)
1179
- params = @params[key]
1180
- return '' unless params
1181
- value = params[0]
1182
- if @multipart
1183
- if value
1184
- return value
1185
- elsif defined? StringIO
1186
- StringIO.new("")
1187
- else
1188
- Tempfile.new("CGI")
1189
- end
1190
- else
1191
- str = if value then value.dup else "" end
1192
- str.extend(Value)
1193
- str.set_params(params)
1194
- str
1195
- end
1196
- end
1197
-
1198
- # Return all parameter keys as an array.
1199
- def keys(*args)
1200
- @params.keys(*args)
1201
- end
1202
-
1203
- # Returns true if a given parameter key exists in the query.
1204
- def has_key?(*args)
1205
- @params.has_key?(*args)
1206
- end
1207
- alias key? has_key?
1208
- alias include? has_key?
1209
-
1210
- end # QueryExtension
1211
-
1212
-
1213
- # Prettify (indent) an HTML string.
1214
- #
1215
- # +string+ is the HTML string to indent. +shift+ is the indentation
1216
- # unit to use; it defaults to two spaces.
1217
- #
1218
- # print CGI::pretty("<HTML><BODY></BODY></HTML>")
1219
- # # <HTML>
1220
- # # <BODY>
1221
- # # </BODY>
1222
- # # </HTML>
1223
- #
1224
- # print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
1225
- # # <HTML>
1226
- # # <BODY>
1227
- # # </BODY>
1228
- # # </HTML>
1229
- #
1230
- def CGI::pretty(string, shift = " ")
1231
- lines = string.gsub(/(?!\A)<(?:.|\n)*?>/n, "\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/n, "\\0\n")
1232
- end_pos = 0
1233
- while end_pos = lines.index(/^<\/(\w+)/n, end_pos)
1234
- element = $1.dup
1235
- start_pos = lines.rindex(/^\s*<#{element}/ni, end_pos)
1236
- lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/n, "\n" + shift) + "__"
1237
- end
1238
- lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/n, '\1')
1239
- end
1240
-
1241
-
1242
- # Base module for HTML-generation mixins.
1243
- #
1244
- # Provides methods for code generation for tags following
1245
- # the various DTD element types.
1246
- module TagMaker # :nodoc:
1247
- extend self
1248
-
1249
- # Generate code for an element with required start and end tags.
1250
- #
1251
- # - -
1252
- def nn_element_def(element)
1253
- nOE_element_def(element, <<-END)
1254
- if block_given?
1255
- yield.to_s
1256
- else
1257
- ""
1258
- end +
1259
- "</#{element.upcase}>"
1260
- END
1261
- end
1262
-
1263
- # Generate code for an empty element.
1264
- #
1265
- # - O EMPTY
1266
- def nOE_element_def(element, append = nil)
1267
- s = <<-END
1268
- "<#{element.upcase}" + attributes.collect{|name, value|
1269
- next unless value
1270
- " " + CGI::escapeHTML(name) +
1271
- if true == value
1272
- ""
1273
- else
1274
- '="' + CGI::escapeHTML(value) + '"'
1275
- end
1276
- }.to_s + ">"
1277
- END
1278
- s.sub!(/\Z/, " +") << append if append
1279
- s
1280
- end
1281
-
1282
- # Generate code for an element for which the end (and possibly the
1283
- # start) tag is optional.
1284
- #
1285
- # O O or - O
1286
- def nO_element_def(element)
1287
- nOE_element_def(element, <<-END)
1288
- if block_given?
1289
- yield.to_s + "</#{element.upcase}>"
1290
- else
1291
- ""
1292
- end
1293
- END
1294
- end
1295
-
1296
- end # TagMaker
1297
-
1298
-
1299
- #
1300
- # Mixin module providing HTML generation methods.
1301
- #
1302
- # For example,
1303
- # cgi.a("http://www.example.com") { "Example" }
1304
- # # => "<A HREF=\"http://www.example.com\">Example</A>"
1305
- #
1306
- # Modules Http3, Http4, etc., contain more basic HTML-generation methods
1307
- # (:title, :center, etc.).
1308
- #
1309
- # See class CGI for a detailed example.
1310
- #
1311
- module HtmlExtension
1312
-
1313
-
1314
- # Generate an Anchor element as a string.
1315
- #
1316
- # +href+ can either be a string, giving the URL
1317
- # for the HREF attribute, or it can be a hash of
1318
- # the element's attributes.
1319
- #
1320
- # The body of the element is the string returned by the no-argument
1321
- # block passed in.
1322
- #
1323
- # a("http://www.example.com") { "Example" }
1324
- # # => "<A HREF=\"http://www.example.com\">Example</A>"
1325
- #
1326
- # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" }
1327
- # # => "<A HREF=\"http://www.example.com\" TARGET=\"_top\">Example</A>"
1328
- #
1329
- def a(href = "") # :yield:
1330
- attributes = if href.kind_of?(String)
1331
- { "HREF" => href }
1332
- else
1333
- href
1334
- end
1335
- if block_given?
1336
- super(attributes){ yield }
1337
- else
1338
- super(attributes)
1339
- end
1340
- end
1341
-
1342
- # Generate a Document Base URI element as a String.
1343
- #
1344
- # +href+ can either by a string, giving the base URL for the HREF
1345
- # attribute, or it can be a has of the element's attributes.
1346
- #
1347
- # The passed-in no-argument block is ignored.
1348
- #
1349
- # base("http://www.example.com/cgi")
1350
- # # => "<BASE HREF=\"http://www.example.com/cgi\">"
1351
- def base(href = "") # :yield:
1352
- attributes = if href.kind_of?(String)
1353
- { "HREF" => href }
1354
- else
1355
- href
1356
- end
1357
- if block_given?
1358
- super(attributes){ yield }
1359
- else
1360
- super(attributes)
1361
- end
1362
- end
1363
-
1364
- # Generate a BlockQuote element as a string.
1365
- #
1366
- # +cite+ can either be a string, give the URI for the source of
1367
- # the quoted text, or a hash, giving all attributes of the element,
1368
- # or it can be omitted, in which case the element has no attributes.
1369
- #
1370
- # The body is provided by the passed-in no-argument block
1371
- #
1372
- # blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
1373
- # #=> "<BLOCKQUOTE CITE=\"http://www.example.com/quotes/foo.html\">Foo!</BLOCKQUOTE>
1374
- def blockquote(cite = nil) # :yield:
1375
- attributes = if cite.kind_of?(String)
1376
- { "CITE" => cite }
1377
- else
1378
- cite or ""
1379
- end
1380
- if block_given?
1381
- super(attributes){ yield }
1382
- else
1383
- super(attributes)
1384
- end
1385
- end
1386
-
1387
-
1388
- # Generate a Table Caption element as a string.
1389
- #
1390
- # +align+ can be a string, giving the alignment of the caption
1391
- # (one of top, bottom, left, or right). It can be a hash of
1392
- # all the attributes of the element. Or it can be omitted.
1393
- #
1394
- # The body of the element is provided by the passed-in no-argument block.
1395
- #
1396
- # caption("left") { "Capital Cities" }
1397
- # # => <CAPTION ALIGN=\"left\">Capital Cities</CAPTION>
1398
- def caption(align = nil) # :yield:
1399
- attributes = if align.kind_of?(String)
1400
- { "ALIGN" => align }
1401
- else
1402
- align or ""
1403
- end
1404
- if block_given?
1405
- super(attributes){ yield }
1406
- else
1407
- super(attributes)
1408
- end
1409
- end
1410
-
1411
-
1412
- # Generate a Checkbox Input element as a string.
1413
- #
1414
- # The attributes of the element can be specified as three arguments,
1415
- # +name+, +value+, and +checked+. +checked+ is a boolean value;
1416
- # if true, the CHECKED attribute will be included in the element.
1417
- #
1418
- # Alternatively, the attributes can be specified as a hash.
1419
- #
1420
- # checkbox("name")
1421
- # # = checkbox("NAME" => "name")
1422
- #
1423
- # checkbox("name", "value")
1424
- # # = checkbox("NAME" => "name", "VALUE" => "value")
1425
- #
1426
- # checkbox("name", "value", true)
1427
- # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true)
1428
- def checkbox(name = "", value = nil, checked = nil)
1429
- attributes = if name.kind_of?(String)
1430
- { "TYPE" => "checkbox", "NAME" => name,
1431
- "VALUE" => value, "CHECKED" => checked }
1432
- else
1433
- name["TYPE"] = "checkbox"
1434
- name
1435
- end
1436
- input(attributes)
1437
- end
1438
-
1439
- # Generate a sequence of checkbox elements, as a String.
1440
- #
1441
- # The checkboxes will all have the same +name+ attribute.
1442
- # Each checkbox is followed by a label.
1443
- # There will be one checkbox for each value. Each value
1444
- # can be specified as a String, which will be used both
1445
- # as the value of the VALUE attribute and as the label
1446
- # for that checkbox. A single-element array has the
1447
- # same effect.
1448
- #
1449
- # Each value can also be specified as a three-element array.
1450
- # The first element is the VALUE attribute; the second is the
1451
- # label; and the third is a boolean specifying whether this
1452
- # checkbox is CHECKED.
1453
- #
1454
- # Each value can also be specified as a two-element
1455
- # array, by omitting either the value element (defaults
1456
- # to the same as the label), or the boolean checked element
1457
- # (defaults to false).
1458
- #
1459
- # checkbox_group("name", "foo", "bar", "baz")
1460
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
1461
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="bar">bar
1462
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
1463
- #
1464
- # checkbox_group("name", ["foo"], ["bar", true], "baz")
1465
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
1466
- # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="bar">bar
1467
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
1468
- #
1469
- # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
1470
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="1">Foo
1471
- # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="2">Bar
1472
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="Baz">Baz
1473
- #
1474
- # checkbox_group("NAME" => "name",
1475
- # "VALUES" => ["foo", "bar", "baz"])
1476
- #
1477
- # checkbox_group("NAME" => "name",
1478
- # "VALUES" => [["foo"], ["bar", true], "baz"])
1479
- #
1480
- # checkbox_group("NAME" => "name",
1481
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
1482
- def checkbox_group(name = "", *values)
1483
- if name.kind_of?(Hash)
1484
- values = name["VALUES"]
1485
- name = name["NAME"]
1486
- end
1487
- values.collect{|value|
1488
- if value.kind_of?(String)
1489
- checkbox(name, value) + value
1490
- else
1491
- if value[value.size - 1] == true
1492
- checkbox(name, value[0], true) +
1493
- value[value.size - 2]
1494
- elsif value[value.size - 1] == false
1495
- checkbox(name, value[0], false) +
1496
- value[value.size - 2]
1497
- else
1498
- checkbox(name, value[0]) +
1499
- value[value.size - 1]
1500
- end
1501
- end
1502
- }.to_s
1503
- end
1504
-
1505
-
1506
- # Generate an File Upload Input element as a string.
1507
- #
1508
- # The attributes of the element can be specified as three arguments,
1509
- # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length
1510
- # of the file's _name_, not of the file's _contents_.
1511
- #
1512
- # Alternatively, the attributes can be specified as a hash.
1513
- #
1514
- # See #multipart_form() for forms that include file uploads.
1515
- #
1516
- # file_field("name")
1517
- # # <INPUT TYPE="file" NAME="name" SIZE="20">
1518
- #
1519
- # file_field("name", 40)
1520
- # # <INPUT TYPE="file" NAME="name" SIZE="40">
1521
- #
1522
- # file_field("name", 40, 100)
1523
- # # <INPUT TYPE="file" NAME="name" SIZE="40" MAXLENGTH="100">
1524
- #
1525
- # file_field("NAME" => "name", "SIZE" => 40)
1526
- # # <INPUT TYPE="file" NAME="name" SIZE="40">
1527
- def file_field(name = "", size = 20, maxlength = nil)
1528
- attributes = if name.kind_of?(String)
1529
- { "TYPE" => "file", "NAME" => name,
1530
- "SIZE" => size.to_s }
1531
- else
1532
- name["TYPE"] = "file"
1533
- name["SIZE"] = name["SIZE"].to_s if name["SIZE"]
1534
- name["MAXLENGTH"] = name["MAXLENGTH"].to_s if name["MAXLENGTH"]
1535
- name
1536
- end
1537
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
1538
- input(attributes)
1539
- end
1540
-
1541
-
1542
- # Generate a Form element as a string.
1543
- #
1544
- # +method+ should be either "get" or "post", and defaults to the latter.
1545
- # +action+ defaults to the current CGI script name. +enctype+
1546
- # defaults to "application/x-www-form-urlencoded".
1547
- #
1548
- # Alternatively, the attributes can be specified as a hash.
1549
- #
1550
- # See also #multipart_form() for forms that include file uploads.
1551
- #
1552
- # form{ "string" }
1553
- # # <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
1554
- #
1555
- # form("get") { "string" }
1556
- # # <FORM METHOD="get" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
1557
- #
1558
- # form("get", "url") { "string" }
1559
- # # <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
1560
- #
1561
- # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" }
1562
- # # <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
1563
- def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded")
1564
- attributes = if method.kind_of?(String)
1565
- { "METHOD" => method, "ACTION" => action,
1566
- "ENCTYPE" => enctype }
1567
- else
1568
- unless method.has_key?("METHOD")
1569
- method["METHOD"] = "post"
1570
- end
1571
- unless method.has_key?("ENCTYPE")
1572
- method["ENCTYPE"] = enctype
1573
- end
1574
- method
1575
- end
1576
- if block_given?
1577
- body = yield
1578
- else
1579
- body = ""
1580
- end
1581
- if @output_hidden
1582
- body += @output_hidden.collect{|k,v|
1583
- "<INPUT TYPE=\"HIDDEN\" NAME=\"#{k}\" VALUE=\"#{v}\">"
1584
- }.to_s
1585
- end
1586
- super(attributes){body}
1587
- end
1588
-
1589
- # Generate a Hidden Input element as a string.
1590
- #
1591
- # The attributes of the element can be specified as two arguments,
1592
- # +name+ and +value+.
1593
- #
1594
- # Alternatively, the attributes can be specified as a hash.
1595
- #
1596
- # hidden("name")
1597
- # # <INPUT TYPE="hidden" NAME="name">
1598
- #
1599
- # hidden("name", "value")
1600
- # # <INPUT TYPE="hidden" NAME="name" VALUE="value">
1601
- #
1602
- # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo")
1603
- # # <INPUT TYPE="hidden" NAME="name" VALUE="value" ID="foo">
1604
- def hidden(name = "", value = nil)
1605
- attributes = if name.kind_of?(String)
1606
- { "TYPE" => "hidden", "NAME" => name, "VALUE" => value }
1607
- else
1608
- name["TYPE"] = "hidden"
1609
- name
1610
- end
1611
- input(attributes)
1612
- end
1613
-
1614
- # Generate a top-level HTML element as a string.
1615
- #
1616
- # The attributes of the element are specified as a hash. The
1617
- # pseudo-attribute "PRETTY" can be used to specify that the generated
1618
- # HTML string should be indented. "PRETTY" can also be specified as
1619
- # a string as the sole argument to this method. The pseudo-attribute
1620
- # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it
1621
- # should include the entire text of this tag, including angle brackets.
1622
- #
1623
- # The body of the html element is supplied as a block.
1624
- #
1625
- # html{ "string" }
1626
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>string</HTML>
1627
- #
1628
- # html("LANG" => "ja") { "string" }
1629
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML LANG="ja">string</HTML>
1630
- #
1631
- # html("DOCTYPE" => false) { "string" }
1632
- # # <HTML>string</HTML>
1633
- #
1634
- # html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">') { "string" }
1635
- # # <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML>string</HTML>
1636
- #
1637
- # html("PRETTY" => " ") { "<BODY></BODY>" }
1638
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
1639
- # # <HTML>
1640
- # # <BODY>
1641
- # # </BODY>
1642
- # # </HTML>
1643
- #
1644
- # html("PRETTY" => "\t") { "<BODY></BODY>" }
1645
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
1646
- # # <HTML>
1647
- # # <BODY>
1648
- # # </BODY>
1649
- # # </HTML>
1650
- #
1651
- # html("PRETTY") { "<BODY></BODY>" }
1652
- # # = html("PRETTY" => " ") { "<BODY></BODY>" }
1653
- #
1654
- # html(if $VERBOSE then "PRETTY" end) { "HTML string" }
1655
- #
1656
- def html(attributes = {}) # :yield:
1657
- if nil == attributes
1658
- attributes = {}
1659
- elsif "PRETTY" == attributes
1660
- attributes = { "PRETTY" => true }
1661
- end
1662
- pretty = attributes.delete("PRETTY")
1663
- pretty = " " if true == pretty
1664
- buf = ""
1665
-
1666
- if attributes.has_key?("DOCTYPE")
1667
- if attributes["DOCTYPE"]
1668
- buf += attributes.delete("DOCTYPE")
1669
- else
1670
- attributes.delete("DOCTYPE")
1671
- end
1672
- else
1673
- buf += doctype
1674
- end
1675
-
1676
- if block_given?
1677
- buf += super(attributes){ yield }
1678
- else
1679
- buf += super(attributes)
1680
- end
1681
-
1682
- if pretty
1683
- CGI::pretty(buf, pretty)
1684
- else
1685
- buf
1686
- end
1687
-
1688
- end
1689
-
1690
- # Generate an Image Button Input element as a string.
1691
- #
1692
- # +src+ is the URL of the image to use for the button. +name+
1693
- # is the input name. +alt+ is the alternative text for the image.
1694
- #
1695
- # Alternatively, the attributes can be specified as a hash.
1696
- #
1697
- # image_button("url")
1698
- # # <INPUT TYPE="image" SRC="url">
1699
- #
1700
- # image_button("url", "name", "string")
1701
- # # <INPUT TYPE="image" SRC="url" NAME="name" ALT="string">
1702
- #
1703
- # image_button("SRC" => "url", "ATL" => "strng")
1704
- # # <INPUT TYPE="image" SRC="url" ALT="string">
1705
- def image_button(src = "", name = nil, alt = nil)
1706
- attributes = if src.kind_of?(String)
1707
- { "TYPE" => "image", "SRC" => src, "NAME" => name,
1708
- "ALT" => alt }
1709
- else
1710
- src["TYPE"] = "image"
1711
- src["SRC"] ||= ""
1712
- src
1713
- end
1714
- input(attributes)
1715
- end
1716
-
1717
-
1718
- # Generate an Image element as a string.
1719
- #
1720
- # +src+ is the URL of the image. +alt+ is the alternative text for
1721
- # the image. +width+ is the width of the image, and +height+ is
1722
- # its height.
1723
- #
1724
- # Alternatively, the attributes can be specified as a hash.
1725
- #
1726
- # img("src", "alt", 100, 50)
1727
- # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
1728
- #
1729
- # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50)
1730
- # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
1731
- def img(src = "", alt = "", width = nil, height = nil)
1732
- attributes = if src.kind_of?(String)
1733
- { "SRC" => src, "ALT" => alt }
1734
- else
1735
- src["WIDTH"] = src["WIDTH"].to_s if src["WIDTH"]
1736
- src["HEIGHT"] = src["HEIGHT"].to_s if src["HEIGHT"]
1737
- src
1738
- end
1739
- attributes["WIDTH"] = width.to_s if width
1740
- attributes["HEIGHT"] = height.to_s if height
1741
- super(attributes)
1742
- end
1743
-
1744
-
1745
- # Generate a Form element with multipart encoding as a String.
1746
- #
1747
- # Multipart encoding is used for forms that include file uploads.
1748
- #
1749
- # +action+ is the action to perform. +enctype+ is the encoding
1750
- # type, which defaults to "multipart/form-data".
1751
- #
1752
- # Alternatively, the attributes can be specified as a hash.
1753
- #
1754
- # multipart_form{ "string" }
1755
- # # <FORM METHOD="post" ENCTYPE="multipart/form-data">string</FORM>
1756
- #
1757
- # multipart_form("url") { "string" }
1758
- # # <FORM METHOD="post" ACTION="url" ENCTYPE="multipart/form-data">string</FORM>
1759
- def multipart_form(action = nil, enctype = "multipart/form-data")
1760
- attributes = if action == nil
1761
- { "METHOD" => "post", "ENCTYPE" => enctype }
1762
- elsif action.kind_of?(String)
1763
- { "METHOD" => "post", "ACTION" => action,
1764
- "ENCTYPE" => enctype }
1765
- else
1766
- unless action.has_key?("METHOD")
1767
- action["METHOD"] = "post"
1768
- end
1769
- unless action.has_key?("ENCTYPE")
1770
- action["ENCTYPE"] = enctype
1771
- end
1772
- action
1773
- end
1774
- if block_given?
1775
- form(attributes){ yield }
1776
- else
1777
- form(attributes)
1778
- end
1779
- end
1780
-
1781
-
1782
- # Generate a Password Input element as a string.
1783
- #
1784
- # +name+ is the name of the input field. +value+ is its default
1785
- # value. +size+ is the size of the input field display. +maxlength+
1786
- # is the maximum length of the inputted password.
1787
- #
1788
- # Alternatively, attributes can be specified as a hash.
1789
- #
1790
- # password_field("name")
1791
- # # <INPUT TYPE="password" NAME="name" SIZE="40">
1792
- #
1793
- # password_field("name", "value")
1794
- # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="40">
1795
- #
1796
- # password_field("password", "value", 80, 200)
1797
- # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
1798
- #
1799
- # password_field("NAME" => "name", "VALUE" => "value")
1800
- # # <INPUT TYPE="password" NAME="name" VALUE="value">
1801
- def password_field(name = "", value = nil, size = 40, maxlength = nil)
1802
- attributes = if name.kind_of?(String)
1803
- { "TYPE" => "password", "NAME" => name,
1804
- "VALUE" => value, "SIZE" => size.to_s }
1805
- else
1806
- name["TYPE"] = "password"
1807
- name
1808
- end
1809
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
1810
- input(attributes)
1811
- end
1812
-
1813
- # Generate a Select element as a string.
1814
- #
1815
- # +name+ is the name of the element. The +values+ are the options that
1816
- # can be selected from the Select menu. Each value can be a String or
1817
- # a one, two, or three-element Array. If a String or a one-element
1818
- # Array, this is both the value of that option and the text displayed for
1819
- # it. If a three-element Array, the elements are the option value, displayed
1820
- # text, and a boolean value specifying whether this option starts as selected.
1821
- # The two-element version omits either the option value (defaults to the same
1822
- # as the display text) or the boolean selected specifier (defaults to false).
1823
- #
1824
- # The attributes and options can also be specified as a hash. In this
1825
- # case, options are specified as an array of values as described above,
1826
- # with the hash key of "VALUES".
1827
- #
1828
- # popup_menu("name", "foo", "bar", "baz")
1829
- # # <SELECT NAME="name">
1830
- # # <OPTION VALUE="foo">foo</OPTION>
1831
- # # <OPTION VALUE="bar">bar</OPTION>
1832
- # # <OPTION VALUE="baz">baz</OPTION>
1833
- # # </SELECT>
1834
- #
1835
- # popup_menu("name", ["foo"], ["bar", true], "baz")
1836
- # # <SELECT NAME="name">
1837
- # # <OPTION VALUE="foo">foo</OPTION>
1838
- # # <OPTION VALUE="bar" SELECTED>bar</OPTION>
1839
- # # <OPTION VALUE="baz">baz</OPTION>
1840
- # # </SELECT>
1841
- #
1842
- # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
1843
- # # <SELECT NAME="name">
1844
- # # <OPTION VALUE="1">Foo</OPTION>
1845
- # # <OPTION SELECTED VALUE="2">Bar</OPTION>
1846
- # # <OPTION VALUE="Baz">Baz</OPTION>
1847
- # # </SELECT>
1848
- #
1849
- # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true,
1850
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
1851
- # # <SELECT NAME="name" MULTIPLE SIZE="2">
1852
- # # <OPTION VALUE="1">Foo</OPTION>
1853
- # # <OPTION SELECTED VALUE="2">Bar</OPTION>
1854
- # # <OPTION VALUE="Baz">Baz</OPTION>
1855
- # # </SELECT>
1856
- def popup_menu(name = "", *values)
1857
-
1858
- if name.kind_of?(Hash)
1859
- values = name["VALUES"]
1860
- size = name["SIZE"].to_s if name["SIZE"]
1861
- multiple = name["MULTIPLE"]
1862
- name = name["NAME"]
1863
- else
1864
- size = nil
1865
- multiple = nil
1866
- end
1867
-
1868
- select({ "NAME" => name, "SIZE" => size,
1869
- "MULTIPLE" => multiple }){
1870
- values.collect{|value|
1871
- if value.kind_of?(String)
1872
- option({ "VALUE" => value }){ value }
1873
- else
1874
- if value[value.size - 1] == true
1875
- option({ "VALUE" => value[0], "SELECTED" => true }){
1876
- value[value.size - 2]
1877
- }
1878
- else
1879
- option({ "VALUE" => value[0] }){
1880
- value[value.size - 1]
1881
- }
1882
- end
1883
- end
1884
- }.to_s
1885
- }
1886
-
1887
- end
1888
-
1889
- # Generates a radio-button Input element.
1890
- #
1891
- # +name+ is the name of the input field. +value+ is the value of
1892
- # the field if checked. +checked+ specifies whether the field
1893
- # starts off checked.
1894
- #
1895
- # Alternatively, the attributes can be specified as a hash.
1896
- #
1897
- # radio_button("name", "value")
1898
- # # <INPUT TYPE="radio" NAME="name" VALUE="value">
1899
- #
1900
- # radio_button("name", "value", true)
1901
- # # <INPUT TYPE="radio" NAME="name" VALUE="value" CHECKED>
1902
- #
1903
- # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo")
1904
- # # <INPUT TYPE="radio" NAME="name" VALUE="value" ID="foo">
1905
- def radio_button(name = "", value = nil, checked = nil)
1906
- attributes = if name.kind_of?(String)
1907
- { "TYPE" => "radio", "NAME" => name,
1908
- "VALUE" => value, "CHECKED" => checked }
1909
- else
1910
- name["TYPE"] = "radio"
1911
- name
1912
- end
1913
- input(attributes)
1914
- end
1915
-
1916
- # Generate a sequence of radio button Input elements, as a String.
1917
- #
1918
- # This works the same as #checkbox_group(). However, it is not valid
1919
- # to have more than one radiobutton in a group checked.
1920
- #
1921
- # radio_group("name", "foo", "bar", "baz")
1922
- # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
1923
- # # <INPUT TYPE="radio" NAME="name" VALUE="bar">bar
1924
- # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
1925
- #
1926
- # radio_group("name", ["foo"], ["bar", true], "baz")
1927
- # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
1928
- # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="bar">bar
1929
- # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
1930
- #
1931
- # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
1932
- # # <INPUT TYPE="radio" NAME="name" VALUE="1">Foo
1933
- # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="2">Bar
1934
- # # <INPUT TYPE="radio" NAME="name" VALUE="Baz">Baz
1935
- #
1936
- # radio_group("NAME" => "name",
1937
- # "VALUES" => ["foo", "bar", "baz"])
1938
- #
1939
- # radio_group("NAME" => "name",
1940
- # "VALUES" => [["foo"], ["bar", true], "baz"])
1941
- #
1942
- # radio_group("NAME" => "name",
1943
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
1944
- def radio_group(name = "", *values)
1945
- if name.kind_of?(Hash)
1946
- values = name["VALUES"]
1947
- name = name["NAME"]
1948
- end
1949
- values.collect{|value|
1950
- if value.kind_of?(String)
1951
- radio_button(name, value) + value
1952
- else
1953
- if value[value.size - 1] == true
1954
- radio_button(name, value[0], true) +
1955
- value[value.size - 2]
1956
- elsif value[value.size - 1] == false
1957
- radio_button(name, value[0], false) +
1958
- value[value.size - 2]
1959
- else
1960
- radio_button(name, value[0]) +
1961
- value[value.size - 1]
1962
- end
1963
- end
1964
- }.to_s
1965
- end
1966
-
1967
- # Generate a reset button Input element, as a String.
1968
- #
1969
- # This resets the values on a form to their initial values. +value+
1970
- # is the text displayed on the button. +name+ is the name of this button.
1971
- #
1972
- # Alternatively, the attributes can be specified as a hash.
1973
- #
1974
- # reset
1975
- # # <INPUT TYPE="reset">
1976
- #
1977
- # reset("reset")
1978
- # # <INPUT TYPE="reset" VALUE="reset">
1979
- #
1980
- # reset("VALUE" => "reset", "ID" => "foo")
1981
- # # <INPUT TYPE="reset" VALUE="reset" ID="foo">
1982
- def reset(value = nil, name = nil)
1983
- attributes = if (not value) or value.kind_of?(String)
1984
- { "TYPE" => "reset", "VALUE" => value, "NAME" => name }
1985
- else
1986
- value["TYPE"] = "reset"
1987
- value
1988
- end
1989
- input(attributes)
1990
- end
1991
-
1992
- alias scrolling_list popup_menu
1993
-
1994
- # Generate a submit button Input element, as a String.
1995
- #
1996
- # +value+ is the text to display on the button. +name+ is the name
1997
- # of the input.
1998
- #
1999
- # Alternatively, the attributes can be specified as a hash.
2000
- #
2001
- # submit
2002
- # # <INPUT TYPE="submit">
2003
- #
2004
- # submit("ok")
2005
- # # <INPUT TYPE="submit" VALUE="ok">
2006
- #
2007
- # submit("ok", "button1")
2008
- # # <INPUT TYPE="submit" VALUE="ok" NAME="button1">
2009
- #
2010
- # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo")
2011
- # # <INPUT TYPE="submit" VALUE="ok" NAME="button1" ID="foo">
2012
- def submit(value = nil, name = nil)
2013
- attributes = if (not value) or value.kind_of?(String)
2014
- { "TYPE" => "submit", "VALUE" => value, "NAME" => name }
2015
- else
2016
- value["TYPE"] = "submit"
2017
- value
2018
- end
2019
- input(attributes)
2020
- end
2021
-
2022
- # Generate a text field Input element, as a String.
2023
- #
2024
- # +name+ is the name of the input field. +value+ is its initial
2025
- # value. +size+ is the size of the input area. +maxlength+
2026
- # is the maximum length of input accepted.
2027
- #
2028
- # Alternatively, the attributes can be specified as a hash.
2029
- #
2030
- # text_field("name")
2031
- # # <INPUT TYPE="text" NAME="name" SIZE="40">
2032
- #
2033
- # text_field("name", "value")
2034
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="40">
2035
- #
2036
- # text_field("name", "value", 80)
2037
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80">
2038
- #
2039
- # text_field("name", "value", 80, 200)
2040
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
2041
- #
2042
- # text_field("NAME" => "name", "VALUE" => "value")
2043
- # # <INPUT TYPE="text" NAME="name" VALUE="value">
2044
- def text_field(name = "", value = nil, size = 40, maxlength = nil)
2045
- attributes = if name.kind_of?(String)
2046
- { "TYPE" => "text", "NAME" => name, "VALUE" => value,
2047
- "SIZE" => size.to_s }
2048
- else
2049
- name["TYPE"] = "text"
2050
- name
2051
- end
2052
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
2053
- input(attributes)
2054
- end
2055
-
2056
- # Generate a TextArea element, as a String.
2057
- #
2058
- # +name+ is the name of the textarea. +cols+ is the number of
2059
- # columns and +rows+ is the number of rows in the display.
2060
- #
2061
- # Alternatively, the attributes can be specified as a hash.
2062
- #
2063
- # The body is provided by the passed-in no-argument block
2064
- #
2065
- # textarea("name")
2066
- # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10)
2067
- #
2068
- # textarea("name", 40, 5)
2069
- # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5)
2070
- def textarea(name = "", cols = 70, rows = 10) # :yield:
2071
- attributes = if name.kind_of?(String)
2072
- { "NAME" => name, "COLS" => cols.to_s,
2073
- "ROWS" => rows.to_s }
2074
- else
2075
- name
2076
- end
2077
- if block_given?
2078
- super(attributes){ yield }
2079
- else
2080
- super(attributes)
2081
- end
2082
- end
2083
-
2084
- end # HtmlExtension
2085
-
2086
-
2087
- # Mixin module for HTML version 3 generation methods.
2088
- module Html3 # :nodoc:
2089
-
2090
- # The DOCTYPE declaration for this version of HTML
2091
- def doctype
2092
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">|
2093
- end
2094
-
2095
- # Initialise the HTML generation methods for this version.
2096
- def element_init
2097
- extend TagMaker
2098
- methods = ""
2099
- # - -
2100
- for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG
2101
- DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV center MAP
2102
- APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT table TITLE
2103
- STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE
2104
- CAPTION ]
2105
- methods += <<-BEGIN + nn_element_def(element) + <<-END
2106
- def #{element.downcase}(attributes = {})
2107
- BEGIN
2108
- end
2109
- END
2110
- end
2111
-
2112
- # - O EMPTY
2113
- for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
2114
- ISINDEX META ]
2115
- methods += <<-BEGIN + nOE_element_def(element) + <<-END
2116
- def #{element.downcase}(attributes = {})
2117
- BEGIN
2118
- end
2119
- END
2120
- end
2121
-
2122
- # O O or - O
2123
- for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr
2124
- th td ]
2125
- methods += <<-BEGIN + nO_element_def(element) + <<-END
2126
- def #{element.downcase}(attributes = {})
2127
- BEGIN
2128
- end
2129
- END
2130
- end
2131
- eval(methods)
2132
- end
2133
-
2134
- end # Html3
2135
-
2136
-
2137
- # Mixin module for HTML version 4 generation methods.
2138
- module Html4 # :nodoc:
2139
-
2140
- # The DOCTYPE declaration for this version of HTML
2141
- def doctype
2142
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">|
2143
- end
2144
-
2145
- def element_init
2146
- # did this is the module body
2147
- end
2148
-
2149
- # Initialise the HTML generation methods for this version.
2150
- def self.element_init_methods
2151
- methods = ""
2152
- # - -
2153
- for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD
2154
- VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
2155
- H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP
2156
- FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
2157
- TEXTAREA FORM A BLOCKQUOTE CAPTION ]
2158
- methods += <<-BEGIN + TagMaker.nn_element_def(element) + <<-END
2159
- def #{element.downcase}(attributes = {})
2160
- BEGIN
2161
- end
2162
- END
2163
- end
2164
-
2165
- # - O EMPTY
2166
- for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ]
2167
- methods += <<-BEGIN + TagMaker.nOE_element_def(element) + <<-END
2168
- def #{element.downcase}(attributes = {})
2169
- BEGIN
2170
- end
2171
- END
2172
- end
2173
-
2174
- # O O or - O
2175
- for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
2176
- COLGROUP TR TH TD HEAD]
2177
- methods += <<-BEGIN + TagMaker.nO_element_def(element) + <<-END
2178
- def #{element.downcase}(attributes = {})
2179
- BEGIN
2180
- end
2181
- END
2182
- end
2183
- eval(methods)
2184
- end
2185
-
2186
- element_init_methods()
2187
-
2188
- end # Html4
2189
-
2190
-
2191
- # Mixin module for HTML version 4 transitional generation methods.
2192
- module Html4Tr # :nodoc:
2193
-
2194
- # The DOCTYPE declaration for this version of HTML
2195
- def doctype
2196
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">|
2197
- end
2198
-
2199
- # Initialise the HTML generation methods for this version.
2200
- def element_init
2201
- extend TagMaker
2202
- methods = ""
2203
- # - -
2204
- for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN
2205
- CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO
2206
- ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q
2207
- INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET
2208
- LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT
2209
- NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ]
2210
- methods += <<-BEGIN + nn_element_def(element) + <<-END
2211
- def #{element.downcase}(attributes = {})
2212
- BEGIN
2213
- end
2214
- END
2215
- end
2216
-
2217
- # - O EMPTY
2218
- for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
2219
- COL ISINDEX META ]
2220
- methods += <<-BEGIN + nOE_element_def(element) + <<-END
2221
- def #{element.downcase}(attributes = {})
2222
- BEGIN
2223
- end
2224
- END
2225
- end
2226
-
2227
- # O O or - O
2228
- for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
2229
- COLGROUP TR TH TD HEAD ]
2230
- methods += <<-BEGIN + nO_element_def(element) + <<-END
2231
- def #{element.downcase}(attributes = {})
2232
- BEGIN
2233
- end
2234
- END
2235
- end
2236
- eval(methods)
2237
- end
2238
-
2239
- end # Html4Tr
2240
-
2241
-
2242
- # Mixin module for generating HTML version 4 with framesets.
2243
- module Html4Fr # :nodoc:
2244
-
2245
- # The DOCTYPE declaration for this version of HTML
2246
- def doctype
2247
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">|
2248
- end
2249
-
2250
- # Initialise the HTML generation methods for this version.
2251
- def element_init
2252
- methods = ""
2253
- # - -
2254
- for element in %w[ FRAMESET ]
2255
- methods += <<-BEGIN + nn_element_def(element) + <<-END
2256
- def #{element.downcase}(attributes = {})
2257
- BEGIN
2258
- end
2259
- END
2260
- end
2261
-
2262
- # - O EMPTY
2263
- for element in %w[ FRAME ]
2264
- methods += <<-BEGIN + nOE_element_def(element) + <<-END
2265
- def #{element.downcase}(attributes = {})
2266
- BEGIN
2267
- end
2268
- END
2269
- end
2270
- eval(methods)
2271
- end
2272
-
2273
- end # Html4Fr
2274
-
2275
-
2276
- # Creates a new CGI instance.
2277
- #
2278
- # +type+ specifies which version of HTML to load the HTML generation
2279
- # methods for. The following versions of HTML are supported:
2280
- #
2281
- # html3:: HTML 3.x
2282
- # html4:: HTML 4.0
2283
- # html4Tr:: HTML 4.0 Transitional
2284
- # html4Fr:: HTML 4.0 with Framesets
2285
- #
2286
- # If not specified, no HTML generation methods will be loaded.
2287
- #
2288
- # If the CGI object is not created in a standard CGI call environment
2289
- # (that is, it can't locate REQUEST_METHOD in its environment), then
2290
- # it will run in "offline" mode. In this mode, it reads its parameters
2291
- # from the command line or (failing that) from standard input. Otherwise,
2292
- # cookies and other parameters are parsed automatically from the standard
2293
- # CGI locations, which varies according to the REQUEST_METHOD.
2294
- def initialize(type = "query")
2295
- if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
2296
- Apache.request.setup_cgi_env
2297
- end
2298
-
2299
- extend QueryExtension
2300
- @multipart = false
2301
- if defined?(CGI_PARAMS)
2302
- warn "do not use CGI_PARAMS and CGI_COOKIES"
2303
- @params = CGI_PARAMS.dup
2304
- @cookies = CGI_COOKIES.dup
2305
- else
2306
- initialize_query() # set @params, @cookies
2307
- end
2308
- @output_cookies = nil
2309
- @output_hidden = nil
2310
-
2311
- case type
2312
- when "html3"
2313
- extend Html3
2314
- element_init()
2315
- extend HtmlExtension
2316
- when "html4"
2317
- extend Html4
2318
- element_init()
2319
- extend HtmlExtension
2320
- when "html4Tr"
2321
- extend Html4Tr
2322
- element_init()
2323
- extend HtmlExtension
2324
- when "html4Fr"
2325
- extend Html4Tr
2326
- element_init()
2327
- extend Html4Fr
2328
- element_init()
2329
- extend HtmlExtension
2330
- end
2331
- end
272
+ class CGI
273
+ end
2332
274
 
2333
- end # class CGI
275
+ require 'cgi/core'
276
+ require 'cgi/cookie'
277
+ require 'cgi/util'
278
+ CGI.autoload(:HtmlExtension, 'cgi/html')