cgialt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1463 @@
1
+ ##
2
+ ## copyright(c) 2007 kuwata-lab.com all rights reserved.
3
+ ##
4
+ ## Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
5
+ ##
6
+ ## Copyright (C) 2000 Information-technology Promotion Agency, Japan
7
+ ##
8
+ ## Original Author: Wakou Aoyama <wakou@ruby-lang.org>
9
+ ##
10
+ ## Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
11
+ ##
12
+
13
+ raise "Please, use ruby 1.5.4 or later." if RUBY_VERSION < "1.5.4"
14
+
15
+ #*** original
16
+ #*require 'English'
17
+ #*** original
18
+
19
+ # CGI class. See documentation for the file cgi.rb for an overview
20
+ # of the CGI protocol.
21
+ #
22
+ # == Introduction
23
+ #
24
+ # CGI is a large class, providing several categories of methods, many of which
25
+ # are mixed in from other modules. Some of the documentation is in this class,
26
+ # some in the modules CGI::QueryExtension and CGI::HtmlExtension. See
27
+ # CGI::Cookie for specific information on handling cookies, and cgi/session.rb
28
+ # (CGI::Session) for information on sessions.
29
+ #
30
+ # For queries, CGI provides methods to get at environmental variables,
31
+ # parameters, cookies, and multipart request data. For responses, CGI provides
32
+ # methods for writing output and generating HTML.
33
+ #
34
+ # Read on for more details. Examples are provided at the bottom.
35
+ #
36
+ # == Queries
37
+ #
38
+ # The CGI class dynamically mixes in parameter and cookie-parsing
39
+ # functionality, environmental variable access, and support for
40
+ # parsing multipart requests (including uploaded files) from the
41
+ # CGI::QueryExtension module.
42
+ #
43
+ # === Environmental Variables
44
+ #
45
+ # The standard CGI environmental variables are available as read-only
46
+ # attributes of a CGI object. The following is a list of these variables:
47
+ #
48
+ #
49
+ # AUTH_TYPE HTTP_HOST REMOTE_IDENT
50
+ # CONTENT_LENGTH HTTP_NEGOTIATE REMOTE_USER
51
+ # CONTENT_TYPE HTTP_PRAGMA REQUEST_METHOD
52
+ # GATEWAY_INTERFACE HTTP_REFERER SCRIPT_NAME
53
+ # HTTP_ACCEPT HTTP_USER_AGENT SERVER_NAME
54
+ # HTTP_ACCEPT_CHARSET PATH_INFO SERVER_PORT
55
+ # HTTP_ACCEPT_ENCODING PATH_TRANSLATED SERVER_PROTOCOL
56
+ # HTTP_ACCEPT_LANGUAGE QUERY_STRING SERVER_SOFTWARE
57
+ # HTTP_CACHE_CONTROL REMOTE_ADDR
58
+ # HTTP_FROM REMOTE_HOST
59
+ #
60
+ #
61
+ # For each of these variables, there is a corresponding attribute with the
62
+ # same name, except all lower case and without a preceding HTTP_.
63
+ # +content_length+ and +server_port+ are integers; the rest are strings.
64
+ #
65
+ # === Parameters
66
+ #
67
+ # The method #params() returns a hash of all parameters in the request as
68
+ # name/value-list pairs, where the value-list is an Array of one or more
69
+ # values. The CGI object itself also behaves as a hash of parameter names
70
+ # to values, but only returns a single value (as a String) for each
71
+ # parameter name.
72
+ #
73
+ # For instance, suppose the request contains the parameter
74
+ # "favourite_colours" with the multiple values "blue" and "green". The
75
+ # following behaviour would occur:
76
+ #
77
+ # cgi.params["favourite_colours"] # => ["blue", "green"]
78
+ # cgi["favourite_colours"] # => "blue"
79
+ #
80
+ # If a parameter does not exist, the former method will return an empty
81
+ # array, the latter an empty string. The simplest way to test for existence
82
+ # of a parameter is by the #has_key? method.
83
+ #
84
+ # === Cookies
85
+ #
86
+ # HTTP Cookies are automatically parsed from the request. They are available
87
+ # from the #cookies() accessor, which returns a hash from cookie name to
88
+ # CGI::Cookie object.
89
+ #
90
+ # === Multipart requests
91
+ #
92
+ # If a request's method is POST and its content type is multipart/form-data,
93
+ # then it may contain uploaded files. These are stored by the QueryExtension
94
+ # module in the parameters of the request. The parameter name is the name
95
+ # attribute of the file input field, as usual. However, the value is not
96
+ # a string, but an IO object, either an IOString for small files, or a
97
+ # Tempfile for larger ones. This object also has the additional singleton
98
+ # methods:
99
+ #
100
+ # #local_path():: the path of the uploaded file on the local filesystem
101
+ # #original_filename():: the name of the file on the client computer
102
+ # #content_type():: the content type of the file
103
+ #
104
+ # == Responses
105
+ #
106
+ # The CGI class provides methods for sending header and content output to
107
+ # the HTTP client, and mixes in methods for programmatic HTML generation
108
+ # from CGI::HtmlExtension and CGI::TagMaker modules. The precise version of HTML
109
+ # to use for HTML generation is specified at object creation time.
110
+ #
111
+ # === Writing output
112
+ #
113
+ # The simplest way to send output to the HTTP client is using the #out() method.
114
+ # This takes the HTTP headers as a hash parameter, and the body content
115
+ # via a block. The headers can be generated as a string using the #header()
116
+ # method. The output stream can be written directly to using the #print()
117
+ # method.
118
+ #
119
+ # === Generating HTML
120
+ #
121
+ # Each HTML element has a corresponding method for generating that
122
+ # element as a String. The name of this method is the same as that
123
+ # of the element, all lowercase. The attributes of the element are
124
+ # passed in as a hash, and the body as a no-argument block that evaluates
125
+ # to a String. The HTML generation module knows which elements are
126
+ # always empty, and silently drops any passed-in body. It also knows
127
+ # which elements require matching closing tags and which don't. However,
128
+ # it does not know what attributes are legal for which elements.
129
+ #
130
+ # There are also some additional HTML generation methods mixed in from
131
+ # the CGI::HtmlExtension module. These include individual methods for the
132
+ # different types of form inputs, and methods for elements that commonly
133
+ # take particular attributes where the attributes can be directly specified
134
+ # as arguments, rather than via a hash.
135
+ #
136
+ # == Examples of use
137
+ #
138
+ # === Get form values
139
+ #
140
+ # require "cgi"
141
+ # cgi = CGI.new
142
+ # value = cgi['field_name'] # <== value string for 'field_name'
143
+ # # if not 'field_name' included, then return "".
144
+ # fields = cgi.keys # <== array of field names
145
+ #
146
+ # # returns true if form has 'field_name'
147
+ # cgi.has_key?('field_name')
148
+ # cgi.has_key?('field_name')
149
+ # cgi.include?('field_name')
150
+ #
151
+ # CAUTION! cgi['field_name'] returned an Array with the old
152
+ # cgi.rb(included in ruby 1.6)
153
+ #
154
+ # === Get form values as hash
155
+ #
156
+ # require "cgi"
157
+ # cgi = CGI.new
158
+ # params = cgi.params
159
+ #
160
+ # cgi.params is a hash.
161
+ #
162
+ # cgi.params['new_field_name'] = ["value"] # add new param
163
+ # cgi.params['field_name'] = ["new_value"] # change value
164
+ # cgi.params.delete('field_name') # delete param
165
+ # cgi.params.clear # delete all params
166
+ #
167
+ #
168
+ # === Save form values to file
169
+ #
170
+ # require "pstore"
171
+ # db = PStore.new("query.db")
172
+ # db.transaction do
173
+ # db["params"] = cgi.params
174
+ # end
175
+ #
176
+ #
177
+ # === Restore form values from file
178
+ #
179
+ # require "pstore"
180
+ # db = PStore.new("query.db")
181
+ # db.transaction do
182
+ # cgi.params = db["params"]
183
+ # end
184
+ #
185
+ #
186
+ # === Get multipart form values
187
+ #
188
+ # require "cgi"
189
+ # cgi = CGI.new
190
+ # value = cgi['field_name'] # <== value string for 'field_name'
191
+ # value.read # <== body of value
192
+ # value.local_path # <== path to local file of value
193
+ # value.original_filename # <== original filename of value
194
+ # value.content_type # <== content_type of value
195
+ #
196
+ # and value has StringIO or Tempfile class methods.
197
+ #
198
+ # === Get cookie values
199
+ #
200
+ # require "cgi"
201
+ # cgi = CGI.new
202
+ # values = cgi.cookies['name'] # <== array of 'name'
203
+ # # if not 'name' included, then return [].
204
+ # names = cgi.cookies.keys # <== array of cookie names
205
+ #
206
+ # and cgi.cookies is a hash.
207
+ #
208
+ # === Get cookie objects
209
+ #
210
+ # require "cgi"
211
+ # cgi = CGI.new
212
+ # for name, cookie in cgi.cookies
213
+ # cookie.expires = Time.now + 30
214
+ # end
215
+ # cgi.out("cookie" => cgi.cookies) {"string"}
216
+ #
217
+ # cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
218
+ #
219
+ # require "cgi"
220
+ # cgi = CGI.new
221
+ # cgi.cookies['name'].expires = Time.now + 30
222
+ # cgi.out("cookie" => cgi.cookies['name']) {"string"}
223
+ #
224
+ # === Print http header and html string to $DEFAULT_OUTPUT ($>)
225
+ #
226
+ # require "cgi"
227
+ # cgi = CGI.new("html3") # add HTML generation methods
228
+ # cgi.out() do
229
+ # cgi.html() do
230
+ # cgi.head{ cgi.title{"TITLE"} } +
231
+ # cgi.body() do
232
+ # cgi.form() do
233
+ # cgi.textarea("get_text") +
234
+ # cgi.br +
235
+ # cgi.submit
236
+ # end +
237
+ # cgi.pre() do
238
+ # CGI::escapeHTML(
239
+ # "params: " + cgi.params.inspect + "\n" +
240
+ # "cookies: " + cgi.cookies.inspect + "\n" +
241
+ # ENV.collect() do |key, value|
242
+ # key + " --> " + value + "\n"
243
+ # end.join("")
244
+ # )
245
+ # end
246
+ # end
247
+ # end
248
+ # end
249
+ #
250
+ # # add HTML generation methods
251
+ # CGI.new("html3") # html3.2
252
+ # CGI.new("html4") # html4.01 (Strict)
253
+ # CGI.new("html4Tr") # html4.01 Transitional
254
+ # CGI.new("html4Fr") # html4.01 Frameset
255
+ #
256
+ class CGI
257
+
258
+ # :stopdoc:
259
+
260
+ EOL = "\r\n"
261
+ #*** original
262
+ #*# String for carriage return
263
+ #*CR = "\015"
264
+ #*
265
+ #*# String for linefeed
266
+ #*LF = "\012"
267
+ #*
268
+ #*# Standard internet newline sequence
269
+ #*EOL = CR + LF
270
+ #*
271
+ #*REVISION = '$Id: core.rb 27 2007-12-08 23:17:16Z kwatch $' #:nodoc:
272
+ #*
273
+ #*NEEDS_BINMODE = true if /WIN/ni.match(RUBY_PLATFORM)
274
+ #*
275
+ #*# Path separators in different environments.
276
+ #*PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
277
+ #*** /original
278
+
279
+ # HTTP status codes.
280
+ HTTP_STATUS = {
281
+ "OK" => "200 OK",
282
+ "PARTIAL_CONTENT" => "206 Partial Content",
283
+ "MULTIPLE_CHOICES" => "300 Multiple Choices",
284
+ "MOVED" => "301 Moved Permanently",
285
+ "REDIRECT" => "302 Found",
286
+ "NOT_MODIFIED" => "304 Not Modified",
287
+ "BAD_REQUEST" => "400 Bad Request",
288
+ "AUTH_REQUIRED" => "401 Authorization Required",
289
+ "FORBIDDEN" => "403 Forbidden",
290
+ "NOT_FOUND" => "404 Not Found",
291
+ "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
292
+ "NOT_ACCEPTABLE" => "406 Not Acceptable",
293
+ "LENGTH_REQUIRED" => "411 Length Required",
294
+ "PRECONDITION_FAILED" => "412 Rrecondition Failed",
295
+ "SERVER_ERROR" => "500 Internal Server Error",
296
+ "NOT_IMPLEMENTED" => "501 Method Not Implemented",
297
+ "BAD_GATEWAY" => "502 Bad Gateway",
298
+ "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates",
299
+ }
300
+
301
+ # Abbreviated day-of-week names specified by RFC 822
302
+ RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
303
+
304
+ # Abbreviated month names specified by RFC 822
305
+ RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
306
+
307
+ # :startdoc:
308
+
309
+ def env_table
310
+ ENV
311
+ end
312
+
313
+ def stdinput
314
+ $stdin
315
+ end
316
+
317
+ def stdoutput
318
+ $DEFAULT_OUTPUT
319
+ end
320
+
321
+ private :env_table, :stdinput, :stdoutput
322
+
323
+
324
+ # Create an HTTP header block as a string.
325
+ #
326
+ # Includes the empty line that ends the header block.
327
+ #
328
+ # +options+ can be a string specifying the Content-Type (defaults
329
+ # to text/html), or a hash of header key/value pairs. The following
330
+ # header keys are recognized:
331
+ #
332
+ # type:: the Content-Type header. Defaults to "text/html"
333
+ # charset:: the charset of the body, appended to the Content-Type header.
334
+ # nph:: a boolean value. If true, prepend protocol string and status code, and
335
+ # date; and sets default values for "server" and "connection" if not
336
+ # explicitly set.
337
+ # status:: the HTTP status code, returned as the Status header. See the
338
+ # list of available status codes below.
339
+ # server:: the server software, returned as the Server header.
340
+ # connection:: the connection type, returned as the Connection header (for
341
+ # instance, "close".
342
+ # length:: the length of the content that will be sent, returned as the
343
+ # Content-Length header.
344
+ # language:: the language of the content, returned as the Content-Language
345
+ # header.
346
+ # expires:: the time on which the current content expires, as a +Time+
347
+ # object, returned as the Expires header.
348
+ # cookie:: a cookie or cookies, returned as one or more Set-Cookie headers.
349
+ # The value can be the literal string of the cookie; a CGI::Cookie
350
+ # object; an Array of literal cookie strings or Cookie objects; or a
351
+ # hash all of whose values are literal cookie strings or Cookie objects.
352
+ # These cookies are in addition to the cookies held in the
353
+ # @output_cookies field.
354
+ #
355
+ # Other header lines can also be set; they are appended as key: value.
356
+ #
357
+ # header
358
+ # # Content-Type: text/html
359
+ #
360
+ # header("text/plain")
361
+ # # Content-Type: text/plain
362
+ #
363
+ # header("nph" => true,
364
+ # "status" => "OK", # == "200 OK"
365
+ # # "status" => "200 GOOD",
366
+ # "server" => ENV['SERVER_SOFTWARE'],
367
+ # "connection" => "close",
368
+ # "type" => "text/html",
369
+ # "charset" => "iso-2022-jp",
370
+ # # Content-Type: text/html; charset=iso-2022-jp
371
+ # "length" => 103,
372
+ # "language" => "ja",
373
+ # "expires" => Time.now + 30,
374
+ # "cookie" => [cookie1, cookie2],
375
+ # "my_header1" => "my_value"
376
+ # "my_header2" => "my_value")
377
+ #
378
+ # The status codes are:
379
+ #
380
+ # "OK" --> "200 OK"
381
+ # "PARTIAL_CONTENT" --> "206 Partial Content"
382
+ # "MULTIPLE_CHOICES" --> "300 Multiple Choices"
383
+ # "MOVED" --> "301 Moved Permanently"
384
+ # "REDIRECT" --> "302 Found"
385
+ # "NOT_MODIFIED" --> "304 Not Modified"
386
+ # "BAD_REQUEST" --> "400 Bad Request"
387
+ # "AUTH_REQUIRED" --> "401 Authorization Required"
388
+ # "FORBIDDEN" --> "403 Forbidden"
389
+ # "NOT_FOUND" --> "404 Not Found"
390
+ # "METHOD_NOT_ALLOWED" --> "405 Method Not Allowed"
391
+ # "NOT_ACCEPTABLE" --> "406 Not Acceptable"
392
+ # "LENGTH_REQUIRED" --> "411 Length Required"
393
+ # "PRECONDITION_FAILED" --> "412 Precondition Failed"
394
+ # "SERVER_ERROR" --> "500 Internal Server Error"
395
+ # "NOT_IMPLEMENTED" --> "501 Method Not Implemented"
396
+ # "BAD_GATEWAY" --> "502 Bad Gateway"
397
+ # "VARIANT_ALSO_VARIES" --> "506 Variant Also Negotiates"
398
+ #
399
+ # This method does not perform charset conversion.
400
+ #
401
+ def header(options='text/html')
402
+ if options.is_a?(String)
403
+ content_type = options
404
+ buf = _header_for_string(content_type)
405
+ elsif options.is_a?(Hash)
406
+ if options.size == 1 && options.has_key?('type')
407
+ content_type = options['type']
408
+ buf = _header_for_string(content_type)
409
+ else
410
+ buf = _header_for_hash(options.dup)
411
+ end
412
+ else
413
+ raise ArgumentError.new("expected String or Hash but got #{options.class}")
414
+ end
415
+ if defined?(MOD_RUBY)
416
+ _header_for_modruby(buf)
417
+ return ''
418
+ else
419
+ buf << EOL # empty line of separator
420
+ return buf
421
+ end
422
+ end
423
+
424
+ def _header_for_string(content_type) #:nodoc:
425
+ buf = ''
426
+ if nph?()
427
+ buf << "#{ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
428
+ buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
429
+ buf << "Server: #{ENV['SERVER_SOFTWARE']}#{EOL}"
430
+ buf << "Connection: close#{EOL}"
431
+ end
432
+ buf << "Content-Type: #{content_type}#{EOL}"
433
+ if @output_cookies
434
+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
435
+ end
436
+ return buf
437
+ end
438
+ private :_header_for_string
439
+
440
+ def _header_for_hash(options) #:nodoc:
441
+ buf = ''
442
+ ## add charset to option['type']
443
+ options['type'] ||= 'text/html'
444
+ charset = options.delete('charset')
445
+ options['type'] += "; charset=#{charset}" if charset
446
+ ## NPH
447
+ options.delete('nph') if defined?(MOD_RUBY)
448
+ if options.delete('nph') || nph?()
449
+ protocol = ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
450
+ status = options.delete('status')
451
+ status = HTTP_STATUS[status] || status || '200 OK'
452
+ buf << "#{protocol} #{status}#{EOL}"
453
+ buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
454
+ options['server'] ||= ENV['SERVER_SOFTWARE'] || ''
455
+ options['connection'] ||= 'close'
456
+ end
457
+ ## common headers
458
+ status = options.delete('status')
459
+ buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status
460
+ server = options.delete('server')
461
+ buf << "Server: #{server}#{EOL}" if server
462
+ connection = options.delete('connection')
463
+ buf << "Connection: #{connection}#{EOL}" if connection
464
+ type = options.delete('type')
465
+ buf << "Content-Type: #{type}#{EOL}" #if type
466
+ length = options.delete('length')
467
+ buf << "Content-Length: #{length}#{EOL}" if length
468
+ language = options.delete('language')
469
+ buf << "Content-Language: #{language}#{EOL}" if language
470
+ expires = options.delete('expires')
471
+ buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
472
+ ## cookie
473
+ if cookie = options.delete('cookie')
474
+ case cookie
475
+ when String, Cookie
476
+ buf << "Set-Cookie: #{cookie}#{EOL}"
477
+ when Array
478
+ arr = cookie
479
+ arr.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
480
+ when Hash
481
+ hash = cookie
482
+ hash.each {|name, cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
483
+ end
484
+ end
485
+ if @output_cookies
486
+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
487
+ end
488
+ ## other headers
489
+ options.each do |key, value|
490
+ buf << "#{key}: #{value}#{EOL}"
491
+ end
492
+ return buf
493
+ end
494
+ private :_header_for_hash
495
+
496
+ def nph? #:nodoc:
497
+ return /IIS\/(\d+)/n.match(ENV['SERVER_SOFTWARE']) && $1.to_i < 5
498
+ end
499
+
500
+ def _header_for_modruby(buf) #:nodoc:
501
+ request = Apache::request
502
+ buf.scan(/([^:]+): (.+)#{EOL}/no) do |name, value|
503
+ warn sprintf("name:%s value:%s\n", name, value) if $DEBUG
504
+ case name
505
+ when 'Set-Cookie'
506
+ request.headers_out.add(name, value)
507
+ when /^status$/ni
508
+ request.status_line = value
509
+ request.status = value.to_i
510
+ when /^content-type$/ni
511
+ request.content_type = value
512
+ when /^content-encoding$/ni
513
+ request.content_encoding = value
514
+ when /^location$/ni
515
+ request.status = 302 if request.status == 200
516
+ request.headers_out[name] = value
517
+ else
518
+ request.headers_out[name] = value
519
+ end
520
+ end
521
+ request.send_http_header
522
+ return ''
523
+ end
524
+ private :_header_for_modruby
525
+ #*** original
526
+ #*def header(options = "text/html")
527
+ #*
528
+ #* buf = ""
529
+ #*
530
+ #* case options
531
+ #* when String
532
+ #* options = { "type" => options }
533
+ #* when Hash
534
+ #* options = options.dup
535
+ #* end
536
+ #*
537
+ #* unless options.has_key?("type")
538
+ #* options["type"] = "text/html"
539
+ #* end
540
+ #*
541
+ #* if options.has_key?("charset")
542
+ #* options["type"] += "; charset=" + options.delete("charset")
543
+ #* end
544
+ #*
545
+ #* options.delete("nph") if defined?(MOD_RUBY)
546
+ #* if options.delete("nph") or
547
+ #* (/IIS\/(\d+)/n.match(env_table['SERVER_SOFTWARE']) and $1.to_i < 5)
548
+ #* buf += (env_table["SERVER_PROTOCOL"] or "HTTP/1.0") + " " +
549
+ #* (HTTP_STATUS[options["status"]] or options["status"] or "200 OK") +
550
+ #* EOL +
551
+ #* "Date: " + CGI::rfc1123_date(Time.now) + EOL
552
+ #*
553
+ #* unless options.has_key?("server")
554
+ #* options["server"] = (env_table['SERVER_SOFTWARE'] or "")
555
+ #* end
556
+ #*
557
+ #* unless options.has_key?("connection")
558
+ #* options["connection"] = "close"
559
+ #* end
560
+ #*
561
+ #* options.delete("status")
562
+ #* end
563
+ #*
564
+ #* if options.has_key?("status")
565
+ #* buf += "Status: " +
566
+ #* (HTTP_STATUS[options["status"]] or options["status"]) + EOL
567
+ #* options.delete("status")
568
+ #* end
569
+ #*
570
+ #* if options.has_key?("server")
571
+ #* buf += "Server: " + options.delete("server") + EOL
572
+ #* end
573
+ #*
574
+ #* if options.has_key?("connection")
575
+ #* buf += "Connection: " + options.delete("connection") + EOL
576
+ #* end
577
+ #*
578
+ #* buf += "Content-Type: " + options.delete("type") + EOL
579
+ #*
580
+ #* if options.has_key?("length")
581
+ #* buf += "Content-Length: " + options.delete("length").to_s + EOL
582
+ #* end
583
+ #*
584
+ #* if options.has_key?("language")
585
+ #* buf += "Content-Language: " + options.delete("language") + EOL
586
+ #* end
587
+ #*
588
+ #* if options.has_key?("expires")
589
+ #* buf += "Expires: " + CGI::rfc1123_date( options.delete("expires") ) + EOL
590
+ #* end
591
+ #*
592
+ #* if options.has_key?("cookie")
593
+ #* if options["cookie"].kind_of?(String) or
594
+ #* options["cookie"].kind_of?(Cookie)
595
+ #* buf += "Set-Cookie: " + options.delete("cookie").to_s + EOL
596
+ #* elsif options["cookie"].kind_of?(Array)
597
+ #* options.delete("cookie").each{|cookie|
598
+ #* buf += "Set-Cookie: " + cookie.to_s + EOL
599
+ #* }
600
+ #* elsif options["cookie"].kind_of?(Hash)
601
+ #* options.delete("cookie").each_value{|cookie|
602
+ #* buf += "Set-Cookie: " + cookie.to_s + EOL
603
+ #* }
604
+ #* end
605
+ #* end
606
+ #* if @output_cookies
607
+ #* for cookie in @output_cookies
608
+ #* buf += "Set-Cookie: " + cookie.to_s + EOL
609
+ #* end
610
+ #* end
611
+ #*
612
+ #* options.each{|key, value|
613
+ #* buf += key + ": " + value.to_s + EOL
614
+ #* }
615
+ #*
616
+ #* if defined?(MOD_RUBY)
617
+ #* table = Apache::request.headers_out
618
+ #* buf.scan(/([^:]+): (.+)#{EOL}/n){ |name, value|
619
+ #* warn sprintf("name:%s value:%s\n", name, value) if $DEBUG
620
+ #* case name
621
+ #* when 'Set-Cookie'
622
+ #* table.add(name, value)
623
+ #* when /^status$/ni
624
+ #* Apache::request.status_line = value
625
+ #* Apache::request.status = value.to_i
626
+ #* when /^content-type$/ni
627
+ #* Apache::request.content_type = value
628
+ #* when /^content-encoding$/ni
629
+ #* Apache::request.content_encoding = value
630
+ #* when /^location$/ni
631
+ #* if Apache::request.status == 200
632
+ #* Apache::request.status = 302
633
+ #* end
634
+ #* Apache::request.headers_out[name] = value
635
+ #* else
636
+ #* Apache::request.headers_out[name] = value
637
+ #* end
638
+ #* }
639
+ #* Apache::request.send_http_header
640
+ #* ''
641
+ #* else
642
+ #* buf + EOL
643
+ #* end
644
+ #*
645
+ #*end # header()
646
+ #*** /original
647
+
648
+
649
+ # Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
650
+ #
651
+ # The header is provided by +options+, as for #header().
652
+ # The body of the document is that returned by the passed-
653
+ # in block. This block takes no arguments. It is required.
654
+ #
655
+ # cgi = CGI.new
656
+ # cgi.out{ "string" }
657
+ # # Content-Type: text/html
658
+ # # Content-Length: 6
659
+ # #
660
+ # # string
661
+ #
662
+ # cgi.out("text/plain") { "string" }
663
+ # # Content-Type: text/plain
664
+ # # Content-Length: 6
665
+ # #
666
+ # # string
667
+ #
668
+ # cgi.out("nph" => true,
669
+ # "status" => "OK", # == "200 OK"
670
+ # "server" => ENV['SERVER_SOFTWARE'],
671
+ # "connection" => "close",
672
+ # "type" => "text/html",
673
+ # "charset" => "iso-2022-jp",
674
+ # # Content-Type: text/html; charset=iso-2022-jp
675
+ # "language" => "ja",
676
+ # "expires" => Time.now + (3600 * 24 * 30),
677
+ # "cookie" => [cookie1, cookie2],
678
+ # "my_header1" => "my_value",
679
+ # "my_header2" => "my_value") { "string" }
680
+ #
681
+ # Content-Length is automatically calculated from the size of
682
+ # the String returned by the content block.
683
+ #
684
+ # If ENV['REQUEST_METHOD'] == "HEAD", then only the header
685
+ # is outputted (the content block is still required, but it
686
+ # is ignored).
687
+ #
688
+ # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then
689
+ # the content is converted to this charset, and the language is set
690
+ # to "ja".
691
+ def out(options='text/html') # :yield:
692
+ options = { 'type' => options } if options.kind_of?(String)
693
+ stdout = $stdout
694
+ stdout.binmode if defined? stdout.binmode
695
+ #if ENV['REQUEST_METHOD'] == 'HEAD'
696
+ # charset = options['charset']
697
+ # options['language'] ||= 'ja' if charset && charset =~ /iso-2022-jp|euc-jp|shift_jis/ni
698
+ # stdout.print header(options)
699
+ # return
700
+ #end
701
+ content = yield
702
+ content = convert_content(content, options)
703
+ options['length'] = content.length.to_s
704
+ stdout.print header(options)
705
+ stdout.print content unless ENV['REQUEST_METHOD'] == 'HEAD'
706
+ end
707
+ def convert_content(content, options) #:nodoc:
708
+ charset = options['charset']
709
+ return content unless charset
710
+ opt = nil
711
+ case charset
712
+ when /iso-2022-jp/ni ; opt = '-m0 -x -j'
713
+ when /euc-jp/ni ; opt = '-m0 -x -e'
714
+ when /shift_jis/ni ; opt = '-m0 -x -s'
715
+ end
716
+ if opt
717
+ require 'nkf'
718
+ content = NKF.nkf(opt, content)
719
+ options['language'] ||= 'ja'
720
+ end
721
+ return content
722
+ end
723
+ private :convert_content
724
+ #*** original
725
+ #*def out(options = "text/html") # :yield:
726
+ #*
727
+ #* options = { "type" => options } if options.kind_of?(String)
728
+ #* content = yield
729
+ #*
730
+ #* if options.has_key?("charset")
731
+ #* require "nkf"
732
+ #* case options["charset"]
733
+ #* when /iso-2022-jp/ni
734
+ #* content = NKF::nkf('-m0 -x -j', content)
735
+ #* options["language"] = "ja" unless options.has_key?("language")
736
+ #* when /euc-jp/ni
737
+ #* content = NKF::nkf('-m0 -x -e', content)
738
+ #* options["language"] = "ja" unless options.has_key?("language")
739
+ #* when /shift_jis/ni
740
+ #* content = NKF::nkf('-m0 -x -s', content)
741
+ #* options["language"] = "ja" unless options.has_key?("language")
742
+ #* end
743
+ #* end
744
+ #*
745
+ #* options["length"] = content.length.to_s
746
+ #* output = stdoutput
747
+ #* output.binmode if defined? output.binmode
748
+ #* output.print header(options)
749
+ #* output.print content unless "HEAD" == env_table['REQUEST_METHOD']
750
+ #*end
751
+ #*** /original
752
+
753
+
754
+ # Print an argument or list of arguments to the default output stream
755
+ #
756
+ # cgi = CGI.new
757
+ # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
758
+ def print(*options)
759
+ $stdout.print(*options)
760
+ #*** original
761
+ #*stdoutput.print(*options)
762
+ #*** /original
763
+ end
764
+
765
+
766
+ # Parse an HTTP query string into a hash of key=>value pairs.
767
+ #
768
+ # params = CGI::parse("query_string")
769
+ # # {"name1" => ["value1", "value2", ...],
770
+ # # "name2" => ["value1", "value2", ...], ... }
771
+ #
772
+ def CGI::parse(query)
773
+ params = {}
774
+ query.split(/[&;]/n).each do |pair|
775
+ key, value = pair.split('=', 2)
776
+ (params[CGI.unescape(key)] ||= []) << CGI.unescape(value)
777
+ end
778
+ params.default = [].freeze
779
+ return params
780
+ end
781
+ #*** original
782
+ #*def CGI::parse(query)
783
+ #* params = Hash.new([].freeze)
784
+ #*
785
+ #* query.split(/[&;]/n).each do |pairs|
786
+ #* key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) }
787
+ #* if params.has_key?(key)
788
+ #* params[key].push(value)
789
+ #* else
790
+ #* params[key] = [value]
791
+ #* end
792
+ #* end
793
+ #*
794
+ #* params
795
+ #*end
796
+ #*** /original
797
+
798
+
799
+ # Maximum content length of post data
800
+ MAX_CONTENT_LENGTH = 2 * 1024 * 1024
801
+
802
+ # Maximum content length of multipart data
803
+ MAX_MULTIPART_LENGTH = 128 * 1024 * 1024
804
+
805
+ # Maximum number of request parameters when multipart
806
+ MAX_MULTIPART_COUNT = 128
807
+
808
+
809
+ # Mixin module. It provides the follow functionality groups:
810
+ #
811
+ # 1. Access to CGI environment variables as methods. See
812
+ # documentation to the CGI class for a list of these variables.
813
+ #
814
+ # 2. Access to cookies, including the cookies attribute.
815
+ #
816
+ # 3. Access to parameters, including the params attribute, and overloading
817
+ # [] to perform parameter value lookup by key.
818
+ #
819
+ # 4. The initialize_query method, for initialising the above
820
+ # mechanisms, handling multipart forms, and allowing the
821
+ # class to be used in "offline" mode.
822
+ #
823
+ module QueryExtension
824
+
825
+ ## return Integer(ENV['CONTENT_LENGTH'])
826
+ def content_length ; return Integer(ENV['CONTENT_LENGTH']) ; end
827
+
828
+ ## return Integer(ENV['SERVER_PORT'])
829
+ def server_port ; return Integer(ENV['SERVER_PORT']) ; end
830
+
831
+ ## return ENV['AUTH_TYPE']
832
+ def auth_type ; return ENV['AUTH_TYPE'] ; end
833
+
834
+ ## return ENV['CONTENT_TYPE']
835
+ def content_type ; return ENV['CONTENT_TYPE'] ; end
836
+
837
+ ## return ENV['GATEWAY_INTERFACE']
838
+ def gateway_interface ; return ENV['GATEWAY_INTERFACE'] ; end
839
+
840
+ ## return ENV['PATH_INFO']
841
+ def path_info ; return ENV['PATH_INFO'] ; end
842
+
843
+ ## return ENV['PATH_TRANSLATED']
844
+ def path_translated ; return ENV['PATH_TRANSLATED'] ; end
845
+
846
+ ## return ENV['QUERY_STRING']
847
+ def query_string ; return ENV['QUERY_STRING'] ; end
848
+
849
+ ## return ENV['REMOTE_ADDR']
850
+ def remote_addr ; return ENV['REMOTE_ADDR'] ; end
851
+
852
+ ## return ENV['REMOTE_HOST']
853
+ def remote_host ; return ENV['REMOTE_HOST'] ; end
854
+
855
+ ## return ENV['REMOTE_IDENT']
856
+ def remote_ident ; return ENV['REMOTE_IDENT'] ; end
857
+
858
+ ## return ENV['REMOTE_USER']
859
+ def remote_user ; return ENV['REMOTE_USER'] ; end
860
+
861
+ ## return ENV['REQUEST_METHOD']
862
+ def request_method ; return ENV['REQUEST_METHOD'] ; end
863
+
864
+ ## return ENV['SCRIPT_NAME']
865
+ def script_name ; return ENV['SCRIPT_NAME'] ; end
866
+
867
+ ## return ENV['SERVER_NAME']
868
+ def server_name ; return ENV['SERVER_NAME'] ; end
869
+
870
+ ## return ENV['SERVER_PROTOCOL']
871
+ def server_protocol ; return ENV['SERVER_PROTOCOL'] ; end
872
+
873
+ ## return ENV['SERVER_SOFTWARE']
874
+ def server_software ; return ENV['SERVER_SOFTWARE'] ; end
875
+
876
+ ## return ENV['HTTP_ACCEPT']
877
+ def accept ; return ENV['HTTP_ACCEPT'] ; end
878
+
879
+ ## return ENV['HTTP_ACCEPT_CHARSET']
880
+ def accept_charset ; return ENV['HTTP_ACCEPT_CHARSET'] ; end
881
+
882
+ ## return ENV['HTTP_ACCEPT_ENCODING']
883
+ def accept_encoding ; return ENV['HTTP_ACCEPT_ENCODING'] ; end
884
+
885
+ ## return ENV['HTTP_ACCEPT_LANGUAGE']
886
+ def accept_language ; return ENV['HTTP_ACCEPT_LANGUAGE'] ; end
887
+
888
+ ## return ENV['HTTP_CACHE_CONTROL']
889
+ def cache_control ; return ENV['HTTP_CACHE_CONTROL'] ; end
890
+
891
+ ## return ENV['HTTP_FROM']
892
+ def from ; return ENV['HTTP_FROM'] ; end
893
+
894
+ ## return ENV['HTTP_HOST']
895
+ def host ; return ENV['HTTP_HOST'] ; end
896
+
897
+ ## return ENV['HTTP_NEGOTIATE']
898
+ def negotiate ; return ENV['HTTP_NEGOTIATE'] ; end
899
+
900
+ ## return ENV['HTTP_PRAGMA']
901
+ def pragma ; return ENV['HTTP_PRAGMA'] ; end
902
+
903
+ ## return ENV['HTTP_REFERER']
904
+ def referer ; return ENV['HTTP_REFERER'] ; end
905
+
906
+ ## return ENV['HTTP_USER_AGENT']
907
+ def user_agent ; return ENV['HTTP_USER_AGENT'] ; end
908
+
909
+ #*** orignal
910
+ #*%w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
911
+ #* define_method(env.sub(/^HTTP_/n, '').downcase) do
912
+ #* (val = env_table[env]) && Integer(val)
913
+ #* end
914
+ #*end
915
+ #*
916
+ #*%w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
917
+ #* PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
918
+ #* REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
919
+ #* SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
920
+ #*
921
+ #* HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
922
+ #* HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
923
+ #* HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
924
+ #* define_method(env.sub(/^HTTP_/n, '').downcase) do
925
+ #* env_table[env]
926
+ #* end
927
+ #*end
928
+ #*** /orignal
929
+
930
+ # Get the raw cookies as a string.
931
+ def raw_cookie
932
+ return ENV['HTTP_COOKIE']
933
+ end
934
+ #*** original
935
+ #*def raw_cookie
936
+ #* env_table["HTTP_COOKIE"]
937
+ #*end
938
+ #*** /original
939
+
940
+ # Get the raw RFC2965 cookies as a string.
941
+ def raw_cookie2
942
+ return ENV['HTTP_COOKIE2']
943
+ end
944
+ #*** original
945
+ #*def raw_cookie2
946
+ #* env_table["HTTP_COOKIE2"]
947
+ #*end
948
+ #*** /original
949
+
950
+ # Get the cookies as a hash of cookie-name=>Cookie pairs.
951
+ attr_accessor :cookies
952
+ #*** original
953
+ #*attr_accessor("cookies")
954
+ #*** /original
955
+
956
+ # Get the parameters as a hash of name=>values pairs, where
957
+ # values is an Array.
958
+ attr_reader :params
959
+ #*** original
960
+ #*attr("params")
961
+ #*** /original
962
+
963
+ # Set all the parameters.
964
+ def params=(hash)
965
+ @params.clear
966
+ @params.update(hash)
967
+ end
968
+
969
+ def read_multipart(boundary, content_length)
970
+ ## read first boundary
971
+ stdin = $stdin
972
+ stdin.binmode if defined? stdin.binmode
973
+ first_line = "--#{boundary}#{EOL}"
974
+ content_length -= first_line.length
975
+ status = stdin.read(first_line.length)
976
+ raise EOFError.new("no content body") unless status
977
+ raise EOFError.new("bad content body") unless first_line == status
978
+ ## parse and set params
979
+ params = {}
980
+ boundary_rexp = /--#{Regexp.quote(boundary, 'n')}(#{EOL}|--)/n
981
+ boundary_size = "#{EOL}--#{boundary}#{EOL}".length
982
+ boundary_end = nil
983
+ buf = ''
984
+ bufsize = 10 * 1024
985
+ max_count = MAX_MULTIPART_COUNT
986
+ n = 0
987
+ while true
988
+ (n += 1) < max_count or raise StandardError.new("too many parameters.")
989
+ ## create body (StringIO or Tempfile)
990
+ body = create_body(bufsize < content_length)
991
+ class << body
992
+ alias local_path path
993
+ attr_reader :original_filename, :content_type
994
+ end
995
+ ## find head and boundary
996
+ head = nil
997
+ separator = EOL * 2
998
+ until head && matched = boundary_rexp.match(buf)
999
+ if !head && pos = buf.index(separator)
1000
+ len = pos + EOL.length
1001
+ head = buf[0, len]
1002
+ buf = buf[(pos+separator.length)..-1]
1003
+ else
1004
+ if head && buf.size > boundary_size
1005
+ len = buf.size - boundary_size
1006
+ body.print(buf[0, len])
1007
+ buf[0, len] = ''
1008
+ end
1009
+ c = stdin.read(bufsize < content_length ? bufsize : content_length)
1010
+ raise EOFError.new("bad content body") if c.nil? || c.empty?
1011
+ buf << c
1012
+ content_length -= c.length
1013
+ end
1014
+ end
1015
+ ## read to end of boundary
1016
+ m = matched
1017
+ len = m.begin(0)
1018
+ s = buf[0, len]
1019
+ if s =~ /(\r?\n)\z/
1020
+ s = buf[0, len - $1.length]
1021
+ end
1022
+ body.print(s)
1023
+ buf = buf[m.end(0)..-1]
1024
+ boundary_end = m[1]
1025
+ content_length = -1 if boundary_end == '--'
1026
+ ## reset file cursor position
1027
+ body.rewind
1028
+ ## original filename
1029
+ /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/ni.match(head)
1030
+ filename = $1 || $2 || ''
1031
+ filename = CGI.unescape(filename) if unescape_filename?()
1032
+ body.instance_variable_set('@original_filename', filename.taint)
1033
+ ## content type
1034
+ /Content-Type: (.*)/ni.match(head)
1035
+ (content_type = $1 || '').chomp!
1036
+ body.instance_variable_set('@content_type', content_type.taint)
1037
+ ## query parameter name
1038
+ /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/ni.match(head)
1039
+ name = $1 || $2 || ''
1040
+ (params[name] ||= []) << body
1041
+ ## break loop
1042
+ break if buf.size == 0
1043
+ break if content_length == -1
1044
+ end
1045
+ raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/
1046
+ params.default = []
1047
+ params
1048
+ end # read_multipart
1049
+ private :read_multipart
1050
+ def create_body(is_large) #:nodoc:
1051
+ if is_large
1052
+ require 'tempfile'
1053
+ body = Tempfile.new('CGI')
1054
+ else
1055
+ begin
1056
+ require 'stringio'
1057
+ body = StringIO.new
1058
+ rescue LoadError
1059
+ require 'tempfile'
1060
+ body = Tempfile.new('CGI')
1061
+ end
1062
+ end
1063
+ body.binmode if defined? body.binmode
1064
+ return body
1065
+ end
1066
+ def unescape_filename? #:nodoc:
1067
+ user_agent = ENV['HTTP_USER_AGENT']
1068
+ return /Mac/ni.match(user_agent) && /Mozilla/ni.match(user_agent) && !/MSIE/ni.match(user_agent)
1069
+ end
1070
+ #*** original
1071
+ #*def read_multipart(boundary, content_length)
1072
+ #* params = Hash.new([])
1073
+ #* boundary = "--" + boundary
1074
+ #* quoted_boundary = Regexp.quote(boundary, "n")
1075
+ #* buf = ""
1076
+ #* bufsize = 10 * 1024
1077
+ #* boundary_end=""
1078
+ #*
1079
+ #* # start multipart/form-data
1080
+ #* stdinput.binmode if defined? stdinput.binmode
1081
+ #* boundary_size = boundary.size + EOL.size
1082
+ #* content_length -= boundary_size
1083
+ #* status = stdinput.read(boundary_size)
1084
+ #* if nil == status
1085
+ #* raise EOFError, "no content body"
1086
+ #* elsif boundary + EOL != status
1087
+ #* raise EOFError, "bad content body"
1088
+ #* end
1089
+ #*
1090
+ #* loop do
1091
+ #* head = nil
1092
+ #* if 10240 < content_length
1093
+ #* require "tempfile"
1094
+ #* body = Tempfile.new("CGI")
1095
+ #* else
1096
+ #* begin
1097
+ #* require "stringio"
1098
+ #* body = StringIO.new
1099
+ #* rescue LoadError
1100
+ #* require "tempfile"
1101
+ #* body = Tempfile.new("CGI")
1102
+ #* end
1103
+ #* end
1104
+ #* body.binmode if defined? body.binmode
1105
+ #*
1106
+ #* until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
1107
+ #*
1108
+ #* if (not head) and /#{EOL}#{EOL}/n.match(buf)
1109
+ #* buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
1110
+ #* head = $1.dup
1111
+ #* ""
1112
+ #* end
1113
+ #* next
1114
+ #* end
1115
+ #*
1116
+ #* if head and ( (EOL + boundary + EOL).size < buf.size )
1117
+ #* body.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
1118
+ #* buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
1119
+ #* end
1120
+ #*
1121
+ #* c = if bufsize < content_length
1122
+ #* stdinput.read(bufsize)
1123
+ #* else
1124
+ #* stdinput.read(content_length)
1125
+ #* end
1126
+ #* if c.nil? || c.empty?
1127
+ #* raise EOFError, "bad content body"
1128
+ #* end
1129
+ #* buf.concat(c)
1130
+ #* content_length -= c.size
1131
+ #* end
1132
+ #*
1133
+ #* buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
1134
+ #* body.print $1
1135
+ #* if "--" == $2
1136
+ #* content_length = -1
1137
+ #* end
1138
+ #* boundary_end = $2.dup
1139
+ #* ""
1140
+ #* end
1141
+ #*
1142
+ #* body.rewind
1143
+ #*
1144
+ #* /Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;]*))/ni.match(head)
1145
+ #* filename = ($1 or $2 or "")
1146
+ #* if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
1147
+ #* /Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
1148
+ #* (not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
1149
+ #* filename = CGI::unescape(filename)
1150
+ #* end
1151
+ #*
1152
+ #* /Content-Type: (.*)/ni.match(head)
1153
+ #* content_type = ($1 or "")
1154
+ #*
1155
+ #* (class << body; self; end).class_eval do
1156
+ #* alias local_path path
1157
+ #* define_method(:original_filename) {filename.dup.taint}
1158
+ #* define_method(:content_type) {content_type.dup.taint}
1159
+ #* end
1160
+ #*
1161
+ #* /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
1162
+ #* name = $1.dup
1163
+ #*
1164
+ #* if params.has_key?(name)
1165
+ #* params[name].push(body)
1166
+ #* else
1167
+ #* params[name] = [body]
1168
+ #* end
1169
+ #* break if buf.size == 0
1170
+ #* break if content_length == -1
1171
+ #* end
1172
+ #* raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
1173
+ #*
1174
+ #* params
1175
+ #*end # read_multipart
1176
+ #*private :read_multipart
1177
+ #*** /original
1178
+
1179
+ # offline mode. read name=value pairs on standard input.
1180
+ def read_from_cmdline
1181
+ require 'shellwords'
1182
+ if ARGV.empty?
1183
+ string = ARGV.join(' ')
1184
+ else
1185
+ $stdin.tty? and $stderr.puts "(offline mode: enter name=value pairs on standard input)"
1186
+ string = readlines().join(' ').gsub(/\n/n, '')
1187
+ end
1188
+ string = string.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26')
1189
+ words = Shellwords.shellwords(string)
1190
+ sep = words.find {|x| /=/n.match(x) } ? '&' : '+'
1191
+ return words.join(sep)
1192
+ end
1193
+ private :read_from_cmdline
1194
+ #*** original
1195
+ #*def read_from_cmdline
1196
+ #* require "shellwords"
1197
+ #*
1198
+ #* string = unless ARGV.empty?
1199
+ #* ARGV.join(' ')
1200
+ #* else
1201
+ #* if STDIN.tty?
1202
+ #* STDERR.print(
1203
+ #* %|(offline mode: enter name=value pairs on standard input)\n|
1204
+ #* )
1205
+ #* end
1206
+ #* readlines.join(' ').gsub(/\n/n, '')
1207
+ #* end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26')
1208
+ #*
1209
+ #* words = Shellwords.shellwords(string)
1210
+ #*
1211
+ #* if words.find{|x| /=/n.match(x) }
1212
+ #* words.join('&')
1213
+ #* else
1214
+ #* words.join('+')
1215
+ #* end
1216
+ #*end
1217
+ #*private :read_from_cmdline
1218
+ #*** /original
1219
+
1220
+ # Initialize the data from the query.
1221
+ #
1222
+ # Handles multipart forms (in particular, forms that involve file uploads).
1223
+ # Reads query parameters in the @params field, and cookies into @cookies.
1224
+ def initialize_query()
1225
+ case ENV['REQUEST_METHOD']
1226
+ when 'GET', 'HEAD'
1227
+ query_str = defined?(MOD_RUBY) ? Apache::request.args : ENV['QUERY_STRING']
1228
+ @params = CGI.parse(query_str || '')
1229
+ @multipart = false
1230
+ when 'POST'
1231
+ content_length = Integer(ENV['CONTENT_LENGTH'])
1232
+ if /\Amultipart\/form-data/.match(ENV['CONTENT_TYPE'])
1233
+ raise StandardError.new("too large multipart data.") if content_length > MAX_MULTIPART_LENGTH
1234
+ unless /boundary=(?:"([^";,]+?)"|([^;,\s]+))/.match(ENV['CONTENT_TYPE'])
1235
+ raise StandardError.new("no boundary of multipart data.")
1236
+ end
1237
+ boundary = $1 || $2
1238
+ @params = read_multipart(boundary, content_length)
1239
+ @multipart = true
1240
+ else
1241
+ raise StandardError.new("too large post data.") if content_length > MAX_CONTENT_LENGTH
1242
+ stdin = $stdin
1243
+ stdin.binmode if defined? stdin.binmode
1244
+ query_str = stdin.read(content_length)
1245
+ @params = CGI.parse(query_str || '')
1246
+ @multipart = false
1247
+ end
1248
+ else
1249
+ @params = Hash.new([].freeze)
1250
+ @multipart = false
1251
+ end
1252
+ @cookies = CGI::Cookie.parse(ENV['HTTP_COOKIE'] || ENV['COOKIE'])
1253
+ nil
1254
+ end
1255
+ private :initialize_query
1256
+ #*** original
1257
+ #*def initialize_query()
1258
+ #* if ("POST" == env_table['REQUEST_METHOD']) and
1259
+ #* %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(env_table['CONTENT_TYPE'])
1260
+ #* boundary = $1.dup
1261
+ #* @multipart = true
1262
+ #* @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
1263
+ #* else
1264
+ #* @multipart = false
1265
+ #* @params = CGI::parse(
1266
+ #* case env_table['REQUEST_METHOD']
1267
+ #* when "GET", "HEAD"
1268
+ #* if defined?(MOD_RUBY)
1269
+ #* Apache::request.args or ""
1270
+ #* else
1271
+ #* env_table['QUERY_STRING'] or ""
1272
+ #* end
1273
+ #* when "POST"
1274
+ #* stdinput.binmode if defined? stdinput.binmode
1275
+ #* stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
1276
+ #* else
1277
+ #* read_from_cmdline
1278
+ #* end
1279
+ #* )
1280
+ #* end
1281
+ #*
1282
+ #* @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
1283
+ #*end
1284
+ #*private :initialize_query
1285
+ #*** /original
1286
+
1287
+ def multipart?
1288
+ @multipart
1289
+ end
1290
+
1291
+ module Value # :nodoc:
1292
+ def set_params(params)
1293
+ @params = params
1294
+ end
1295
+ def [](idx, *args)
1296
+ if args.size == 0
1297
+ warn "#{caller(1)[0]}:CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key']"
1298
+ @params[idx]
1299
+ else
1300
+ super[idx,*args]
1301
+ end
1302
+ end
1303
+ def first
1304
+ warn "#{caller(1)[0]}:CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key']"
1305
+ self
1306
+ end
1307
+ alias last first
1308
+ def to_a
1309
+ @params || [self]
1310
+ end
1311
+ alias to_ary to_a # to be rhs of multiple assignment
1312
+ end
1313
+
1314
+ # Get the value for the parameter with a given key.
1315
+ #
1316
+ # If the parameter has multiple values, only the first will be
1317
+ # retrieved; use #params() to get the array of values.
1318
+ def [](key)
1319
+ params = @params[key]
1320
+ value = params[0]
1321
+ if @multipart
1322
+ return value if value
1323
+ return defined?(StringIO) ? StringIO.new('') : Tempfile.new('CGI')
1324
+ else
1325
+ str = value ? value.dup : ''
1326
+ str.extend(Value)
1327
+ str.set_params(params)
1328
+ return str
1329
+ end
1330
+ end
1331
+ #*** original
1332
+ #*def [](key)
1333
+ #* params = @params[key]
1334
+ #* value = params[0]
1335
+ #* if @multipart
1336
+ #* if value
1337
+ #* return value
1338
+ #* elsif defined? StringIO
1339
+ #* StringIO.new("")
1340
+ #* else
1341
+ #* Tempfile.new("CGI")
1342
+ #* end
1343
+ #* else
1344
+ #* str = if value then value.dup else "" end
1345
+ #* str.extend(Value)
1346
+ #* str.set_params(params)
1347
+ #* str
1348
+ #* end
1349
+ #*end
1350
+ #*** /original
1351
+
1352
+ # Return all parameter keys as an array.
1353
+ def keys(*args)
1354
+ @params.keys(*args)
1355
+ end
1356
+
1357
+ # Returns true if a given parameter key exists in the query.
1358
+ def has_key?(*args)
1359
+ @params.has_key?(*args)
1360
+ end
1361
+ alias key? has_key?
1362
+ alias include? has_key?
1363
+
1364
+ end # QueryExtension
1365
+
1366
+
1367
+ # Creates a new CGI instance.
1368
+ #
1369
+ # +type+ specifies which version of HTML to load the HTML generation
1370
+ # methods for. The following versions of HTML are supported:
1371
+ #
1372
+ # html3:: HTML 3.x
1373
+ # html4:: HTML 4.0
1374
+ # html4Tr:: HTML 4.0 Transitional
1375
+ # html4Fr:: HTML 4.0 with Framesets
1376
+ #
1377
+ # If not specified, no HTML generation methods will be loaded.
1378
+ #
1379
+ # If the CGI object is not created in a standard CGI call environment
1380
+ # (that is, it can't locate REQUEST_METHOD in its environment), then
1381
+ # it will run in "offline" mode. In this mode, it reads its parameters
1382
+ # from the command line or (failing that) from standard input. Otherwise,
1383
+ # cookies and other parameters are parsed automatically from the standard
1384
+ # CGI locations, which varies according to the REQUEST_METHOD.
1385
+ def initialize(type=nil)
1386
+ if defined?(MOD_RUBY) && !ENV['GATEWAY_INTERFACE']
1387
+ Apache.request.setup_cgi_env
1388
+ end
1389
+ ##
1390
+ #extend QueryExtension
1391
+ if defined?(CGI_PARAMS)
1392
+ warn "do not use CGI_PARAMS and CGI_COOKIES"
1393
+ @params = CGI_PARAMS.dup
1394
+ @cookies = CGI_COOKIES.dup
1395
+ @multipart = false
1396
+ else
1397
+ initialize_query() # set @params, @cookies, and @multipart
1398
+ end
1399
+ @output_cookies = nil
1400
+ @output_hidden = nil
1401
+ ##
1402
+ if type
1403
+ require 'cgialt/html' unless defined?(HtmlExtension)
1404
+ case type
1405
+ when 'html3'
1406
+ extend Html3; element_init()
1407
+ extend HtmlExtension
1408
+ when 'html4'
1409
+ extend Html4; element_init()
1410
+ extend HtmlExtension
1411
+ when 'html4Tr'
1412
+ extend Html4Tr; element_init()
1413
+ extend HtmlExtension
1414
+ when 'html4Fr'
1415
+ extend Html4Tr; element_init()
1416
+ extend Html4Fr; element_init()
1417
+ extend HtmlExtension
1418
+ end
1419
+ end
1420
+ end
1421
+ include QueryExtension
1422
+ #*** original
1423
+ #*def initialize(type = "query")
1424
+ #* if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
1425
+ #* Apache.request.setup_cgi_env
1426
+ #* end
1427
+ #*
1428
+ #* extend QueryExtension
1429
+ #* @multipart = false
1430
+ #* if defined?(CGI_PARAMS)
1431
+ #* warn "do not use CGI_PARAMS and CGI_COOKIES"
1432
+ #* @params = CGI_PARAMS.dup
1433
+ #* @cookies = CGI_COOKIES.dup
1434
+ #* else
1435
+ #* initialize_query() # set @params, @cookies
1436
+ #* end
1437
+ #* @output_cookies = nil
1438
+ #* @output_hidden = nil
1439
+ #*
1440
+ #* case type
1441
+ #* when "html3"
1442
+ #* extend Html3
1443
+ #* element_init()
1444
+ #* extend HtmlExtension
1445
+ #* when "html4"
1446
+ #* extend Html4
1447
+ #* element_init()
1448
+ #* extend HtmlExtension
1449
+ #* when "html4Tr"
1450
+ #* extend Html4Tr
1451
+ #* element_init()
1452
+ #* extend HtmlExtension
1453
+ #* when "html4Fr"
1454
+ #* extend Html4Tr
1455
+ #* element_init()
1456
+ #* extend Html4Fr
1457
+ #* element_init()
1458
+ #* extend HtmlExtension
1459
+ #* end
1460
+ #*end
1461
+ #*** /original
1462
+
1463
+ end # class CGI