cgialt 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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