rubysl-cgi 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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')