class CGI

def self.accept_charset

Return the accept character set for all new CGI instances.
def self.accept_charset
  @@accept_charset
end

def self.accept_charset=(accept_charset)

Set the accept character set for all new CGI instances.
def self.accept_charset=(accept_charset)
  @@accept_charset=accept_charset
end

def self.parse(query)


# "name2" => ["value1", "value2", ...], ... }
# {"name1" => ["value1", "value2", ...],
params = CGI.parse("query_string")

Parse an HTTP query string into a hash of key=>value pairs.
def self.parse(query)
  params = {}
  query.split(/[&;]/).each do |pairs|
    key, value = pairs.split('=',2).collect{|v| CGI.unescape(v) }
    next unless key
    params[key] ||= []
    params[key].push(value) if value
  end
  params.default=[].freeze
  params
end

def _header_for_hash(options) #:nodoc:

:nodoc:
def _header_for_hash(options)  #:nodoc:
  buf = ''.dup
  ## add charset to option['type']
  options['type'] ||= 'text/html'
  charset = options.delete('charset')
  options['type'] += "; charset=#{charset}" if charset
  ## NPH
  options.delete('nph') if defined?(MOD_RUBY)
  if options.delete('nph') || nph?()
    protocol = _no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'
    status = options.delete('status')
    status = HTTP_STATUS[status] || _no_crlf_check(status) || '200 OK'
    buf << "#{protocol} #{status}#{EOL}"
    buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
    options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
    options['connection'] ||= 'close'
  end
  ## common headers
  status = options.delete('status')
  buf << "Status: #{HTTP_STATUS[status] || _no_crlf_check(status)}#{EOL}" if status
  server = options.delete('server')
  buf << "Server: #{_no_crlf_check(server)}#{EOL}" if server
  connection = options.delete('connection')
  buf << "Connection: #{_no_crlf_check(connection)}#{EOL}" if connection
  type = options.delete('type')
  buf << "Content-Type: #{_no_crlf_check(type)}#{EOL}" #if type
  length = options.delete('length')
  buf << "Content-Length: #{_no_crlf_check(length)}#{EOL}" if length
  language = options.delete('language')
  buf << "Content-Language: #{_no_crlf_check(language)}#{EOL}" if language
  expires = options.delete('expires')
  buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
  ## cookie
  if cookie = options.delete('cookie')
    case cookie
    when String, Cookie
      buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}"
    when Array
      arr = cookie
      arr.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
    when Hash
      hash = cookie
      hash.each_value {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
    end
  end
  if @output_cookies
    @output_cookies.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
  end
  ## other headers
  options.each do |key, value|
    buf << "#{_no_crlf_check(key)}: #{_no_crlf_check(value)}#{EOL}"
  end
  return buf
end # _header_for_hash

def _header_for_modruby(buf) #:nodoc:

:nodoc:
def _header_for_modruby(buf)  #:nodoc:
  request = Apache::request
  buf.scan(/([^:]+): (.+)#{EOL}/o) do |name, value|
    $stderr.printf("name:%s value:%s\n", name, value) if $DEBUG
    case name
    when 'Set-Cookie'
      request.headers_out.add(name, value)
    when /^status$/i
      request.status_line = value
      request.status = value.to_i
    when /^content-type$/i
      request.content_type = value
    when /^content-encoding$/i
      request.content_encoding = value
    when /^location$/i
      request.status = 302 if request.status == 200
      request.headers_out[name] = value
    else
      request.headers_out[name] = value
    end
  end
  request.send_http_header
  return ''
end

def _header_for_string(content_type) #:nodoc:

:nodoc:
def _header_for_string(content_type) #:nodoc:
  buf = ''.dup
  if nph?()
    buf << "#{_no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'} 200 OK#{EOL}"
    buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
    buf << "Server: #{_no_crlf_check($CGI_ENV['SERVER_SOFTWARE'])}#{EOL}"
    buf << "Connection: close#{EOL}"
  end
  buf << "Content-Type: #{_no_crlf_check(content_type)}#{EOL}"
  if @output_cookies
    @output_cookies.each {|cookie| buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" }
  end
  return buf
end # _header_for_string

def _no_crlf_check(str)

def _no_crlf_check(str)
  if str
    str = str.to_s
    raise "A HTTP status or header field must not include CR and LF" if str =~ /[\r\n]/
    str
  else
    nil
  end
end

def env_table

Synonym for ENV.
def env_table
  ENV
end

def http_header(options='text/html')

This method does not perform charset conversion.

"my_header2" => "my_value")
"my_header1" => "my_value",
"cookie" => [cookie1, cookie2],
"expires" => Time.now + 30,
"language" => "ja",
"length" => 103,
# Content-Type: text/html; charset=iso-2022-jp
"charset" => "iso-2022-jp",
"type" => "text/html",
"connection" => "close",
"server" => ENV['SERVER_SOFTWARE'],
# "status" => "200 GOOD",
"status" => "OK", # == "200 OK"
http_header("nph" => true,

# Content-Type: text/plain
http_header("text/plain")

# Content-Type: text/html
http_header

Examples:

Other headers can also be set; they are appended as key: value.

@output_cookies field.
These cookies are in addition to the cookies held in the

whose values are literal cookie strings or Cookie objects.
an Array of literal cookie strings or Cookie objects; or a hash all of
value can be the literal string of the cookie; a CGI::Cookie object;
A cookie or cookies, returned as one or more Set-Cookie headers. The
cookie::
object, returned as the Expires header.
expires:: The time on which the current content expires, as a +Time+
header.
language:: The language of the content, returned as the Content-Language
Content-Length header.
length:: The length of the content that will be sent, returned as the
instance, "close".
connection:: The connection type, returned as the Connection header (for
server:: The server software, returned as the Server header.

VARIANT_ALSO_VARIES:: 506 Variant Also Negotiates
BAD_GATEWAY:: 502 Bad Gateway
NOT_IMPLEMENTED:: 501 Method Not Implemented
SERVER_ERROR:: 500 Internal Server Error
PRECONDITION_FAILED:: 412 Precondition Failed
LENGTH_REQUIRED:: 411 Length Required
NOT_ACCEPTABLE:: 406 Not Acceptable
METHOD_NOT_ALLOWED:: 405 Method Not Allowed
NOT_FOUND:: 404 Not Found
FORBIDDEN:: 403 Forbidden
AUTH_REQUIRED:: 401 Authorization Required
BAD_REQUEST:: 400 Bad Request
NOT_MODIFIED:: 304 Not Modified
REDIRECT:: 302 Found
MOVED:: 301 Moved Permanently
MULTIPLE_CHOICES:: 300 Multiple Choices
PARTIAL_CONTENT:: 206 Partial Content
OK:: 200 OK

values are:
The HTTP status code as a String, returned as the Status header. The
status::
"connection" if not explicitly set.
code, and date; and sets default values for "server" and
nph:: A boolean value. If true, prepend protocol string and status
charset:: The charset of the body, appended to the Content-Type header.
type:: The Content-Type header. Defaults to "text/html"

A Hash of header values. The following header keys are recognized:
+headers_hash+::
If this form is used, this string is the Content-Type
+content_type_string+::

Includes the empty line that ends the header block.

http_header(headers_hash)
http_header(content_type_string="text/html")
:call-seq:

Create an HTTP header block as a string.
def http_header(options='text/html')
  if options.is_a?(String)
    content_type = options
    buf = _header_for_string(content_type)
  elsif options.is_a?(Hash)
    if options.size == 1 && options.has_key?('type')
      content_type = options['type']
      buf = _header_for_string(content_type)
    else
      buf = _header_for_hash(options.dup)
    end
  else
    raise ArgumentError.new("expected String or Hash but got #{options.class}")
  end
  if defined?(MOD_RUBY)
    _header_for_modruby(buf)
    return ''
  else
    buf << EOL    # empty line of separator
    return buf
  end
end # http_header()

def initialize(options = {}, &block) # :yields: name, value

:yields: name, value
CGI locations, which varies according to the REQUEST_METHOD.
cookies and other parameters are parsed automatically from the standard
from the command line or (failing that) from standard input. Otherwise,
then it will run in "offline" mode. In this mode, it reads its parameters
environment (that is, it can't locate REQUEST_METHOD in its environment),
Finally, if the CGI object is not created in a standard CGI call

end
encoding_errors[name] = value
cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
encoding_errors={}

encountered. For example:
If provided, the block is called when an invalid encoding is
block::

cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda

cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar

Default is 128 * 1024 * 1024 bytes

multipart data (e.g. consult a registered users upload allowance)
allows more complex logic to be set when determining whether to accept
a lambda, that will be evaluated when the request is parsed. This
Specifies maximum length of multipart data. Can be an Integer scalar or
:max_multipart_length::

"html5":: HTML 5
"html4Fr":: HTML 4.0 with Framesets
"html4Tr":: HTML 4.0 Transitional
"html4":: HTML 4.0
"html3":: HTML 3.x

The following values are supported:

use. If not specified, no HTML generation methods will be loaded.
String that specifies which version of the HTML generation methods to
:tag_maker::

cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"

when specified as "EUC-JP":

cgi=CGI.new # @accept_charset # => "UTF-8"

when not specified:

Example. Suppose @@accept_charset is "UTF-8"

CGI::InvalidEncoding will be raised.
@@accept_charset is used. If the encoding is not valid, a
specifies encoding of received query string. If omitted,
:accept_charset::

A Hash that recognizes three options:
options_hash::
will accept.
+options_hash+ form, since it also allows you specify the charset you
:tag_maker => tag_maker } Note that it is recommended to use the
This is the same as using the +options_hash+ form with the value {
tag_maker::


CGI.new(options_hash = {}) { block }
CGI.new(tag_maker) { block }
:call-seq:

Create a new CGI instance.
def initialize(options = {}, &block) # :yields: name, value
  @accept_charset_error_block = block_given? ? block : nil
  @options={
    :accept_charset=>@@accept_charset,
    :max_multipart_length=>@@max_multipart_length
  }
  case options
  when Hash
    @options.merge!(options)
  when String
    @options[:tag_maker]=options
  end
  @accept_charset=@options[:accept_charset]
  @max_multipart_length=@options[:max_multipart_length]
  if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
    Apache.request.setup_cgi_env
  end
  extend QueryExtension
  @multipart = false
  initialize_query()  # set @params, @cookies
  @output_cookies = nil
  @output_hidden = nil
  case @options[:tag_maker]
  when "html3"
    require_relative 'html'
    extend Html3
    extend HtmlExtension
  when "html4"
    require_relative 'html'
    extend Html4
    extend HtmlExtension
  when "html4Tr"
    require_relative 'html'
    extend Html4Tr
    extend HtmlExtension
  when "html4Fr"
    require_relative 'html'
    extend Html4Tr
    extend Html4Fr
    extend HtmlExtension
  when "html5"
    require_relative 'html'
    extend Html5
    extend HtmlExtension
  end
end

def nph? #:nodoc:

:nodoc:
def nph?  #:nodoc:
  return /IIS\/(\d+)/ =~ $CGI_ENV['SERVER_SOFTWARE'] && $1.to_i < 5
end

def out(options = "text/html") # :yield:

:yield:
# string
#
# my_header2: my_value
# my_header1: my_value
# Set-Cookie: bar
# Set-Cookie: foo
# Expires: Tue, 14 Jun 2011 17:35:54 GMT
# Content-Language: ja
# Content-Length: 6
# Content-Type: text/html; charset=iso-2022-jp
# Connection: close
# Server: Apache 2.2.0
# Date: Sun, 15 May 2011 17:35:54 GMT
# HTTP/1.1 200 OK
"my_header2" => "my_value") { "string" }
"my_header1" => "my_value",
"cookie" => [cookie1, cookie2],
"expires" => Time.now + (3600 * 24 * 30),
"language" => "ja",
# Content-Type: text/html; charset=iso-2022-jp
"charset" => "iso-2022-jp",
"type" => "text/html",
"connection" => "close",
"server" => ENV['SERVER_SOFTWARE'],
"status" => "OK", # == "200 OK"
cgi.out("nph" => true,

# string
#
# Content-Length: 6
# Content-Type: text/plain
cgi.out("text/plain") { "string" }

# string
#
# Content-Length: 6
# Content-Type: text/html
cgi.out{ "string" }
cgi = CGI.new

Example:

content is converted to this charset, and the language is set to "ja".
If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then the

is output (the content block is still required, but it is ignored).
If ENV['REQUEST_METHOD'] == "HEAD", then only the header

the String returned by the content block.
Content-Length is automatically calculated from the size of

A block is required and should evaluate to the body of the response.
+block+::
This is a Hash of headers, similar to that used by #http_header.
+headers_hash+::
If a string is passed, it is assumed to be the content type.
+content_type_string+::

cgi.out(headers_hash)
cgi.out(content_type_string='text/html')
:call-seq:

Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
def out(options = "text/html") # :yield:
  options = { "type" => options } if options.kind_of?(String)
  content = yield
  options["length"] = content.bytesize.to_s
  output = stdoutput
  output.binmode if defined? output.binmode
  output.print http_header(options)
  output.print content unless "HEAD" == env_table['REQUEST_METHOD']
end

def print(*options)

cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
cgi = CGI.new

Print an argument or list of arguments to the default output stream
def print(*options)
  stdoutput.print(*options)
end

def stdinput

Synonym for $stdin.
def stdinput
  $stdin
end

def stdoutput

Synonym for $stdout.
def stdoutput
  $stdout
end