summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <[email protected]>2025-05-08 19:21:47 +0900
committerHiroshi SHIBATA <[email protected]>2025-05-09 14:27:28 +0900
commit600c616507b258cdf9dbfbc822deb267f3202325 (patch)
treeaff8f5b0847a0301391f2dc5463049b0d7cd4e33
parenta61f51f66d7dff966dd17915c854fea08763722d (diff)
Removed CGI library without CGI::Escape features
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/13275
-rw-r--r--lib/cgi.rb298
-rw-r--r--lib/cgi/cgi.gemspec43
-rw-r--r--lib/cgi/cookie.rb210
-rw-r--r--lib/cgi/core.rb900
-rw-r--r--lib/cgi/html.rb1035
-rw-r--r--lib/cgi/session.rb562
-rw-r--r--lib/cgi/session/pstore.rb91
-rw-r--r--lib/cgi/util.rb44
-rw-r--r--test/cgi/test_cgi_cookie.rb211
-rw-r--r--test/cgi/test_cgi_core.rb307
-rw-r--r--test/cgi/test_cgi_header.rb192
-rw-r--r--test/cgi/test_cgi_modruby.rb149
-rw-r--r--test/cgi/test_cgi_multipart.rb385
-rw-r--r--test/cgi/test_cgi_session.rb169
-rw-r--r--test/cgi/test_cgi_tag_helper.rb355
-rw-r--r--test/cgi/test_cgi_util.rb12
-rw-r--r--test/cgi/testdata/file1.html10
-rw-r--r--test/cgi/testdata/large.pngbin156414 -> 0 bytes
-rw-r--r--test/cgi/testdata/small.pngbin82 -> 0 bytes
19 files changed, 0 insertions, 4973 deletions
diff --git a/lib/cgi.rb b/lib/cgi.rb
deleted file mode 100644
index d6f3ed5b49..0000000000
--- a/lib/cgi.rb
+++ /dev/null
@@ -1,298 +0,0 @@
-# frozen_string_literal: true
-#
-# cgi.rb - cgi support library
-#
-# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
-#
-# Copyright (C) 2000 Information-technology Promotion Agency, Japan
-#
-# Author: Wakou Aoyama <[email protected]>
-#
-# Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
-#
-
-# == Overview
-#
-# The Common Gateway Interface (CGI) is a simple protocol for passing an HTTP
-# request from a web server to a standalone program, and returning the output
-# to the web browser. Basically, a CGI program is called with the parameters
-# of the request passed in either in the environment (GET) or via $stdin
-# (POST), and everything it prints to $stdout is returned to the client.
-#
-# This file holds the CGI class. This class provides functionality for
-# retrieving HTTP request parameters, managing cookies, and generating HTML
-# output.
-#
-# The file CGI::Session provides session management functionality; see that
-# class for more details.
-#
-# See http://www.w3.org/CGI/ for more information on the CGI protocol.
-#
-# == Introduction
-#
-# CGI is a large class, providing several categories of methods, many of which
-# are mixed in from other modules. Some of the documentation is in this class,
-# some in the modules CGI::QueryExtension and CGI::HtmlExtension. See
-# CGI::Cookie for specific information on handling cookies, and cgi/session.rb
-# (CGI::Session) for information on sessions.
-#
-# For queries, CGI provides methods to get at environmental variables,
-# parameters, cookies, and multipart request data. For responses, CGI provides
-# methods for writing output and generating HTML.
-#
-# Read on for more details. Examples are provided at the bottom.
-#
-# == Queries
-#
-# The CGI class dynamically mixes in parameter and cookie-parsing
-# functionality, environmental variable access, and support for
-# parsing multipart requests (including uploaded files) from the
-# CGI::QueryExtension module.
-#
-# === Environmental Variables
-#
-# The standard CGI environmental variables are available as read-only
-# attributes of a CGI object. The following is a list of these variables:
-#
-#
-# AUTH_TYPE HTTP_HOST REMOTE_IDENT
-# CONTENT_LENGTH HTTP_NEGOTIATE REMOTE_USER
-# CONTENT_TYPE HTTP_PRAGMA REQUEST_METHOD
-# GATEWAY_INTERFACE HTTP_REFERER SCRIPT_NAME
-# HTTP_ACCEPT HTTP_USER_AGENT SERVER_NAME
-# HTTP_ACCEPT_CHARSET PATH_INFO SERVER_PORT
-# HTTP_ACCEPT_ENCODING PATH_TRANSLATED SERVER_PROTOCOL
-# HTTP_ACCEPT_LANGUAGE QUERY_STRING SERVER_SOFTWARE
-# HTTP_CACHE_CONTROL REMOTE_ADDR
-# HTTP_FROM REMOTE_HOST
-#
-#
-# For each of these variables, there is a corresponding attribute with the
-# same name, except all lower case and without a preceding HTTP_.
-# +content_length+ and +server_port+ are integers; the rest are strings.
-#
-# === Parameters
-#
-# The method #params() returns a hash of all parameters in the request as
-# name/value-list pairs, where the value-list is an Array of one or more
-# values. The CGI object itself also behaves as a hash of parameter names
-# to values, but only returns a single value (as a String) for each
-# parameter name.
-#
-# For instance, suppose the request contains the parameter
-# "favourite_colours" with the multiple values "blue" and "green". The
-# following behavior would occur:
-#
-# cgi.params["favourite_colours"] # => ["blue", "green"]
-# cgi["favourite_colours"] # => "blue"
-#
-# If a parameter does not exist, the former method will return an empty
-# array, the latter an empty string. The simplest way to test for existence
-# of a parameter is by the #has_key? method.
-#
-# === Cookies
-#
-# HTTP Cookies are automatically parsed from the request. They are available
-# from the #cookies() accessor, which returns a hash from cookie name to
-# CGI::Cookie object.
-#
-# === Multipart requests
-#
-# If a request's method is POST and its content type is multipart/form-data,
-# then it may contain uploaded files. These are stored by the QueryExtension
-# module in the parameters of the request. The parameter name is the name
-# attribute of the file input field, as usual. However, the value is not
-# a string, but an IO object, either an IOString for small files, or a
-# Tempfile for larger ones. This object also has the additional singleton
-# methods:
-#
-# #local_path():: the path of the uploaded file on the local filesystem
-# #original_filename():: the name of the file on the client computer
-# #content_type():: the content type of the file
-#
-# == Responses
-#
-# The CGI class provides methods for sending header and content output to
-# the HTTP client, and mixes in methods for programmatic HTML generation
-# from CGI::HtmlExtension and CGI::TagMaker modules. The precise version of HTML
-# to use for HTML generation is specified at object creation time.
-#
-# === Writing output
-#
-# The simplest way to send output to the HTTP client is using the #out() method.
-# This takes the HTTP headers as a hash parameter, and the body content
-# via a block. The headers can be generated as a string using the #http_header()
-# method. The output stream can be written directly to using the #print()
-# method.
-#
-# === Generating HTML
-#
-# Each HTML element has a corresponding method for generating that
-# element as a String. The name of this method is the same as that
-# of the element, all lowercase. The attributes of the element are
-# passed in as a hash, and the body as a no-argument block that evaluates
-# to a String. The HTML generation module knows which elements are
-# always empty, and silently drops any passed-in body. It also knows
-# which elements require matching closing tags and which don't. However,
-# it does not know what attributes are legal for which elements.
-#
-# There are also some additional HTML generation methods mixed in from
-# the CGI::HtmlExtension module. These include individual methods for the
-# different types of form inputs, and methods for elements that commonly
-# take particular attributes where the attributes can be directly specified
-# as arguments, rather than via a hash.
-#
-# === Utility HTML escape and other methods like a function.
-#
-# There are some utility tool defined in cgi/util.rb .
-# And when include, you can use utility methods like a function.
-#
-# == Examples of use
-#
-# === Get form values
-#
-# require "cgi"
-# cgi = CGI.new
-# value = cgi['field_name'] # <== value string for 'field_name'
-# # if not 'field_name' included, then return "".
-# fields = cgi.keys # <== array of field names
-#
-# # returns true if form has 'field_name'
-# cgi.has_key?('field_name')
-# cgi.has_key?('field_name')
-# cgi.include?('field_name')
-#
-# CAUTION! <code>cgi['field_name']</code> returned an Array with the old
-# cgi.rb(included in Ruby 1.6)
-#
-# === Get form values as hash
-#
-# require "cgi"
-# cgi = CGI.new
-# params = cgi.params
-#
-# cgi.params is a hash.
-#
-# cgi.params['new_field_name'] = ["value"] # add new param
-# cgi.params['field_name'] = ["new_value"] # change value
-# cgi.params.delete('field_name') # delete param
-# cgi.params.clear # delete all params
-#
-#
-# === Save form values to file
-#
-# require "pstore"
-# db = PStore.new("query.db")
-# db.transaction do
-# db["params"] = cgi.params
-# end
-#
-#
-# === Restore form values from file
-#
-# require "pstore"
-# db = PStore.new("query.db")
-# db.transaction do
-# cgi.params = db["params"]
-# end
-#
-#
-# === Get multipart form values
-#
-# require "cgi"
-# cgi = CGI.new
-# value = cgi['field_name'] # <== value string for 'field_name'
-# value.read # <== body of value
-# value.local_path # <== path to local file of value
-# value.original_filename # <== original filename of value
-# value.content_type # <== content_type of value
-#
-# and value has StringIO or Tempfile class methods.
-#
-# === Get cookie values
-#
-# require "cgi"
-# cgi = CGI.new
-# values = cgi.cookies['name'] # <== array of 'name'
-# # if not 'name' included, then return [].
-# names = cgi.cookies.keys # <== array of cookie names
-#
-# and cgi.cookies is a hash.
-#
-# === Get cookie objects
-#
-# require "cgi"
-# cgi = CGI.new
-# for name, cookie in cgi.cookies
-# cookie.expires = Time.now + 30
-# end
-# cgi.out("cookie" => cgi.cookies) {"string"}
-#
-# cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
-#
-# require "cgi"
-# cgi = CGI.new
-# cgi.cookies['name'].expires = Time.now + 30
-# cgi.out("cookie" => cgi.cookies['name']) {"string"}
-#
-# === Print http header and html string to $DEFAULT_OUTPUT ($>)
-#
-# require "cgi"
-# cgi = CGI.new("html4") # add HTML generation methods
-# cgi.out do
-# cgi.html do
-# cgi.head do
-# cgi.title { "TITLE" }
-# end +
-# cgi.body do
-# cgi.form("ACTION" => "uri") do
-# cgi.p do
-# cgi.textarea("get_text") +
-# cgi.br +
-# cgi.submit
-# end
-# end +
-# cgi.pre do
-# CGI.escapeHTML(
-# "params: #{cgi.params.inspect}\n" +
-# "cookies: #{cgi.cookies.inspect}\n" +
-# ENV.collect do |key, value|
-# "#{key} --> #{value}\n"
-# end.join("")
-# )
-# end
-# end
-# end
-# end
-#
-# # add HTML generation methods
-# CGI.new("html3") # html3.2
-# CGI.new("html4") # html4.01 (Strict)
-# CGI.new("html4Tr") # html4.01 Transitional
-# CGI.new("html4Fr") # html4.01 Frameset
-# CGI.new("html5") # html5
-#
-# === Some utility methods
-#
-# require 'cgi/util'
-# CGI.escapeHTML('Usage: foo "bar" <baz>')
-#
-#
-# === Some utility methods like a function
-#
-# require 'cgi/util'
-# include CGI::Util
-# escapeHTML('Usage: foo "bar" <baz>')
-# h('Usage: foo "bar" <baz>') # alias
-#
-#
-
-class CGI
- VERSION = "0.4.2"
-end
-
-require 'cgi/core'
-require 'cgi/cookie'
-require 'cgi/util'
-require 'cgi/escape'
-CGI.autoload(:HtmlExtension, 'cgi/html')
diff --git a/lib/cgi/cgi.gemspec b/lib/cgi/cgi.gemspec
deleted file mode 100644
index 5ef00d591d..0000000000
--- a/lib/cgi/cgi.gemspec
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
- end rescue nil
-end
-
-Gem::Specification.new do |spec|
- spec.name = name
- spec.version = version
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["[email protected]"]
-
- spec.summary = %q{Support for the Common Gateway Interface protocol.}
- spec.description = %q{Support for the Common Gateway Interface protocol.}
- spec.homepage = "https://github.com/ruby/cgi"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.required_ruby_version = ">= 2.5.0"
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- spec.executables = []
-
- spec.files = [
- "COPYING",
- "BSDL",
- "README.md",
- *Dir["lib{.rb,/**/*.rb}", "bin/*"] ]
-
- spec.require_paths = ["lib"]
-
- if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby'
- spec.platform = 'java'
- spec.require_paths << "ext/java/org/jruby/ext/cgi/escape/lib"
- spec.files += Dir["ext/java/**/*.{rb}", "lib/cgi/escape.jar"]
- else
- spec.files += Dir["ext/cgi/**/*.{rb,c,h,sh}", "ext/cgi/escape/depend", "lib/cgi/escape.so"]
- spec.extensions = ["ext/cgi/escape/extconf.rb"]
- end
-end
diff --git a/lib/cgi/cookie.rb b/lib/cgi/cookie.rb
deleted file mode 100644
index 1c4ef6a600..0000000000
--- a/lib/cgi/cookie.rb
+++ /dev/null
@@ -1,210 +0,0 @@
-# frozen_string_literal: true
-require_relative 'util'
-class CGI
- # Class representing an HTTP cookie.
- #
- # In addition to its specific fields and methods, a Cookie instance
- # is a delegator to the array of its values.
- #
- # See RFC 2965.
- #
- # == Examples of use
- # cookie1 = CGI::Cookie.new("name", "value1", "value2", ...)
- # cookie1 = CGI::Cookie.new("name" => "name", "value" => "value")
- # cookie1 = CGI::Cookie.new('name' => 'name',
- # 'value' => ['value1', 'value2', ...],
- # 'path' => 'path', # optional
- # 'domain' => 'domain', # optional
- # 'expires' => Time.now, # optional
- # 'secure' => true, # optional
- # 'httponly' => true # optional
- # )
- #
- # cgi.out("cookie" => [cookie1, cookie2]) { "string" }
- #
- # name = cookie1.name
- # values = cookie1.value
- # path = cookie1.path
- # domain = cookie1.domain
- # expires = cookie1.expires
- # secure = cookie1.secure
- # httponly = cookie1.httponly
- #
- # cookie1.name = 'name'
- # cookie1.value = ['value1', 'value2', ...]
- # cookie1.path = 'path'
- # cookie1.domain = 'domain'
- # cookie1.expires = Time.now + 30
- # cookie1.secure = true
- # cookie1.httponly = true
- class Cookie < Array
- @@accept_charset="UTF-8" unless defined?(@@accept_charset)
-
- TOKEN_RE = %r"\A[[!-~]&&[^()<>@,;:\\\"/?=\[\]{}]]+\z"
- PATH_VALUE_RE = %r"\A[[ -~]&&[^;]]*\z"
- DOMAIN_VALUE_RE = %r"\A\.?(?<label>(?!-)[-A-Za-z0-9]+(?<!-))(?:\.\g<label>)*\z"
-
- # Create a new CGI::Cookie object.
- #
- # :call-seq:
- # Cookie.new(name_string,*value)
- # Cookie.new(options_hash)
- #
- # +name_string+::
- # The name of the cookie; in this form, there is no #domain or
- # #expiration. The #path is gleaned from the +SCRIPT_NAME+ environment
- # variable, and #secure is false.
- # <tt>*value</tt>::
- # value or list of values of the cookie
- # +options_hash+::
- # A Hash of options to initialize this Cookie. Possible options are:
- #
- # name:: the name of the cookie. Required.
- # value:: the cookie's value or list of values.
- # path:: the path for which this cookie applies. Defaults to
- # the value of the +SCRIPT_NAME+ environment variable.
- # domain:: the domain for which this cookie applies.
- # expires:: the time at which this cookie expires, as a +Time+ object.
- # secure:: whether this cookie is a secure cookie or not (default to
- # false). Secure cookies are only transmitted to HTTPS
- # servers.
- # httponly:: whether this cookie is a HttpOnly cookie or not (default to
- # false). HttpOnly cookies are not available to javascript.
- #
- # These keywords correspond to attributes of the cookie object.
- def initialize(name = "", *value)
- @domain = nil
- @expires = nil
- if name.kind_of?(String)
- self.name = name
- self.path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
- @secure = false
- @httponly = false
- return super(value)
- end
-
- options = name
- unless options.has_key?("name")
- raise ArgumentError, "`name' required"
- end
-
- self.name = options["name"]
- value = Array(options["value"])
- # simple support for IE
- self.path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
- self.domain = options["domain"]
- @expires = options["expires"]
- @secure = options["secure"] == true
- @httponly = options["httponly"] == true
-
- super(value)
- end
-
- # Name of this cookie, as a +String+
- attr_reader :name
- # Set name of this cookie
- def name=(str)
- if str and !TOKEN_RE.match?(str)
- raise ArgumentError, "invalid name: #{str.dump}"
- end
- @name = str
- end
-
- # Path for which this cookie applies, as a +String+
- attr_reader :path
- # Set path for which this cookie applies
- def path=(str)
- if str and !PATH_VALUE_RE.match?(str)
- raise ArgumentError, "invalid path: #{str.dump}"
- end
- @path = str
- end
-
- # Domain for which this cookie applies, as a +String+
- attr_reader :domain
- # Set domain for which this cookie applies
- def domain=(str)
- if str and ((str = str.b).bytesize > 255 or !DOMAIN_VALUE_RE.match?(str))
- raise ArgumentError, "invalid domain: #{str.dump}"
- end
- @domain = str
- end
-
- # Time at which this cookie expires, as a +Time+
- attr_accessor :expires
- # True if this cookie is secure; false otherwise
- attr_reader :secure
- # True if this cookie is httponly; false otherwise
- attr_reader :httponly
-
- # Returns the value or list of values for this cookie.
- def value
- self
- end
-
- # Replaces the value of this cookie with a new value or list of values.
- def value=(val)
- replace(Array(val))
- end
-
- # Set whether the Cookie is a secure cookie or not.
- #
- # +val+ must be a boolean.
- def secure=(val)
- @secure = val if val == true or val == false
- @secure
- end
-
- # Set whether the Cookie is a httponly cookie or not.
- #
- # +val+ must be a boolean.
- def httponly=(val)
- @httponly = !!val
- end
-
- # Convert the Cookie to its string representation.
- def to_s
- val = collect{|v| CGI.escape(v) }.join("&")
- buf = "#{@name}=#{val}".dup
- buf << "; domain=#{@domain}" if @domain
- buf << "; path=#{@path}" if @path
- buf << "; expires=#{CGI.rfc1123_date(@expires)}" if @expires
- buf << "; secure" if @secure
- buf << "; HttpOnly" if @httponly
- buf
- end
-
- # Parse a raw cookie string into a hash of cookie-name=>Cookie
- # pairs.
- #
- # cookies = CGI::Cookie.parse("raw_cookie_string")
- # # { "name1" => cookie1, "name2" => cookie2, ... }
- #
- def self.parse(raw_cookie)
- cookies = Hash.new([])
- return cookies unless raw_cookie
-
- raw_cookie.split(/;\s?/).each do |pairs|
- name, values = pairs.split('=',2)
- next unless name and values
- values ||= ""
- values = values.split('&').collect{|v| CGI.unescape(v,@@accept_charset) }
- if cookies.has_key?(name)
- cookies[name].concat(values)
- else
- cookies[name] = Cookie.new(name, *values)
- end
- end
-
- cookies
- end
-
- # A summary of cookie string.
- def inspect
- "#<CGI::Cookie: #{self.to_s.inspect}>"
- end
-
- end # class Cookie
-end
-
-
diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
deleted file mode 100644
index e6c19bbaa5..0000000000
--- a/lib/cgi/core.rb
+++ /dev/null
@@ -1,900 +0,0 @@
-# frozen_string_literal: true
-#--
-# Methods for generating HTML, parsing CGI-related parameters, and
-# generating HTTP responses.
-#++
-class CGI
- unless const_defined?(:Escape)
- module Escape
- @@accept_charset = "UTF-8" # :nodoc:
- end
- include Escape
- extend Escape
- end
-
- $CGI_ENV = ENV # for FCGI support
-
- # String for carriage return
- CR = "\015"
-
- # String for linefeed
- LF = "\012"
-
- # Standard internet newline sequence
- EOL = CR + LF
-
- REVISION = '$Id$' #:nodoc:
-
- # Whether processing will be required in binary vs text
- NEEDS_BINMODE = File::BINARY != 0
-
- # Path separators in different environments.
- PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
-
- # HTTP status codes.
- HTTP_STATUS = {
- "OK" => "200 OK",
- "PARTIAL_CONTENT" => "206 Partial Content",
- "MULTIPLE_CHOICES" => "300 Multiple Choices",
- "MOVED" => "301 Moved Permanently",
- "REDIRECT" => "302 Found",
- "NOT_MODIFIED" => "304 Not Modified",
- "BAD_REQUEST" => "400 Bad Request",
- "AUTH_REQUIRED" => "401 Authorization Required",
- "FORBIDDEN" => "403 Forbidden",
- "NOT_FOUND" => "404 Not Found",
- "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
- "NOT_ACCEPTABLE" => "406 Not Acceptable",
- "LENGTH_REQUIRED" => "411 Length Required",
- "PRECONDITION_FAILED" => "412 Precondition Failed",
- "SERVER_ERROR" => "500 Internal Server Error",
- "NOT_IMPLEMENTED" => "501 Method Not Implemented",
- "BAD_GATEWAY" => "502 Bad Gateway",
- "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"
- }
-
- # :startdoc:
-
- # Synonym for ENV.
- def env_table
- ENV
- end
-
- # Synonym for $stdin.
- def stdinput
- $stdin
- end
-
- # Synonym for $stdout.
- def stdoutput
- $stdout
- end
-
- private :env_table, :stdinput, :stdoutput
-
- # Create an HTTP header block as a string.
- #
- # :call-seq:
- # http_header(content_type_string="text/html")
- # http_header(headers_hash)
- #
- # Includes the empty line that ends the header block.
- #
- # +content_type_string+::
- # If this form is used, this string is the <tt>Content-Type</tt>
- # +headers_hash+::
- # A Hash of header values. The following header keys are recognized:
- #
- # type:: The Content-Type header. Defaults to "text/html"
- # charset:: The charset of the body, appended to the Content-Type header.
- # nph:: A boolean value. If true, prepend protocol string and status
- # code, and date; and sets default values for "server" and
- # "connection" if not explicitly set.
- # status::
- # The HTTP status code as a String, returned as the Status header. The
- # values are:
- #
- # OK:: 200 OK
- # PARTIAL_CONTENT:: 206 Partial Content
- # MULTIPLE_CHOICES:: 300 Multiple Choices
- # MOVED:: 301 Moved Permanently
- # REDIRECT:: 302 Found
- # NOT_MODIFIED:: 304 Not Modified
- # BAD_REQUEST:: 400 Bad Request
- # AUTH_REQUIRED:: 401 Authorization Required
- # FORBIDDEN:: 403 Forbidden
- # NOT_FOUND:: 404 Not Found
- # METHOD_NOT_ALLOWED:: 405 Method Not Allowed
- # NOT_ACCEPTABLE:: 406 Not Acceptable
- # LENGTH_REQUIRED:: 411 Length Required
- # PRECONDITION_FAILED:: 412 Precondition Failed
- # SERVER_ERROR:: 500 Internal Server Error
- # NOT_IMPLEMENTED:: 501 Method Not Implemented
- # BAD_GATEWAY:: 502 Bad Gateway
- # VARIANT_ALSO_VARIES:: 506 Variant Also Negotiates
- #
- # server:: The server software, returned as the Server header.
- # connection:: The connection type, returned as the Connection header (for
- # instance, "close".
- # length:: The length of the content that will be sent, returned as the
- # Content-Length header.
- # language:: The language of the content, returned as the Content-Language
- # header.
- # expires:: The time on which the current content expires, as a +Time+
- # object, returned as the Expires header.
- # cookie::
- # A cookie or cookies, returned as one or more Set-Cookie headers. The
- # value can be the literal string of the cookie; a CGI::Cookie object;
- # an Array of literal cookie strings or Cookie objects; or a hash all of
- # whose values are literal cookie strings or Cookie objects.
- #
- # These cookies are in addition to the cookies held in the
- # @output_cookies field.
- #
- # Other headers can also be set; they are appended as key: value.
- #
- # Examples:
- #
- # http_header
- # # Content-Type: text/html
- #
- # http_header("text/plain")
- # # Content-Type: text/plain
- #
- # http_header("nph" => true,
- # "status" => "OK", # == "200 OK"
- # # "status" => "200 GOOD",
- # "server" => ENV['SERVER_SOFTWARE'],
- # "connection" => "close",
- # "type" => "text/html",
- # "charset" => "iso-2022-jp",
- # # Content-Type: text/html; charset=iso-2022-jp
- # "length" => 103,
- # "language" => "ja",
- # "expires" => Time.now + 30,
- # "cookie" => [cookie1, cookie2],
- # "my_header1" => "my_value",
- # "my_header2" => "my_value")
- #
- # This method does not perform charset conversion.
- 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()
-
- # This method is an alias for #http_header, when HTML5 tag maker is inactive.
- #
- # NOTE: use #http_header to create HTTP header blocks, this alias is only
- # provided for backwards compatibility.
- #
- # Using #header with the HTML5 tag maker will create a <header> element.
- alias :header :http_header
-
- 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
- private :_no_crlf_check
-
- 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
- private :_header_for_string
-
- 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
- private :_header_for_hash
-
- def nph? #:nodoc:
- return /IIS\/(\d+)/ =~ $CGI_ENV['SERVER_SOFTWARE'] && $1.to_i < 5
- end
-
- 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
- private :_header_for_modruby
-
- # Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
- #
- # :call-seq:
- # cgi.out(content_type_string='text/html')
- # cgi.out(headers_hash)
- #
- # +content_type_string+::
- # If a string is passed, it is assumed to be the content type.
- # +headers_hash+::
- # This is a Hash of headers, similar to that used by #http_header.
- # +block+::
- # A block is required and should evaluate to the body of the response.
- #
- # <tt>Content-Length</tt> is automatically calculated from the size of
- # the String returned by the content block.
- #
- # If <tt>ENV['REQUEST_METHOD'] == "HEAD"</tt>, then only the header
- # is output (the content block is still required, but it is ignored).
- #
- # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then the
- # content is converted to this charset, and the language is set to "ja".
- #
- # Example:
- #
- # cgi = CGI.new
- # cgi.out{ "string" }
- # # Content-Type: text/html
- # # Content-Length: 6
- # #
- # # string
- #
- # cgi.out("text/plain") { "string" }
- # # Content-Type: text/plain
- # # Content-Length: 6
- # #
- # # string
- #
- # cgi.out("nph" => true,
- # "status" => "OK", # == "200 OK"
- # "server" => ENV['SERVER_SOFTWARE'],
- # "connection" => "close",
- # "type" => "text/html",
- # "charset" => "iso-2022-jp",
- # # Content-Type: text/html; charset=iso-2022-jp
- # "language" => "ja",
- # "expires" => Time.now + (3600 * 24 * 30),
- # "cookie" => [cookie1, cookie2],
- # "my_header1" => "my_value",
- # "my_header2" => "my_value") { "string" }
- # # HTTP/1.1 200 OK
- # # Date: Sun, 15 May 2011 17:35:54 GMT
- # # Server: Apache 2.2.0
- # # Connection: close
- # # Content-Type: text/html; charset=iso-2022-jp
- # # Content-Length: 6
- # # Content-Language: ja
- # # Expires: Tue, 14 Jun 2011 17:35:54 GMT
- # # Set-Cookie: foo
- # # Set-Cookie: bar
- # # my_header1: my_value
- # # my_header2: my_value
- # #
- # # string
- 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
-
-
- # Print an argument or list of arguments to the default output stream
- #
- # cgi = CGI.new
- # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
- def print(*options)
- stdoutput.print(*options)
- end
-
- # Parse an HTTP query string into a hash of key=>value pairs.
- #
- # params = CGI.parse("query_string")
- # # {"name1" => ["value1", "value2", ...],
- # # "name2" => ["value1", "value2", ...], ... }
- #
- 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
-
- # Maximum content length of post data
- ##MAX_CONTENT_LENGTH = 2 * 1024 * 1024
-
- # Maximum number of request parameters when multipart
- MAX_MULTIPART_COUNT = 128
-
- # Mixin module that provides the following:
- #
- # 1. Access to the CGI environment variables as methods. See
- # documentation to the CGI class for a list of these variables. The
- # methods are exposed by removing the leading +HTTP_+ (if it exists) and
- # downcasing the name. For example, +auth_type+ will return the
- # environment variable +AUTH_TYPE+, and +accept+ will return the value
- # for +HTTP_ACCEPT+.
- #
- # 2. Access to cookies, including the cookies attribute.
- #
- # 3. Access to parameters, including the params attribute, and overloading
- # #[] to perform parameter value lookup by key.
- #
- # 4. The initialize_query method, for initializing the above
- # mechanisms, handling multipart forms, and allowing the
- # class to be used in "offline" mode.
- #
- module QueryExtension
-
- %w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
- define_method(env.delete_prefix('HTTP_').downcase) do
- (val = env_table[env]) && Integer(val)
- end
- end
-
- %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
- PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
- REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
- SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
-
- HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
- HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
- HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
- define_method(env.delete_prefix('HTTP_').downcase) do
- env_table[env]
- end
- end
-
- # Get the raw cookies as a string.
- def raw_cookie
- env_table["HTTP_COOKIE"]
- end
-
- # Get the raw RFC2965 cookies as a string.
- def raw_cookie2
- env_table["HTTP_COOKIE2"]
- end
-
- # Get the cookies as a hash of cookie-name=>Cookie pairs.
- attr_accessor :cookies
-
- # Get the parameters as a hash of name=>values pairs, where
- # values is an Array.
- attr_reader :params
-
- # Get the uploaded files as a hash of name=>values pairs
- attr_reader :files
-
- # Set all the parameters.
- def params=(hash)
- @params.clear
- @params.update(hash)
- end
-
- ##
- # Parses multipart form elements according to
- # http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
- #
- # Returns a hash of multipart form parameters with bodies of type StringIO or
- # Tempfile depending on whether the multipart form element exceeds 10 KB
- #
- # params[name => body]
- #
- def read_multipart(boundary, content_length)
- ## read first boundary
- stdin = stdinput
- first_line = "--#{boundary}#{EOL}"
- content_length -= first_line.bytesize
- status = stdin.read(first_line.bytesize)
- raise EOFError.new("no content body") unless status
- raise EOFError.new("bad content body") unless first_line == status
- ## parse and set params
- params = {}
- @files = {}
- boundary_rexp = /--#{Regexp.quote(boundary)}(#{EOL}|--)/
- boundary_size = "#{EOL}--#{boundary}#{EOL}".bytesize
- buf = ''.dup
- bufsize = 10 * 1024
- max_count = MAX_MULTIPART_COUNT
- n = 0
- tempfiles = []
- while true
- (n += 1) < max_count or raise StandardError.new("too many parameters.")
- ## create body (StringIO or Tempfile)
- body = create_body(bufsize < content_length)
- tempfiles << body if defined?(Tempfile) && body.kind_of?(Tempfile)
- class << body
- if method_defined?(:path)
- alias local_path path
- else
- def local_path
- nil
- end
- end
- attr_reader :original_filename, :content_type
- end
- ## find head and boundary
- head = nil
- separator = EOL * 2
- until head && matched = boundary_rexp.match(buf)
- if !head && pos = buf.index(separator)
- len = pos + EOL.bytesize
- head = buf[0, len]
- buf = buf[(pos+separator.bytesize)..-1]
- else
- if head && buf.size > boundary_size
- len = buf.size - boundary_size
- body.print(buf[0, len])
- buf[0, len] = ''
- end
- c = stdin.read(bufsize < content_length ? bufsize : content_length)
- raise EOFError.new("bad content body") if c.nil? || c.empty?
- buf << c
- content_length -= c.bytesize
- end
- end
- ## read to end of boundary
- m = matched
- len = m.begin(0)
- s = buf[0, len]
- if s =~ /(\r?\n)\z/
- s = buf[0, len - $1.bytesize]
- end
- body.print(s)
- buf = buf[m.end(0)..-1]
- boundary_end = m[1]
- content_length = -1 if boundary_end == '--'
- ## reset file cursor position
- body.rewind
- ## original filename
- /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/i.match(head)
- filename = $1 || $2 || ''.dup
- filename = CGI.unescape(filename) if unescape_filename?()
- body.instance_variable_set(:@original_filename, filename)
- ## content type
- /Content-Type: (.*)/i.match(head)
- (content_type = $1 || ''.dup).chomp!
- body.instance_variable_set(:@content_type, content_type)
- ## query parameter name
- /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head)
- name = $1 || $2 || ''
- if body.original_filename.empty?
- value=body.read.dup.force_encoding(@accept_charset)
- body.close! if defined?(Tempfile) && body.kind_of?(Tempfile)
- (params[name] ||= []) << value
- unless value.valid_encoding?
- if @accept_charset_error_block
- @accept_charset_error_block.call(name,value)
- else
- raise InvalidEncoding,"Accept-Charset encoding error"
- end
- end
- class << params[name].last;self;end.class_eval do
- define_method(:read){self}
- define_method(:original_filename){""}
- define_method(:content_type){""}
- end
- else
- (params[name] ||= []) << body
- @files[name]=body
- end
- ## break loop
- break if content_length == -1
- end
- raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/
- params.default = []
- params
- rescue Exception
- if tempfiles
- tempfiles.each {|t|
- if t.path
- t.close!
- end
- }
- end
- raise
- end # read_multipart
- private :read_multipart
- def create_body(is_large) #:nodoc:
- if is_large
- require 'tempfile'
- body = Tempfile.new('CGI', encoding: Encoding::ASCII_8BIT)
- else
- begin
- require 'stringio'
- body = StringIO.new("".b)
- rescue LoadError
- require 'tempfile'
- body = Tempfile.new('CGI', encoding: Encoding::ASCII_8BIT)
- end
- end
- body.binmode if defined? body.binmode
- return body
- end
- def unescape_filename? #:nodoc:
- user_agent = $CGI_ENV['HTTP_USER_AGENT']
- return false unless user_agent
- return /Mac/i.match(user_agent) && /Mozilla/i.match(user_agent) && !/MSIE/i.match(user_agent)
- end
-
- # offline mode. read name=value pairs on standard input.
- def read_from_cmdline
- require "shellwords"
-
- string = unless ARGV.empty?
- ARGV.join(' ')
- else
- if STDIN.tty?
- STDERR.print(
- %|(offline mode: enter name=value pairs on standard input)\n|
- )
- end
- array = readlines rescue nil
- if not array.nil?
- array.join(' ').gsub(/\n/n, '')
- else
- ""
- end
- end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26')
-
- words = Shellwords.shellwords(string)
-
- if words.find{|x| /=/n.match(x) }
- words.join('&')
- else
- words.join('+')
- end
- end
- private :read_from_cmdline
-
- # A wrapper class to use a StringIO object as the body and switch
- # to a TempFile when the passed threshold is passed.
- # Initialize the data from the query.
- #
- # Handles multipart forms (in particular, forms that involve file uploads).
- # Reads query parameters in the @params field, and cookies into @cookies.
- def initialize_query()
- if ("POST" == env_table['REQUEST_METHOD']) and
- %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?| =~ env_table['CONTENT_TYPE']
- current_max_multipart_length = @max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : @max_multipart_length
- raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length
- boundary = $1.dup
- @multipart = true
- @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
- else
- @multipart = false
- @params = CGI.parse(
- case env_table['REQUEST_METHOD']
- when "GET", "HEAD"
- if defined?(MOD_RUBY)
- Apache::request.args or ""
- else
- env_table['QUERY_STRING'] or ""
- end
- when "POST"
- stdinput.binmode if defined? stdinput.binmode
- stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
- else
- read_from_cmdline
- end.dup.force_encoding(@accept_charset)
- )
- unless Encoding.find(@accept_charset) == Encoding::ASCII_8BIT
- @params.each do |key,values|
- values.each do |value|
- unless value.valid_encoding?
- if @accept_charset_error_block
- @accept_charset_error_block.call(key,value)
- else
- raise InvalidEncoding,"Accept-Charset encoding error"
- end
- end
- end
- end
- end
- end
-
- @cookies = CGI::Cookie.parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
- end
- private :initialize_query
-
- # Returns whether the form contained multipart/form-data
- def multipart?
- @multipart
- end
-
- # Get the value for the parameter with a given key.
- #
- # If the parameter has multiple values, only the first will be
- # retrieved; use #params to get the array of values.
- def [](key)
- params = @params[key]
- return '' unless params
- value = params[0]
- if @multipart
- if value
- return value
- elsif defined? StringIO
- StringIO.new("".b)
- else
- Tempfile.new("CGI",encoding: Encoding::ASCII_8BIT)
- end
- else
- str = if value then value.dup else "" end
- str
- end
- end
-
- # Return all query parameter names as an array of String.
- def keys(*args)
- @params.keys(*args)
- end
-
- # Returns true if a given query string parameter exists.
- def has_key?(*args)
- @params.has_key?(*args)
- end
- alias key? has_key?
- alias include? has_key?
-
- end # QueryExtension
-
- # Exception raised when there is an invalid encoding detected
- class InvalidEncoding < Exception; end
-
- # @@accept_charset is default accept character set.
- # This default value default is "UTF-8"
- # If you want to change the default accept character set
- # when create a new CGI instance, set this:
- #
- # CGI.accept_charset = "EUC-JP"
- #
- @@accept_charset="UTF-8" if false # needed for rdoc?
-
- # Return the accept character set for all new CGI instances.
- def self.accept_charset
- @@accept_charset
- end
-
- # Set the accept character set for all new CGI instances.
- def self.accept_charset=(accept_charset)
- @@accept_charset=accept_charset
- end
-
- # Return the accept character set for this CGI instance.
- attr_reader :accept_charset
-
- # @@max_multipart_length is the maximum length of multipart data.
- # The default value is 128 * 1024 * 1024 bytes
- #
- # The default can be set to something else in the CGI constructor,
- # via the :max_multipart_length key in the option hash.
- #
- # See CGI.new documentation.
- #
- @@max_multipart_length= 128 * 1024 * 1024
-
- # Create a new CGI instance.
- #
- # :call-seq:
- # CGI.new(tag_maker) { block }
- # CGI.new(options_hash = {}) { block }
- #
- #
- # <tt>tag_maker</tt>::
- # This is the same as using the +options_hash+ form with the value <tt>{
- # :tag_maker => tag_maker }</tt> Note that it is recommended to use the
- # +options_hash+ form, since it also allows you specify the charset you
- # will accept.
- # <tt>options_hash</tt>::
- # A Hash that recognizes three options:
- #
- # <tt>:accept_charset</tt>::
- # specifies encoding of received query string. If omitted,
- # <tt>@@accept_charset</tt> is used. If the encoding is not valid, a
- # CGI::InvalidEncoding will be raised.
- #
- # Example. Suppose <tt>@@accept_charset</tt> is "UTF-8"
- #
- # when not specified:
- #
- # cgi=CGI.new # @accept_charset # => "UTF-8"
- #
- # when specified as "EUC-JP":
- #
- # cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"
- #
- # <tt>:tag_maker</tt>::
- # String that specifies which version of the HTML generation methods to
- # use. If not specified, no HTML generation methods will be loaded.
- #
- # The following values are supported:
- #
- # "html3":: HTML 3.x
- # "html4":: HTML 4.0
- # "html4Tr":: HTML 4.0 Transitional
- # "html4Fr":: HTML 4.0 with Framesets
- # "html5":: HTML 5
- #
- # <tt>:max_multipart_length</tt>::
- # Specifies maximum length of multipart data. Can be an Integer scalar or
- # a lambda, that will be evaluated when the request is parsed. This
- # allows more complex logic to be set when determining whether to accept
- # multipart data (e.g. consult a registered users upload allowance)
- #
- # Default is 128 * 1024 * 1024 bytes
- #
- # cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar
- #
- # cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda
- #
- # <tt>block</tt>::
- # If provided, the block is called when an invalid encoding is
- # encountered. For example:
- #
- # encoding_errors={}
- # cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
- # encoding_errors[name] = value
- # end
- #
- # Finally, if the CGI object is not created in a standard CGI call
- # environment (that is, it can't locate REQUEST_METHOD in its environment),
- # then it will run in "offline" mode. In this mode, it reads its parameters
- # from the command line or (failing that) from standard input. Otherwise,
- # cookies and other parameters are parsed automatically from the standard
- # CGI locations, which varies according to the REQUEST_METHOD.
- 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
-
-end # class CGI
diff --git a/lib/cgi/html.rb b/lib/cgi/html.rb
deleted file mode 100644
index 1543943320..0000000000
--- a/lib/cgi/html.rb
+++ /dev/null
@@ -1,1035 +0,0 @@
-# frozen_string_literal: true
-class CGI
- # Base module for HTML-generation mixins.
- #
- # Provides methods for code generation for tags following
- # the various DTD element types.
- module TagMaker # :nodoc:
-
- # Generate code for an element with required start and end tags.
- #
- # - -
- def nn_element(element, attributes = {})
- s = nOE_element(element, attributes)
- if block_given?
- s << yield.to_s
- end
- s << "</#{element.upcase}>"
- end
-
- def nn_element_def(attributes = {}, &block)
- nn_element(__callee__, attributes, &block)
- end
-
- # Generate code for an empty element.
- #
- # - O EMPTY
- def nOE_element(element, attributes = {})
- attributes={attributes=>nil} if attributes.kind_of?(String)
- s = "<#{element.upcase}".dup
- attributes.each do|name, value|
- next unless value
- s << " "
- s << CGI.escapeHTML(name.to_s)
- if value != true
- s << '="'
- s << CGI.escapeHTML(value.to_s)
- s << '"'
- end
- end
- s << ">"
- end
-
- def nOE_element_def(attributes = {}, &block)
- nOE_element(__callee__, attributes, &block)
- end
-
-
- # Generate code for an element for which the end (and possibly the
- # start) tag is optional.
- #
- # O O or - O
- def nO_element(element, attributes = {})
- s = nOE_element(element, attributes)
- if block_given?
- s << yield.to_s
- s << "</#{element.upcase}>"
- end
- s
- end
-
- def nO_element_def(attributes = {}, &block)
- nO_element(__callee__, attributes, &block)
- end
-
- end # TagMaker
-
-
- # Mixin module providing HTML generation methods.
- #
- # For example,
- # cgi.a("http://www.example.com") { "Example" }
- # # => "<A HREF=\"http://www.example.com\">Example</A>"
- #
- # Modules Html3, Html4, etc., contain more basic HTML-generation methods
- # (+#title+, +#h1+, etc.).
- #
- # See class CGI for a detailed example.
- #
- module HtmlExtension
-
-
- # Generate an Anchor element as a string.
- #
- # +href+ can either be a string, giving the URL
- # for the HREF attribute, or it can be a hash of
- # the element's attributes.
- #
- # The body of the element is the string returned by the no-argument
- # block passed in.
- #
- # a("http://www.example.com") { "Example" }
- # # => "<A HREF=\"http://www.example.com\">Example</A>"
- #
- # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" }
- # # => "<A HREF=\"http://www.example.com\" TARGET=\"_top\">Example</A>"
- #
- def a(href = "") # :yield:
- attributes = if href.kind_of?(String)
- { "HREF" => href }
- else
- href
- end
- super(attributes)
- end
-
- # Generate a Document Base URI element as a String.
- #
- # +href+ can either by a string, giving the base URL for the HREF
- # attribute, or it can be a has of the element's attributes.
- #
- # The passed-in no-argument block is ignored.
- #
- # base("http://www.example.com/cgi")
- # # => "<BASE HREF=\"http://www.example.com/cgi\">"
- def base(href = "") # :yield:
- attributes = if href.kind_of?(String)
- { "HREF" => href }
- else
- href
- end
- super(attributes)
- end
-
- # Generate a BlockQuote element as a string.
- #
- # +cite+ can either be a string, give the URI for the source of
- # the quoted text, or a hash, giving all attributes of the element,
- # or it can be omitted, in which case the element has no attributes.
- #
- # The body is provided by the passed-in no-argument block
- #
- # blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
- # #=> "<BLOCKQUOTE CITE=\"http://www.example.com/quotes/foo.html\">Foo!</BLOCKQUOTE>
- def blockquote(cite = {}) # :yield:
- attributes = if cite.kind_of?(String)
- { "CITE" => cite }
- else
- cite
- end
- super(attributes)
- end
-
-
- # Generate a Table Caption element as a string.
- #
- # +align+ can be a string, giving the alignment of the caption
- # (one of top, bottom, left, or right). It can be a hash of
- # all the attributes of the element. Or it can be omitted.
- #
- # The body of the element is provided by the passed-in no-argument block.
- #
- # caption("left") { "Capital Cities" }
- # # => <CAPTION ALIGN=\"left\">Capital Cities</CAPTION>
- def caption(align = {}) # :yield:
- attributes = if align.kind_of?(String)
- { "ALIGN" => align }
- else
- align
- end
- super(attributes)
- end
-
-
- # Generate a Checkbox Input element as a string.
- #
- # The attributes of the element can be specified as three arguments,
- # +name+, +value+, and +checked+. +checked+ is a boolean value;
- # if true, the CHECKED attribute will be included in the element.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # checkbox("name")
- # # = checkbox("NAME" => "name")
- #
- # checkbox("name", "value")
- # # = checkbox("NAME" => "name", "VALUE" => "value")
- #
- # checkbox("name", "value", true)
- # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true)
- def checkbox(name = "", value = nil, checked = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "checkbox", "NAME" => name,
- "VALUE" => value, "CHECKED" => checked }
- else
- name["TYPE"] = "checkbox"
- name
- end
- input(attributes)
- end
-
- # Generate a sequence of checkbox elements, as a String.
- #
- # The checkboxes will all have the same +name+ attribute.
- # Each checkbox is followed by a label.
- # There will be one checkbox for each value. Each value
- # can be specified as a String, which will be used both
- # as the value of the VALUE attribute and as the label
- # for that checkbox. A single-element array has the
- # same effect.
- #
- # Each value can also be specified as a three-element array.
- # The first element is the VALUE attribute; the second is the
- # label; and the third is a boolean specifying whether this
- # checkbox is CHECKED.
- #
- # Each value can also be specified as a two-element
- # array, by omitting either the value element (defaults
- # to the same as the label), or the boolean checked element
- # (defaults to false).
- #
- # checkbox_group("name", "foo", "bar", "baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
- #
- # checkbox_group("name", ["foo"], ["bar", true], "baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
- #
- # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="1">Foo
- # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="2">Bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="Baz">Baz
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => ["foo", "bar", "baz"])
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => [["foo"], ["bar", true], "baz"])
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- def checkbox_group(name = "", *values)
- if name.kind_of?(Hash)
- values = name["VALUES"]
- name = name["NAME"]
- end
- values.collect{|value|
- if value.kind_of?(String)
- checkbox(name, value) + value
- else
- if value[-1] == true || value[-1] == false
- checkbox(name, value[0], value[-1]) +
- value[-2]
- else
- checkbox(name, value[0]) +
- value[-1]
- end
- end
- }.join
- end
-
-
- # Generate an File Upload Input element as a string.
- #
- # The attributes of the element can be specified as three arguments,
- # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length
- # of the file's _name_, not of the file's _contents_.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # See #multipart_form() for forms that include file uploads.
- #
- # file_field("name")
- # # <INPUT TYPE="file" NAME="name" SIZE="20">
- #
- # file_field("name", 40)
- # # <INPUT TYPE="file" NAME="name" SIZE="40">
- #
- # file_field("name", 40, 100)
- # # <INPUT TYPE="file" NAME="name" SIZE="40" MAXLENGTH="100">
- #
- # file_field("NAME" => "name", "SIZE" => 40)
- # # <INPUT TYPE="file" NAME="name" SIZE="40">
- def file_field(name = "", size = 20, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "file", "NAME" => name,
- "SIZE" => size.to_s }
- else
- name["TYPE"] = "file"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
-
- # Generate a Form element as a string.
- #
- # +method+ should be either "get" or "post", and defaults to the latter.
- # +action+ defaults to the current CGI script name. +enctype+
- # defaults to "application/x-www-form-urlencoded".
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # See also #multipart_form() for forms that include file uploads.
- #
- # form{ "string" }
- # # <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("get") { "string" }
- # # <FORM METHOD="get" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("get", "url") { "string" }
- # # <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" }
- # # <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
- def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded")
- attributes = if method.kind_of?(String)
- { "METHOD" => method, "ACTION" => action,
- "ENCTYPE" => enctype }
- else
- unless method.has_key?("METHOD")
- method["METHOD"] = "post"
- end
- unless method.has_key?("ENCTYPE")
- method["ENCTYPE"] = enctype
- end
- method
- end
- if block_given?
- body = yield
- else
- body = ""
- end
- if @output_hidden
- body << @output_hidden.collect{|k,v|
- "<INPUT TYPE=\"HIDDEN\" NAME=\"#{k}\" VALUE=\"#{v}\">"
- }.join
- end
- super(attributes){body}
- end
-
- # Generate a Hidden Input element as a string.
- #
- # The attributes of the element can be specified as two arguments,
- # +name+ and +value+.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # hidden("name")
- # # <INPUT TYPE="hidden" NAME="name">
- #
- # hidden("name", "value")
- # # <INPUT TYPE="hidden" NAME="name" VALUE="value">
- #
- # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo")
- # # <INPUT TYPE="hidden" NAME="name" VALUE="value" ID="foo">
- def hidden(name = "", value = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "hidden", "NAME" => name, "VALUE" => value }
- else
- name["TYPE"] = "hidden"
- name
- end
- input(attributes)
- end
-
- # Generate a top-level HTML element as a string.
- #
- # The attributes of the element are specified as a hash. The
- # pseudo-attribute "PRETTY" can be used to specify that the generated
- # HTML string should be indented. "PRETTY" can also be specified as
- # a string as the sole argument to this method. The pseudo-attribute
- # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it
- # should include the entire text of this tag, including angle brackets.
- #
- # The body of the html element is supplied as a block.
- #
- # html{ "string" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>string</HTML>
- #
- # html("LANG" => "ja") { "string" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML LANG="ja">string</HTML>
- #
- # html("DOCTYPE" => false) { "string" }
- # # <HTML>string</HTML>
- #
- # html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">') { "string" }
- # # <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML>string</HTML>
- #
- # html("PRETTY" => " ") { "<BODY></BODY>" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # html("PRETTY" => "\t") { "<BODY></BODY>" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # html("PRETTY") { "<BODY></BODY>" }
- # # = html("PRETTY" => " ") { "<BODY></BODY>" }
- #
- # html(if $VERBOSE then "PRETTY" end) { "HTML string" }
- #
- def html(attributes = {}) # :yield:
- if nil == attributes
- attributes = {}
- elsif "PRETTY" == attributes
- attributes = { "PRETTY" => true }
- end
- pretty = attributes.delete("PRETTY")
- pretty = " " if true == pretty
- buf = "".dup
-
- if attributes.has_key?("DOCTYPE")
- if attributes["DOCTYPE"]
- buf << attributes.delete("DOCTYPE")
- else
- attributes.delete("DOCTYPE")
- end
- else
- buf << doctype
- end
-
- buf << super(attributes)
-
- if pretty
- CGI.pretty(buf, pretty)
- else
- buf
- end
-
- end
-
- # Generate an Image Button Input element as a string.
- #
- # +src+ is the URL of the image to use for the button. +name+
- # is the input name. +alt+ is the alternative text for the image.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # image_button("url")
- # # <INPUT TYPE="image" SRC="url">
- #
- # image_button("url", "name", "string")
- # # <INPUT TYPE="image" SRC="url" NAME="name" ALT="string">
- #
- # image_button("SRC" => "url", "ALT" => "string")
- # # <INPUT TYPE="image" SRC="url" ALT="string">
- def image_button(src = "", name = nil, alt = nil)
- attributes = if src.kind_of?(String)
- { "TYPE" => "image", "SRC" => src, "NAME" => name,
- "ALT" => alt }
- else
- src["TYPE"] = "image"
- src["SRC"] ||= ""
- src
- end
- input(attributes)
- end
-
-
- # Generate an Image element as a string.
- #
- # +src+ is the URL of the image. +alt+ is the alternative text for
- # the image. +width+ is the width of the image, and +height+ is
- # its height.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # img("src", "alt", 100, 50)
- # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
- #
- # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50)
- # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
- def img(src = "", alt = "", width = nil, height = nil)
- attributes = if src.kind_of?(String)
- { "SRC" => src, "ALT" => alt }
- else
- src
- end
- attributes["WIDTH"] = width.to_s if width
- attributes["HEIGHT"] = height.to_s if height
- super(attributes)
- end
-
-
- # Generate a Form element with multipart encoding as a String.
- #
- # Multipart encoding is used for forms that include file uploads.
- #
- # +action+ is the action to perform. +enctype+ is the encoding
- # type, which defaults to "multipart/form-data".
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # multipart_form{ "string" }
- # # <FORM METHOD="post" ENCTYPE="multipart/form-data">string</FORM>
- #
- # multipart_form("url") { "string" }
- # # <FORM METHOD="post" ACTION="url" ENCTYPE="multipart/form-data">string</FORM>
- def multipart_form(action = nil, enctype = "multipart/form-data")
- attributes = if action == nil
- { "METHOD" => "post", "ENCTYPE" => enctype }
- elsif action.kind_of?(String)
- { "METHOD" => "post", "ACTION" => action,
- "ENCTYPE" => enctype }
- else
- unless action.has_key?("METHOD")
- action["METHOD"] = "post"
- end
- unless action.has_key?("ENCTYPE")
- action["ENCTYPE"] = enctype
- end
- action
- end
- if block_given?
- form(attributes){ yield }
- else
- form(attributes)
- end
- end
-
-
- # Generate a Password Input element as a string.
- #
- # +name+ is the name of the input field. +value+ is its default
- # value. +size+ is the size of the input field display. +maxlength+
- # is the maximum length of the inputted password.
- #
- # Alternatively, attributes can be specified as a hash.
- #
- # password_field("name")
- # # <INPUT TYPE="password" NAME="name" SIZE="40">
- #
- # password_field("name", "value")
- # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="40">
- #
- # password_field("password", "value", 80, 200)
- # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
- #
- # password_field("NAME" => "name", "VALUE" => "value")
- # # <INPUT TYPE="password" NAME="name" VALUE="value">
- def password_field(name = "", value = nil, size = 40, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "password", "NAME" => name,
- "VALUE" => value, "SIZE" => size.to_s }
- else
- name["TYPE"] = "password"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
- # Generate a Select element as a string.
- #
- # +name+ is the name of the element. The +values+ are the options that
- # can be selected from the Select menu. Each value can be a String or
- # a one, two, or three-element Array. If a String or a one-element
- # Array, this is both the value of that option and the text displayed for
- # it. If a three-element Array, the elements are the option value, displayed
- # text, and a boolean value specifying whether this option starts as selected.
- # The two-element version omits either the option value (defaults to the same
- # as the display text) or the boolean selected specifier (defaults to false).
- #
- # The attributes and options can also be specified as a hash. In this
- # case, options are specified as an array of values as described above,
- # with the hash key of "VALUES".
- #
- # popup_menu("name", "foo", "bar", "baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="foo">foo</OPTION>
- # # <OPTION VALUE="bar">bar</OPTION>
- # # <OPTION VALUE="baz">baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("name", ["foo"], ["bar", true], "baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="foo">foo</OPTION>
- # # <OPTION VALUE="bar" SELECTED>bar</OPTION>
- # # <OPTION VALUE="baz">baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="1">Foo</OPTION>
- # # <OPTION SELECTED VALUE="2">Bar</OPTION>
- # # <OPTION VALUE="Baz">Baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true,
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- # # <SELECT NAME="name" MULTIPLE SIZE="2">
- # # <OPTION VALUE="1">Foo</OPTION>
- # # <OPTION SELECTED VALUE="2">Bar</OPTION>
- # # <OPTION VALUE="Baz">Baz</OPTION>
- # # </SELECT>
- def popup_menu(name = "", *values)
-
- if name.kind_of?(Hash)
- values = name["VALUES"]
- size = name["SIZE"].to_s if name["SIZE"]
- multiple = name["MULTIPLE"]
- name = name["NAME"]
- else
- size = nil
- multiple = nil
- end
-
- select({ "NAME" => name, "SIZE" => size,
- "MULTIPLE" => multiple }){
- values.collect{|value|
- if value.kind_of?(String)
- option({ "VALUE" => value }){ value }
- else
- if value[value.size - 1] == true
- option({ "VALUE" => value[0], "SELECTED" => true }){
- value[value.size - 2]
- }
- else
- option({ "VALUE" => value[0] }){
- value[value.size - 1]
- }
- end
- end
- }.join
- }
-
- end
-
- # Generates a radio-button Input element.
- #
- # +name+ is the name of the input field. +value+ is the value of
- # the field if checked. +checked+ specifies whether the field
- # starts off checked.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # radio_button("name", "value")
- # # <INPUT TYPE="radio" NAME="name" VALUE="value">
- #
- # radio_button("name", "value", true)
- # # <INPUT TYPE="radio" NAME="name" VALUE="value" CHECKED>
- #
- # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo")
- # # <INPUT TYPE="radio" NAME="name" VALUE="value" ID="foo">
- def radio_button(name = "", value = nil, checked = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "radio", "NAME" => name,
- "VALUE" => value, "CHECKED" => checked }
- else
- name["TYPE"] = "radio"
- name
- end
- input(attributes)
- end
-
- # Generate a sequence of radio button Input elements, as a String.
- #
- # This works the same as #checkbox_group(). However, it is not valid
- # to have more than one radiobutton in a group checked.
- #
- # radio_group("name", "foo", "bar", "baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="radio" NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
- #
- # radio_group("name", ["foo"], ["bar", true], "baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
- #
- # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="1">Foo
- # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="2">Bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="Baz">Baz
- #
- # radio_group("NAME" => "name",
- # "VALUES" => ["foo", "bar", "baz"])
- #
- # radio_group("NAME" => "name",
- # "VALUES" => [["foo"], ["bar", true], "baz"])
- #
- # radio_group("NAME" => "name",
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- def radio_group(name = "", *values)
- if name.kind_of?(Hash)
- values = name["VALUES"]
- name = name["NAME"]
- end
- values.collect{|value|
- if value.kind_of?(String)
- radio_button(name, value) + value
- else
- if value[-1] == true || value[-1] == false
- radio_button(name, value[0], value[-1]) +
- value[-2]
- else
- radio_button(name, value[0]) +
- value[-1]
- end
- end
- }.join
- end
-
- # Generate a reset button Input element, as a String.
- #
- # This resets the values on a form to their initial values. +value+
- # is the text displayed on the button. +name+ is the name of this button.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # reset
- # # <INPUT TYPE="reset">
- #
- # reset("reset")
- # # <INPUT TYPE="reset" VALUE="reset">
- #
- # reset("VALUE" => "reset", "ID" => "foo")
- # # <INPUT TYPE="reset" VALUE="reset" ID="foo">
- def reset(value = nil, name = nil)
- attributes = if (not value) or value.kind_of?(String)
- { "TYPE" => "reset", "VALUE" => value, "NAME" => name }
- else
- value["TYPE"] = "reset"
- value
- end
- input(attributes)
- end
-
- alias scrolling_list popup_menu
-
- # Generate a submit button Input element, as a String.
- #
- # +value+ is the text to display on the button. +name+ is the name
- # of the input.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # submit
- # # <INPUT TYPE="submit">
- #
- # submit("ok")
- # # <INPUT TYPE="submit" VALUE="ok">
- #
- # submit("ok", "button1")
- # # <INPUT TYPE="submit" VALUE="ok" NAME="button1">
- #
- # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo")
- # # <INPUT TYPE="submit" VALUE="ok" NAME="button1" ID="foo">
- def submit(value = nil, name = nil)
- attributes = if (not value) or value.kind_of?(String)
- { "TYPE" => "submit", "VALUE" => value, "NAME" => name }
- else
- value["TYPE"] = "submit"
- value
- end
- input(attributes)
- end
-
- # Generate a text field Input element, as a String.
- #
- # +name+ is the name of the input field. +value+ is its initial
- # value. +size+ is the size of the input area. +maxlength+
- # is the maximum length of input accepted.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # text_field("name")
- # # <INPUT TYPE="text" NAME="name" SIZE="40">
- #
- # text_field("name", "value")
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="40">
- #
- # text_field("name", "value", 80)
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80">
- #
- # text_field("name", "value", 80, 200)
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
- #
- # text_field("NAME" => "name", "VALUE" => "value")
- # # <INPUT TYPE="text" NAME="name" VALUE="value">
- def text_field(name = "", value = nil, size = 40, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "text", "NAME" => name, "VALUE" => value,
- "SIZE" => size.to_s }
- else
- name["TYPE"] = "text"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
- # Generate a TextArea element, as a String.
- #
- # +name+ is the name of the textarea. +cols+ is the number of
- # columns and +rows+ is the number of rows in the display.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # The body is provided by the passed-in no-argument block
- #
- # textarea("name")
- # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10)
- #
- # textarea("name", 40, 5)
- # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5)
- def textarea(name = "", cols = 70, rows = 10) # :yield:
- attributes = if name.kind_of?(String)
- { "NAME" => name, "COLS" => cols.to_s,
- "ROWS" => rows.to_s }
- else
- name
- end
- super(attributes)
- end
-
- end # HtmlExtension
-
-
- # Mixin module for HTML version 3 generation methods.
- module Html3 # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">|
- end
-
- instance_method(:nn_element_def).tap do |m|
- # - -
- for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG
- DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV CENTER MAP
- APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT TABLE TITLE
- STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE
- CAPTION ]
- define_method(element.downcase, m)
- end
- end
-
- instance_method(:nOE_element_def).tap do |m|
- # - O EMPTY
- for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
- ISINDEX META ]
- define_method(element.downcase, m)
- end
- end
-
- instance_method(:nO_element_def).tap do |m|
- # O O or - O
- for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION TR
- TH TD ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html3
-
-
- # Mixin module for HTML version 4 generation methods.
- module Html4 # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">|
- end
-
- # Initialize the HTML generation methods for this version.
- # - -
- instance_method(:nn_element_def).tap do |m|
- for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD
- VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
- H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP
- FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
- TEXTAREA FORM A BLOCKQUOTE CAPTION ]
- define_method(element.downcase, m)
- end
- end
-
- # - O EMPTY
- instance_method(:nOE_element_def).tap do |m|
- for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ]
- define_method(element.downcase, m)
- end
- end
-
- # O O or - O
- instance_method(:nO_element_def).tap do |m|
- for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
- COLGROUP TR TH TD HEAD ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html4
-
-
- # Mixin module for HTML version 4 transitional generation methods.
- module Html4Tr # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">|
- end
-
- # Initialise the HTML generation methods for this version.
- # - -
- instance_method(:nn_element_def).tap do |m|
- for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN
- CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO
- ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q
- INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET
- LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT
- NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ]
- define_method(element.downcase, m)
- end
- end
-
- # - O EMPTY
- instance_method(:nOE_element_def).tap do |m|
- for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
- COL ISINDEX META ]
- define_method(element.downcase, m)
- end
- end
-
- # O O or - O
- instance_method(:nO_element_def).tap do |m|
- for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
- COLGROUP TR TH TD HEAD ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html4Tr
-
-
- # Mixin module for generating HTML version 4 with framesets.
- module Html4Fr # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">|
- end
-
- # Initialise the HTML generation methods for this version.
- # - -
- instance_method(:nn_element_def).tap do |m|
- for element in %w[ FRAMESET ]
- define_method(element.downcase, m)
- end
- end
-
- # - O EMPTY
- instance_method(:nOE_element_def).tap do |m|
- for element in %w[ FRAME ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html4Fr
-
-
- # Mixin module for HTML version 5 generation methods.
- module Html5 # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML>|
- end
-
- # Initialise the HTML generation methods for this version.
- # - -
- instance_method(:nn_element_def).tap do |m|
- for element in %w[ SECTION NAV ARTICLE ASIDE HGROUP HEADER
- FOOTER FIGURE FIGCAPTION S TIME U MARK RUBY BDI IFRAME
- VIDEO AUDIO CANVAS DATALIST OUTPUT PROGRESS METER DETAILS
- SUMMARY MENU DIALOG I B SMALL EM STRONG DFN CODE SAMP KBD
- VAR CITE ABBR SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
- H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT
- FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
- TEXTAREA FORM A BLOCKQUOTE CAPTION ]
- define_method(element.downcase, m)
- end
- end
-
- # - O EMPTY
- instance_method(:nOE_element_def).tap do |m|
- for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META
- COMMAND EMBED KEYGEN SOURCE TRACK WBR ]
- define_method(element.downcase, m)
- end
- end
-
- # O O or - O
- instance_method(:nO_element_def).tap do |m|
- for element in %w[ HTML HEAD BODY P DT DD LI OPTION THEAD TFOOT TBODY
- OPTGROUP COLGROUP RT RP TR TH TD ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html5
-
- class HTML3
- include Html3
- include HtmlExtension
- end
-
- class HTML4
- include Html4
- include HtmlExtension
- end
-
- class HTML4Tr
- include Html4Tr
- include HtmlExtension
- end
-
- class HTML4Fr
- include Html4Tr
- include Html4Fr
- include HtmlExtension
- end
-
- class HTML5
- include Html5
- include HtmlExtension
- end
-
-end
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
deleted file mode 100644
index aab60869bb..0000000000
--- a/lib/cgi/session.rb
+++ /dev/null
@@ -1,562 +0,0 @@
-# frozen_string_literal: true
-#
-# cgi/session.rb - session support for cgi scripts
-#
-# Copyright (C) 2001 Yukihiro "Matz" Matsumoto
-# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
-# Copyright (C) 2000 Information-technology Promotion Agency, Japan
-#
-# Author: Yukihiro "Matz" Matsumoto
-#
-# Documentation: William Webber ([email protected])
-
-require 'cgi'
-require 'tmpdir'
-
-class CGI
-
- # == Overview
- #
- # This file provides the CGI::Session class, which provides session
- # support for CGI scripts. A session is a sequence of HTTP requests
- # and responses linked together and associated with a single client.
- # Information associated with the session is stored
- # on the server between requests. A session id is passed between client
- # and server with every request and response, transparently
- # to the user. This adds state information to the otherwise stateless
- # HTTP request/response protocol.
- #
- # == Lifecycle
- #
- # A CGI::Session instance is created from a CGI object. By default,
- # this CGI::Session instance will start a new session if none currently
- # exists, or continue the current session for this client if one does
- # exist. The +new_session+ option can be used to either always or
- # never create a new session. See #new() for more details.
- #
- # #delete() deletes a session from session storage. It
- # does not however remove the session id from the client. If the client
- # makes another request with the same id, the effect will be to start
- # a new session with the old session's id.
- #
- # == Setting and retrieving session data.
- #
- # The Session class associates data with a session as key-value pairs.
- # This data can be set and retrieved by indexing the Session instance
- # using '[]', much the same as hashes (although other hash methods
- # are not supported).
- #
- # When session processing has been completed for a request, the
- # session should be closed using the close() method. This will
- # store the session's state to persistent storage. If you want
- # to store the session's state to persistent storage without
- # finishing session processing for this request, call the update()
- # method.
- #
- # == Storing session state
- #
- # The caller can specify what form of storage to use for the session's
- # data with the +database_manager+ option to CGI::Session::new. The
- # following storage classes are provided as part of the standard library:
- #
- # CGI::Session::FileStore:: stores data as plain text in a flat file. Only
- # works with String data. This is the default
- # storage type.
- # CGI::Session::MemoryStore:: stores data in an in-memory hash. The data
- # only persists for as long as the current Ruby
- # interpreter instance does.
- # CGI::Session::PStore:: stores data in Marshalled format. Provided by
- # cgi/session/pstore.rb. Supports data of any type,
- # and provides file-locking and transaction support.
- #
- # Custom storage types can also be created by defining a class with
- # the following methods:
- #
- # new(session, options)
- # restore # returns hash of session data.
- # update
- # close
- # delete
- #
- # Changing storage type mid-session does not work. Note in particular
- # that by default the FileStore and PStore session data files have the
- # same name. If your application switches from one to the other without
- # making sure that filenames will be different
- # and clients still have old sessions lying around in cookies, then
- # things will break nastily!
- #
- # == Maintaining the session id.
- #
- # Most session state is maintained on the server. However, a session
- # id must be passed backwards and forwards between client and server
- # to maintain a reference to this session state.
- #
- # The simplest way to do this is via cookies. The CGI::Session class
- # provides transparent support for session id communication via cookies
- # if the client has cookies enabled.
- #
- # If the client has cookies disabled, the session id must be included
- # as a parameter of all requests sent by the client to the server. The
- # CGI::Session class in conjunction with the CGI class will transparently
- # add the session id as a hidden input field to all forms generated
- # using the CGI#form() HTML generation method. No built-in support is
- # provided for other mechanisms, such as URL re-writing. The caller is
- # responsible for extracting the session id from the session_id
- # attribute and manually encoding it in URLs and adding it as a hidden
- # input to HTML forms created by other mechanisms. Also, session expiry
- # is not automatically handled.
- #
- # == Examples of use
- #
- # === Setting the user's name
- #
- # require 'cgi'
- # require 'cgi/session'
- # require 'cgi/session/pstore' # provides CGI::Session::PStore
- #
- # cgi = CGI.new("html4")
- #
- # session = CGI::Session.new(cgi,
- # 'database_manager' => CGI::Session::PStore, # use PStore
- # 'session_key' => '_rb_sess_id', # custom session key
- # 'session_expires' => Time.now + 30 * 60, # 30 minute timeout
- # 'prefix' => 'pstore_sid_') # PStore option
- # if cgi.has_key?('user_name') and cgi['user_name'] != ''
- # # coerce to String: cgi[] returns the
- # # string-like CGI::QueryExtension::Value
- # session['user_name'] = cgi['user_name'].to_s
- # elsif !session['user_name']
- # session['user_name'] = "guest"
- # end
- # session.close
- #
- # === Creating a new session safely
- #
- # require 'cgi'
- # require 'cgi/session'
- #
- # cgi = CGI.new("html4")
- #
- # # We make sure to delete an old session if one exists,
- # # not just to free resources, but to prevent the session
- # # from being maliciously hijacked later on.
- # begin
- # session = CGI::Session.new(cgi, 'new_session' => false)
- # session.delete
- # rescue ArgumentError # if no old session
- # end
- # session = CGI::Session.new(cgi, 'new_session' => true)
- # session.close
- #
- class Session
-
- class NoSession < RuntimeError #:nodoc:
- end
-
- # The id of this session.
- attr_reader :session_id, :new_session
-
- def Session::callback(dbman) #:nodoc:
- Proc.new{
- dbman[0].close unless dbman.empty?
- }
- end
-
- # Create a new session id.
- #
- # The session id is a secure random number by SecureRandom
- # if possible, otherwise an SHA512 hash based upon the time,
- # a random number, and a constant string. This routine is
- # used internally for automatically generated session ids.
- def create_new_id
- require 'securerandom'
- begin
- # by OpenSSL, or system provided entropy pool
- session_id = SecureRandom.hex(16)
- rescue NotImplementedError
- # never happens on modern systems
- require 'digest'
- d = Digest('SHA512').new
- now = Time::now
- d.update(now.to_s)
- d.update(String(now.usec))
- d.update(String(rand(0)))
- d.update(String($$))
- d.update('foobar')
- session_id = d.hexdigest[0, 32]
- end
- session_id
- end
- private :create_new_id
-
-
- # Create a new file to store the session data.
- #
- # This file will be created if it does not exist, or opened if it
- # does.
- #
- # This path is generated under _tmpdir_ from _prefix_, the
- # digested session id, and _suffix_.
- #
- # +option+ is a hash of options for the initializer. The
- # following options are recognised:
- #
- # tmpdir:: the directory to use for storing the FileStore
- # file. Defaults to Dir::tmpdir (generally "/tmp"
- # on Unix systems).
- # prefix:: the prefix to add to the session id when generating
- # the filename for this session's FileStore file.
- # Defaults to "cgi_sid_".
- # suffix:: the prefix to add to the session id when generating
- # the filename for this session's FileStore file.
- # Defaults to the empty string.
- def new_store_file(option={}) # :nodoc:
- dir = option['tmpdir'] || Dir::tmpdir
- prefix = option['prefix']
- suffix = option['suffix']
- require 'digest/md5'
- md5 = Digest::MD5.hexdigest(session_id)[0,16]
- path = dir+"/"
- path << prefix if prefix
- path << md5
- path << suffix if suffix
- if File::exist? path
- hash = nil
- elsif new_session
- hash = {}
- else
- raise NoSession, "uninitialized session"
- end
- return path, hash
- end
-
- # Create a new CGI::Session object for +request+.
- #
- # +request+ is an instance of the +CGI+ class (see cgi.rb).
- # +option+ is a hash of options for initialising this
- # CGI::Session instance. The following options are
- # recognised:
- #
- # session_key:: the parameter name used for the session id.
- # Defaults to '_session_id'.
- # session_id:: the session id to use. If not provided, then
- # it is retrieved from the +session_key+ parameter
- # of the request, or automatically generated for
- # a new session.
- # new_session:: if true, force creation of a new session. If not set,
- # a new session is only created if none currently
- # exists. If false, a new session is never created,
- # and if none currently exists and the +session_id+
- # option is not set, an ArgumentError is raised.
- # database_manager:: the name of the class providing storage facilities
- # for session state persistence. Built-in support
- # is provided for +FileStore+ (the default),
- # +MemoryStore+, and +PStore+ (from
- # cgi/session/pstore.rb). See the documentation for
- # these classes for more details.
- #
- # The following options are also recognised, but only apply if the
- # session id is stored in a cookie.
- #
- # session_expires:: the time the current session expires, as a
- # +Time+ object. If not set, the session will terminate
- # when the user's browser is closed.
- # session_domain:: the hostname domain for which this session is valid.
- # If not set, defaults to the hostname of the server.
- # session_secure:: if +true+, this session will only work over HTTPS.
- # session_path:: the path for which this session applies. Defaults
- # to the directory of the CGI script.
- #
- # +option+ is also passed on to the session storage class initializer; see
- # the documentation for each session storage class for the options
- # they support.
- #
- # The retrieved or created session is automatically added to +request+
- # as a cookie, and also to its +output_hidden+ table, which is used
- # to add hidden input elements to forms.
- #
- # *WARNING* the +output_hidden+
- # fields are surrounded by a <fieldset> tag in HTML 4 generation, which
- # is _not_ invisible on many browsers; you may wish to disable the
- # use of fieldsets with code similar to the following
- # (see https://blade.ruby-lang.org/ruby-list/37805)
- #
- # cgi = CGI.new("html4")
- # class << cgi
- # undef_method :fieldset
- # end
- #
- def initialize(request, option={})
- @new_session = false
- session_key = option['session_key'] || '_session_id'
- session_id = option['session_id']
- unless session_id
- if option['new_session']
- session_id = create_new_id
- @new_session = true
- end
- end
- unless session_id
- if request.key?(session_key)
- session_id = request[session_key]
- session_id = session_id.read if session_id.respond_to?(:read)
- end
- unless session_id
- session_id, = request.cookies[session_key]
- end
- unless session_id
- unless option.fetch('new_session', true)
- raise ArgumentError, "session_key `%s' should be supplied"%session_key
- end
- session_id = create_new_id
- @new_session = true
- end
- end
- @session_id = session_id
- dbman = option['database_manager'] || FileStore
- begin
- @dbman = dbman::new(self, option)
- rescue NoSession
- unless option.fetch('new_session', true)
- raise ArgumentError, "invalid session_id `%s'"%session_id
- end
- session_id = @session_id = create_new_id unless session_id
- @new_session=true
- retry
- end
- request.instance_eval do
- @output_hidden = {session_key => session_id} unless option['no_hidden']
- @output_cookies = [
- Cookie::new("name" => session_key,
- "value" => session_id,
- "expires" => option['session_expires'],
- "domain" => option['session_domain'],
- "secure" => option['session_secure'],
- "path" =>
- if option['session_path']
- option['session_path']
- elsif ENV["SCRIPT_NAME"]
- File::dirname(ENV["SCRIPT_NAME"])
- else
- ""
- end)
- ] unless option['no_cookies']
- end
- @dbprot = [@dbman]
- ObjectSpace::define_finalizer(self, Session::callback(@dbprot))
- end
-
- # Retrieve the session data for key +key+.
- def [](key)
- @data ||= @dbman.restore
- @data[key]
- end
-
- # Set the session data for key +key+.
- def []=(key, val)
- @write_lock ||= true
- @data ||= @dbman.restore
- @data[key] = val
- end
-
- # Store session data on the server. For some session storage types,
- # this is a no-op.
- def update
- @dbman.update
- end
-
- # Store session data on the server and close the session storage.
- # For some session storage types, this is a no-op.
- def close
- @dbman.close
- @dbprot.clear
- end
-
- # Delete the session from storage. Also closes the storage.
- #
- # Note that the session's data is _not_ automatically deleted
- # upon the session expiring.
- def delete
- @dbman.delete
- @dbprot.clear
- end
-
- # File-based session storage class.
- #
- # Implements session storage as a flat file of 'key=value' values.
- # This storage type only works directly with String values; the
- # user is responsible for converting other types to Strings when
- # storing and from Strings when retrieving.
- class FileStore
- # Create a new FileStore instance.
- #
- # This constructor is used internally by CGI::Session. The
- # user does not generally need to call it directly.
- #
- # +session+ is the session for which this instance is being
- # created. The session id must only contain alphanumeric
- # characters; automatically generated session ids observe
- # this requirement.
- #
- # +option+ is a hash of options for the initializer. The
- # following options are recognised:
- #
- # tmpdir:: the directory to use for storing the FileStore
- # file. Defaults to Dir::tmpdir (generally "/tmp"
- # on Unix systems).
- # prefix:: the prefix to add to the session id when generating
- # the filename for this session's FileStore file.
- # Defaults to "cgi_sid_".
- # suffix:: the prefix to add to the session id when generating
- # the filename for this session's FileStore file.
- # Defaults to the empty string.
- #
- # This session's FileStore file will be created if it does
- # not exist, or opened if it does.
- def initialize(session, option={})
- option = {'prefix' => 'cgi_sid_'}.update(option)
- @path, @hash = session.new_store_file(option)
- end
-
- # Restore session state from the session's FileStore file.
- #
- # Returns the session state as a hash.
- def restore
- unless @hash
- @hash = {}
- begin
- lockf = File.open(@path+".lock", "r")
- lockf.flock File::LOCK_SH
- f = File.open(@path, 'r')
- for line in f
- line.chomp!
- k, v = line.split('=',2)
- @hash[CGI.unescape(k)] = Marshal.restore(CGI.unescape(v))
- end
- ensure
- f&.close
- lockf&.close
- end
- end
- @hash
- end
-
- # Save session state to the session's FileStore file.
- def update
- return unless @hash
- begin
- lockf = File.open(@path+".lock", File::CREAT|File::RDWR, 0600)
- lockf.flock File::LOCK_EX
- f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600)
- for k,v in @hash
- f.printf "%s=%s\n", CGI.escape(k), CGI.escape(String(Marshal.dump(v)))
- end
- f.close
- File.rename @path+".new", @path
- ensure
- f&.close
- lockf&.close
- end
- end
-
- # Update and close the session's FileStore file.
- def close
- update
- end
-
- # Close and delete the session's FileStore file.
- def delete
- File::unlink @path+".lock" rescue nil
- File::unlink @path+".new" rescue nil
- File::unlink @path rescue nil
- end
- end
-
- # In-memory session storage class.
- #
- # Implements session storage as a global in-memory hash. Session
- # data will only persist for as long as the Ruby interpreter
- # instance does.
- class MemoryStore
- GLOBAL_HASH_TABLE = {} #:nodoc:
-
- # Create a new MemoryStore instance.
- #
- # +session+ is the session this instance is associated with.
- # +option+ is a list of initialisation options. None are
- # currently recognized.
- def initialize(session, option=nil)
- @session_id = session.session_id
- unless GLOBAL_HASH_TABLE.key?(@session_id)
- unless session.new_session
- raise CGI::Session::NoSession, "uninitialized session"
- end
- GLOBAL_HASH_TABLE[@session_id] = {}
- end
- end
-
- # Restore session state.
- #
- # Returns session data as a hash.
- def restore
- GLOBAL_HASH_TABLE[@session_id]
- end
-
- # Update session state.
- #
- # A no-op.
- def update
- # don't need to update; hash is shared
- end
-
- # Close session storage.
- #
- # A no-op.
- def close
- # don't need to close
- end
-
- # Delete the session state.
- def delete
- GLOBAL_HASH_TABLE.delete(@session_id)
- end
- end
-
- # Dummy session storage class.
- #
- # Implements session storage place holder. No actual storage
- # will be done.
- class NullStore
- # Create a new NullStore instance.
- #
- # +session+ is the session this instance is associated with.
- # +option+ is a list of initialisation options. None are
- # currently recognised.
- def initialize(session, option=nil)
- end
-
- # Restore (empty) session state.
- def restore
- {}
- end
-
- # Update session state.
- #
- # A no-op.
- def update
- end
-
- # Close session storage.
- #
- # A no-op.
- def close
- end
-
- # Delete the session state.
- #
- # A no-op.
- def delete
- end
- end
- end
-end
diff --git a/lib/cgi/session/pstore.rb b/lib/cgi/session/pstore.rb
deleted file mode 100644
index 6e3d10f075..0000000000
--- a/lib/cgi/session/pstore.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-#
-# cgi/session/pstore.rb - persistent storage of marshalled session data
-#
-# Documentation: William Webber ([email protected])
-#
-# == Overview
-#
-# This file provides the CGI::Session::PStore class, which builds
-# persistent of session data on top of the pstore library. See
-# cgi/session.rb for more details on session storage managers.
-
-require_relative '../session'
-begin
- require 'pstore'
-rescue LoadError
-end
-
-class CGI
- class Session
- # PStore-based session storage class.
- #
- # This builds upon the top-level PStore class provided by the
- # library file pstore.rb. Session data is marshalled and stored
- # in a file. File locking and transaction services are provided.
- class PStore
- # Create a new CGI::Session::PStore instance
- #
- # This constructor is used internally by CGI::Session. The
- # user does not generally need to call it directly.
- #
- # +session+ is the session for which this instance is being
- # created. The session id must only contain alphanumeric
- # characters; automatically generated session ids observe
- # this requirement.
- #
- # +option+ is a hash of options for the initializer. The
- # following options are recognised:
- #
- # tmpdir:: the directory to use for storing the PStore
- # file. Defaults to Dir::tmpdir (generally "/tmp"
- # on Unix systems).
- # prefix:: the prefix to add to the session id when generating
- # the filename for this session's PStore file.
- # Defaults to the empty string.
- #
- # This session's PStore file will be created if it does
- # not exist, or opened if it does.
- def initialize(session, option={})
- option = {'suffix'=>''}.update(option)
- path, @hash = session.new_store_file(option)
- @p = ::PStore.new(path)
- @p.transaction do |p|
- File.chmod(0600, p.path)
- end
- end
-
- # Restore session state from the session's PStore file.
- #
- # Returns the session state as a hash.
- def restore
- unless @hash
- @p.transaction do
- @hash = @p['hash'] || {}
- end
- end
- @hash
- end
-
- # Save session state to the session's PStore file.
- def update
- @p.transaction do
- @p['hash'] = @hash
- end
- end
-
- # Update and close the session's PStore file.
- def close
- update
- end
-
- # Close and delete the session's PStore file.
- def delete
- path = @p.path
- File::unlink path
- end
-
- end if defined?(::PStore)
- end
-end
-# :enddoc:
diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb
deleted file mode 100644
index 5d02b9d09f..0000000000
--- a/lib/cgi/util.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-class CGI
- module Util; end
- include Util
- extend Util
-end
-
-module CGI::Util
- # Format a +Time+ object as a String using the format specified by RFC 1123.
- #
- # CGI.rfc1123_date(Time.now)
- # # Sat, 01 Jan 2000 00:00:00 GMT
- def rfc1123_date(time)
- time.getgm.strftime("%a, %d %b %Y %T GMT")
- end
-
- # Prettify (indent) an HTML string.
- #
- # +string+ is the HTML string to indent. +shift+ is the indentation
- # unit to use; it defaults to two spaces.
- #
- # print CGI.pretty("<HTML><BODY></BODY></HTML>")
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # print CGI.pretty("<HTML><BODY></BODY></HTML>", "\t")
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- def pretty(string, shift = " ")
- lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\0\n")
- end_pos = 0
- while end_pos = lines.index(/^<\/(\w+)/, end_pos)
- element = $1.dup
- start_pos = lines.rindex(/^\s*<#{element}/i, end_pos)
- lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__"
- end
- lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
- end
-end
diff --git a/test/cgi/test_cgi_cookie.rb b/test/cgi/test_cgi_cookie.rb
deleted file mode 100644
index eadae45313..0000000000
--- a/test/cgi/test_cgi_cookie.rb
+++ /dev/null
@@ -1,211 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'cgi'
-require 'stringio'
-require_relative 'update_env'
-
-
-class CGICookieTest < Test::Unit::TestCase
- include UpdateEnv
-
-
- def setup
- @environ = {}
- update_env(
- 'REQUEST_METHOD' => 'GET',
- 'SCRIPT_NAME' => nil,
- )
- @str1="\xE3\x82\x86\xE3\x82\x93\xE3\x82\x86\xE3\x82\x93".dup
- @str1.force_encoding("UTF-8") if defined?(::Encoding)
- end
-
- def teardown
- ENV.update(@environ)
- end
-
-
- def test_cgi_cookie_new_simple
- cookie = CGI::Cookie.new('name1', 'val1', '&<>"', @str1)
- assert_equal('name1', cookie.name)
- assert_equal(['val1', '&<>"', @str1], cookie.value)
- assert_nil(cookie.domain)
- assert_nil(cookie.expires)
- assert_equal('', cookie.path)
- assert_equal(false, cookie.secure)
- assert_equal(false, cookie.httponly)
- assert_equal("name1=val1&%26%3C%3E%22&%E3%82%86%E3%82%93%E3%82%86%E3%82%93; path=", cookie.to_s)
- end
-
-
- def test_cgi_cookie_new_complex
- t = Time.gm(2030, 12, 31, 23, 59, 59)
- value = ['val1', '&<>"', "\xA5\xE0\xA5\xB9\xA5\xAB".dup]
- value[2].force_encoding("EUC-JP") if defined?(::Encoding)
- cookie = CGI::Cookie.new('name'=>'name1',
- 'value'=>value,
- 'path'=>'/cgi-bin/myapp/',
- 'domain'=>'www.example.com',
- 'expires'=>t,
- 'secure'=>true,
- 'httponly'=>true
- )
- assert_equal('name1', cookie.name)
- assert_equal(value, cookie.value)
- assert_equal('www.example.com', cookie.domain)
- assert_equal(t, cookie.expires)
- assert_equal('/cgi-bin/myapp/', cookie.path)
- assert_equal(true, cookie.secure)
- assert_equal(true, cookie.httponly)
- assert_equal('name1=val1&%26%3C%3E%22&%A5%E0%A5%B9%A5%AB; domain=www.example.com; path=/cgi-bin/myapp/; expires=Tue, 31 Dec 2030 23:59:59 GMT; secure; HttpOnly', cookie.to_s)
- end
-
-
- def test_cgi_cookie_new_with_domain
- h = {'name'=>'name1', 'value'=>'value1'}
- cookie = CGI::Cookie.new(h.merge('domain'=>'a.example.com'))
- assert_equal('a.example.com', cookie.domain)
-
- cookie = CGI::Cookie.new(h.merge('domain'=>'.example.com'))
- assert_equal('.example.com', cookie.domain)
-
- cookie = CGI::Cookie.new(h.merge('domain'=>'1.example.com'))
- assert_equal('1.example.com', cookie.domain, 'enhanced by RFC 1123')
-
- assert_raise(ArgumentError) {
- CGI::Cookie.new(h.merge('domain'=>'-a.example.com'))
- }
-
- assert_raise(ArgumentError) {
- CGI::Cookie.new(h.merge('domain'=>'a-.example.com'))
- }
- end
-
-
- def test_cgi_cookie_scriptname
- cookie = CGI::Cookie.new('name1', 'value1')
- assert_equal('', cookie.path)
- cookie = CGI::Cookie.new('name'=>'name1', 'value'=>'value1')
- assert_equal('', cookie.path)
- ## when ENV['SCRIPT_NAME'] is set, cookie.path is set automatically
- ENV['SCRIPT_NAME'] = '/cgi-bin/app/example.cgi'
- cookie = CGI::Cookie.new('name1', 'value1')
- assert_equal('/cgi-bin/app/', cookie.path)
- cookie = CGI::Cookie.new('name'=>'name1', 'value'=>'value1')
- assert_equal('/cgi-bin/app/', cookie.path)
- end
-
-
- def test_cgi_cookie_parse
- ## ';' separator
- cookie_str = 'name1=val1&val2; name2=val2&%26%3C%3E%22&%E3%82%86%E3%82%93%E3%82%86%E3%82%93;_session_id=12345'
- cookies = CGI::Cookie.parse(cookie_str)
- list = [
- ['name1', ['val1', 'val2']],
- ['name2', ['val2', '&<>"',@str1]],
- ['_session_id', ['12345']],
- ]
- list.each do |name, value|
- cookie = cookies[name]
- assert_equal(name, cookie.name)
- assert_equal(value, cookie.value)
- end
- ## don't allow ',' separator
- cookie_str = 'name1=val1&val2, name2=val2'
- cookies = CGI::Cookie.parse(cookie_str)
- list = [
- ['name1', ['val1', 'val2, name2=val2']],
- ]
- list.each do |name, value|
- cookie = cookies[name]
- assert_equal(name, cookie.name)
- assert_equal(value, cookie.value)
- end
- end
-
- def test_cgi_cookie_parse_not_decode_name
- cookie_str = "%66oo=baz;foo=bar"
- cookies = CGI::Cookie.parse(cookie_str)
- assert_equal({"%66oo" => ["baz"], "foo" => ["bar"]}, cookies)
- end
-
- def test_cgi_cookie_arrayinterface
- cookie = CGI::Cookie.new('name1', 'a', 'b', 'c')
- assert_equal('a', cookie[0])
- assert_equal('c', cookie[2])
- assert_nil(cookie[3])
- assert_equal('a', cookie.first)
- assert_equal('c', cookie.last)
- assert_equal(['A', 'B', 'C'], cookie.collect{|e| e.upcase})
- end
-
-
- def test_cgi_cookie_domain_injection_into_name
- name = "a=b; domain=example.com;"
- path = "/"
- domain = "example.jp"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- def test_cgi_cookie_newline_injection_into_name
- name = "a=b;\r\nLocation: http://example.com#"
- path = "/"
- domain = "example.jp"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- def test_cgi_cookie_multibyte_injection_into_name
- name = "a=b;\u3042"
- path = "/"
- domain = "example.jp"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- def test_cgi_cookie_injection_into_path
- name = "name"
- path = "/; samesite=none"
- domain = "example.jp"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- def test_cgi_cookie_injection_into_domain
- name = "name"
- path = "/"
- domain = "example.jp; samesite=none"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- instance_methods.each do |method|
- private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
- end if ENV['TEST']
-
-end
diff --git a/test/cgi/test_cgi_core.rb b/test/cgi/test_cgi_core.rb
deleted file mode 100644
index f7adb7e99f..0000000000
--- a/test/cgi/test_cgi_core.rb
+++ /dev/null
@@ -1,307 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'cgi'
-require 'stringio'
-require_relative 'update_env'
-
-
-class CGICoreTest < Test::Unit::TestCase
- include UpdateEnv
-
- def setup
- @environ = {}
- #@environ = {
- # 'SERVER_PROTOCOL' => 'HTTP/1.1',
- # 'REQUEST_METHOD' => 'GET',
- # 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- #}
- #ENV.update(@environ)
- end
-
- def teardown
- ENV.update(@environ)
- $stdout = STDOUT
- end
-
- def test_cgi_parse_illegal_query
- update_env(
- 'REQUEST_METHOD' => 'GET',
- 'QUERY_STRING' => 'a=111&&b=222&c&d=',
- 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- cgi = CGI.new
- assert_equal(["a","b","c","d"],cgi.keys.sort)
- assert_equal("",cgi["d"])
- end
-
- def test_cgi_core_params_GET
- update_env(
- 'REQUEST_METHOD' => 'GET',
- 'QUERY_STRING' => 'id=123&id=456&id=&id&str=%40h+%3D%7E+%2F%5E%24%2F',
- 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- cgi = CGI.new
- ## cgi[]
- assert_equal('123', cgi['id'])
- assert_equal('@h =~ /^$/', cgi['str'])
- ## cgi.params
- assert_equal(['123', '456', ''], cgi.params['id'])
- assert_equal(['@h =~ /^$/'], cgi.params['str'])
- ## cgi.keys
- assert_equal(['id', 'str'], cgi.keys.sort)
- ## cgi.key?, cgi.has_key?, cgi.include?
- assert_equal(true, cgi.key?('id'))
- assert_equal(true, cgi.has_key?('id'))
- assert_equal(true, cgi.include?('id'))
- assert_equal(false, cgi.key?('foo'))
- assert_equal(false, cgi.has_key?('foo'))
- assert_equal(false, cgi.include?('foo'))
- ## invalid parameter name
- assert_equal('', cgi['*notfound*']) # [ruby-dev:30740]
- assert_equal([], cgi.params['*notfound*'])
- end
-
-
- def test_cgi_core_params_POST
- query_str = 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F'
- update_env(
- 'REQUEST_METHOD' => 'POST',
- 'CONTENT_LENGTH' => query_str.length.to_s,
- 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- $stdin = StringIO.new
- $stdin << query_str
- $stdin.rewind
- cgi = CGI.new
- ## cgi[]
- assert_equal('123', cgi['id'])
- assert_equal('@h =~ /^$/', cgi['str'])
- ## cgi.params
- assert_equal(['123', '456', ''], cgi.params['id'])
- assert_equal(['@h =~ /^$/'], cgi.params['str'])
- ## invalid parameter name
- assert_equal('', cgi['*notfound*'])
- assert_equal([], cgi.params['*notfound*'])
- ensure
- $stdin = STDIN
- end
-
- def test_cgi_core_params_encoding_check
- query_str = 'str=%BE%BE%B9%BE'
- update_env(
- 'REQUEST_METHOD' => 'POST',
- 'CONTENT_LENGTH' => query_str.length.to_s,
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- $stdin = StringIO.new
- $stdin << query_str
- $stdin.rewind
- if defined?(::Encoding)
- hash={}
- cgi = CGI.new(:accept_charset=>"UTF-8"){|key,val|hash[key]=val}
- ## cgi[]
- assert_equal("\xBE\xBE\xB9\xBE".dup.force_encoding("UTF-8"), cgi['str'])
- ## cgi.params
- assert_equal(["\xBE\xBE\xB9\xBE".dup.force_encoding("UTF-8")], cgi.params['str'])
- ## accept-charset error
- assert_equal({"str"=>"\xBE\xBE\xB9\xBE".dup.force_encoding("UTF-8")},hash)
-
- $stdin.rewind
- assert_raise(CGI::InvalidEncoding) do
- cgi = CGI.new(:accept_charset=>"UTF-8")
- end
-
- $stdin.rewind
- cgi = CGI.new(:accept_charset=>"EUC-JP")
- ## cgi[]
- assert_equal("\xBE\xBE\xB9\xBE".dup.force_encoding("EUC-JP"), cgi['str'])
- ## cgi.params
- assert_equal(["\xBE\xBE\xB9\xBE".dup.force_encoding("EUC-JP")], cgi.params['str'])
- else
- assert(true)
- end
- ensure
- $stdin = STDIN
- end
-
-
- def test_cgi_core_cookie
- update_env(
- 'REQUEST_METHOD' => 'GET',
- 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F',
- 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- cgi = CGI.new
- assert_not_equal(nil,cgi.cookies)
- [ ['_session_id', ['12345'], ],
- ['name1', ['val1', 'val2'], ],
- ].each do |key, expected|
- cookie = cgi.cookies[key]
- assert_kind_of(CGI::Cookie, cookie)
- assert_equal(expected, cookie.value)
- assert_equal(false, cookie.secure)
- assert_nil(cookie.expires)
- assert_nil(cookie.domain)
- assert_equal('', cookie.path)
- end
- end
-
-
- def test_cgi_core_maxcontentlength
- update_env(
- 'REQUEST_METHOD' => 'POST',
- 'CONTENT_LENGTH' => (64 * 1024 * 1024).to_s
- )
- ex = assert_raise(StandardError) do
- CGI.new
- end
- assert_equal("too large post data.", ex.message)
- end if CGI.const_defined?(:MAX_CONTENT_LENGTH)
-
-
- def test_cgi_core_out
- update_env(
- 'REQUEST_METHOD' => 'GET',
- 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F',
- 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- cgi = CGI.new
- ## euc string
- euc_str = "\270\253\244\355\241\242\277\315\244\254\245\264\245\337\244\316\244\350\244\246\244\300"
- ## utf8 (not converted)
- options = { 'charset'=>'utf8' }
- $stdout = StringIO.new
- cgi.out(options) { euc_str }
- assert_nil(options['language'])
- actual = $stdout.string
- expected = "Content-Type: text/html; charset=utf8\r\n" +
- "Content-Length: 22\r\n" +
- "\r\n" +
- euc_str
- if defined?(::Encoding)
- actual.force_encoding("ASCII-8BIT")
- expected.force_encoding("ASCII-8BIT")
- end
- assert_equal(expected, actual)
- ## language is keeped
- options = { 'charset'=>'Shift_JIS', 'language'=>'en' }
- $stdout = StringIO.new
- cgi.out(options) { euc_str }
- assert_equal('en', options['language'])
- ## HEAD method
- update_env('REQUEST_METHOD' => 'HEAD')
- options = { 'charset'=>'utf8' }
- $stdout = StringIO.new
- cgi.out(options) { euc_str }
- actual = $stdout.string
- expected = "Content-Type: text/html; charset=utf8\r\n" +
- "Content-Length: 22\r\n" +
- "\r\n"
- assert_equal(expected, actual)
- end
-
-
- def test_cgi_core_print
- update_env(
- 'REQUEST_METHOD' => 'GET',
- )
- cgi = CGI.new
- $stdout = StringIO.new
- str = "foobar"
- cgi.print(str)
- expected = str
- actual = $stdout.string
- assert_equal(expected, actual)
- end
-
-
- def test_cgi_core_environs
- update_env(
- 'REQUEST_METHOD' => 'GET',
- )
- cgi = CGI.new
- ##
- list1 = %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
- PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
- REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
- SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
- HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
- HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
- HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT
- ]
- # list2 = %w[ CONTENT_LENGTH SERVER_PORT ]
- ## string expected
- list1.each do |name|
- update_env(name => "**#{name}**")
- end
- list1.each do |name|
- method = name.sub(/\AHTTP_/, '').downcase
- actual = cgi.__send__ method
- expected = "**#{name}**"
- assert_equal(expected, actual)
- end
- ## integer expected
- update_env('CONTENT_LENGTH' => '123')
- update_env('SERVER_PORT' => '8080')
- assert_equal(123, cgi.content_length)
- assert_equal(8080, cgi.server_port)
- ## raw cookie
- update_env('HTTP_COOKIE' => 'name1=val1')
- update_env('HTTP_COOKIE2' => 'name2=val2')
- assert_equal('name1=val1', cgi.raw_cookie)
- assert_equal('name2=val2', cgi.raw_cookie2)
- end
-
-
- def test_cgi_core_htmltype_header
- update_env(
- 'REQUEST_METHOD' => 'GET',
- )
- ## no htmltype
- cgi = CGI.new
- assert_raise(NoMethodError) do cgi.doctype end
- assert_equal("Content-Type: text/html\r\n\r\n",cgi.header)
- ## html3
- cgi = CGI.new('html3')
- expected = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
- assert_equal(expected, cgi.doctype)
- assert_equal("Content-Type: text/html\r\n\r\n",cgi.header)
- ## html4
- cgi = CGI.new('html4')
- expected = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
- assert_equal(expected, cgi.doctype)
- assert_equal("Content-Type: text/html\r\n\r\n",cgi.header)
- ## html4 transitional
- cgi = CGI.new('html4Tr')
- expected = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
- assert_equal(expected, cgi.doctype)
- assert_equal("Content-Type: text/html\r\n\r\n",cgi.header)
- ## html4 frameset
- cgi = CGI.new('html4Fr')
- expected = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'
- assert_equal(expected, cgi.doctype)
- assert_equal("Content-Type: text/html\r\n\r\n",cgi.header)
- ## html5
- cgi = CGI.new('html5')
- expected = '<!DOCTYPE HTML>'
- assert_equal(expected, cgi.doctype)
- assert_match(/^<HEADER><\/HEADER>$/i,cgi.header)
- end
-
-
- instance_methods.each do |method|
- private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
- end if ENV['TEST']
-
-end
diff --git a/test/cgi/test_cgi_header.rb b/test/cgi/test_cgi_header.rb
deleted file mode 100644
index ec2f4deb72..0000000000
--- a/test/cgi/test_cgi_header.rb
+++ /dev/null
@@ -1,192 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'cgi'
-require 'time'
-require_relative 'update_env'
-
-
-class CGIHeaderTest < Test::Unit::TestCase
- include UpdateEnv
-
-
- def setup
- @environ = {}
- update_env(
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- 'REQUEST_METHOD' => 'GET',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- )
- end
-
-
- def teardown
- ENV.update(@environ)
- end
-
-
- def test_cgi_http_header_simple
- cgi = CGI.new
- ## default content type
- expected = "Content-Type: text/html\r\n\r\n"
- actual = cgi.http_header
- assert_equal(expected, actual)
- ## content type specified as string
- expected = "Content-Type: text/xhtml; charset=utf8\r\n\r\n"
- actual = cgi.http_header('text/xhtml; charset=utf8')
- assert_equal(expected, actual)
- ## content type specified as hash
- expected = "Content-Type: image/png\r\n\r\n"
- actual = cgi.http_header('type'=>'image/png')
- assert_equal(expected, actual)
- ## charset specified
- expected = "Content-Type: text/html; charset=utf8\r\n\r\n"
- actual = cgi.http_header('charset'=>'utf8')
- assert_equal(expected, actual)
- end
-
-
- def test_cgi_http_header_complex
- cgi = CGI.new
- options = {
- 'type' => 'text/xhtml',
- 'charset' => 'utf8',
- 'status' => 'REDIRECT',
- 'server' => 'webrick',
- 'connection' => 'close',
- 'length' => 123,
- 'language' => 'ja',
- 'expires' => Time.gm(2000, 1, 23, 12, 34, 56),
- 'location' => 'http://www.ruby-lang.org/',
- }
- expected = "Status: 302 Found\r\n".dup
- expected << "Server: webrick\r\n"
- expected << "Connection: close\r\n"
- expected << "Content-Type: text/xhtml; charset=utf8\r\n"
- expected << "Content-Length: 123\r\n"
- expected << "Content-Language: ja\r\n"
- expected << "Expires: Sun, 23 Jan 2000 12:34:56 GMT\r\n"
- expected << "location: http://www.ruby-lang.org/\r\n"
- expected << "\r\n"
- actual = cgi.http_header(options)
- assert_equal(expected, actual)
- end
-
-
- def test_cgi_http_header_argerr
- cgi = CGI.new
- expected = ArgumentError
-
- assert_raise(expected) do
- cgi.http_header(nil)
- end
- end
-
-
- def test_cgi_http_header_cookie
- cgi = CGI.new
- cookie1 = CGI::Cookie.new('name1', 'abc', '123')
- cookie2 = CGI::Cookie.new('name'=>'name2', 'value'=>'value2', 'secure'=>true)
- ctype = "Content-Type: text/html\r\n"
- sep = "\r\n"
- c1 = "Set-Cookie: name1=abc&123; path=\r\n"
- c2 = "Set-Cookie: name2=value2; path=; secure\r\n"
- ## CGI::Cookie object
- actual = cgi.http_header('cookie'=>cookie1)
- expected = ctype + c1 + sep
- assert_equal(expected, actual)
- ## String
- actual = cgi.http_header('cookie'=>cookie2.to_s)
- expected = ctype + c2 + sep
- assert_equal(expected, actual)
- ## Array
- actual = cgi.http_header('cookie'=>[cookie1, cookie2])
- expected = ctype + c1 + c2 + sep
- assert_equal(expected, actual)
- ## Hash
- actual = cgi.http_header('cookie'=>{'name1'=>cookie1, 'name2'=>cookie2})
- expected = ctype + c1 + c2 + sep
- assert_equal(expected, actual)
- end
-
-
- def test_cgi_http_header_output_cookies
- cgi = CGI.new
- ## output cookies
- cookies = [ CGI::Cookie.new('name1', 'abc', '123'),
- CGI::Cookie.new('name'=>'name2', 'value'=>'value2', 'secure'=>true),
- ]
- cgi.instance_variable_set('@output_cookies', cookies)
- expected = "Content-Type: text/html; charset=utf8\r\n".dup
- expected << "Set-Cookie: name1=abc&123; path=\r\n"
- expected << "Set-Cookie: name2=value2; path=; secure\r\n"
- expected << "\r\n"
- ## header when string
- actual = cgi.http_header('text/html; charset=utf8')
- assert_equal(expected, actual)
- ## _header_for_string
- actual = cgi.http_header('type'=>'text/html', 'charset'=>'utf8')
- assert_equal(expected, actual)
- end
-
-
- def test_cgi_http_header_nph
- time_start = Time.now.to_i
- cgi = CGI.new
- ## 'nph' is true
- ENV['SERVER_SOFTWARE'] = 'Apache 2.2.0'
- actual1 = cgi.http_header('nph'=>true)
- ## when old IIS, NPH-mode is forced
- ENV['SERVER_SOFTWARE'] = 'IIS/4.0'
- actual2 = cgi.http_header
- actual3 = cgi.http_header('status'=>'REDIRECT', 'location'=>'http://www.example.com/')
- ## newer IIS doesn't require NPH-mode ## [ruby-dev:30537]
- ENV['SERVER_SOFTWARE'] = 'IIS/5.0'
- actual4 = cgi.http_header
- actual5 = cgi.http_header('status'=>'REDIRECT', 'location'=>'http://www.example.com/')
- time_end = Time.now.to_i
- date = /^Date: ([A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4} \d\d:\d\d:\d\d GMT)\r\n/
- [actual1, actual2, actual3].each do |actual|
- assert_match(date, actual)
- assert_include(time_start..time_end, date =~ actual && Time.parse($1).to_i)
- actual.sub!(date, "Date: DATE_IS_REMOVED\r\n")
- end
- ## assertion
- expected = "HTTP/1.1 200 OK\r\n".dup
- expected << "Date: DATE_IS_REMOVED\r\n"
- expected << "Server: Apache 2.2.0\r\n"
- expected << "Connection: close\r\n"
- expected << "Content-Type: text/html\r\n"
- expected << "\r\n"
- assert_equal(expected, actual1)
- expected.sub!(/^Server: .*?\r\n/, "Server: IIS/4.0\r\n")
- assert_equal(expected, actual2)
- expected.sub!(/^HTTP\/1.1 200 OK\r\n/, "HTTP/1.1 302 Found\r\n")
- expected.sub!(/\r\n\r\n/, "\r\nlocation: http://www.example.com/\r\n\r\n")
- assert_equal(expected, actual3)
- expected = "Content-Type: text/html\r\n".dup
- expected << "\r\n"
- assert_equal(expected, actual4)
- expected = "Status: 302 Found\r\n".dup
- expected << "Content-Type: text/html\r\n"
- expected << "location: http://www.example.com/\r\n"
- expected << "\r\n"
- assert_equal(expected, actual5)
- ensure
- ENV.delete('SERVER_SOFTWARE')
- end
-
-
- def test_cgi_http_header_crlf_injection
- cgi = CGI.new
- assert_raise(RuntimeError) { cgi.http_header("text/xhtml\r\nBOO") }
- assert_raise(RuntimeError) { cgi.http_header("type" => "text/xhtml\r\nBOO") }
- assert_raise(RuntimeError) { cgi.http_header("status" => "200 OK\r\nBOO") }
- assert_raise(RuntimeError) { cgi.http_header("location" => "text/xhtml\r\nBOO") }
- end
-
-
- instance_methods.each do |method|
- private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
- end if ENV['TEST']
-
-end
diff --git a/test/cgi/test_cgi_modruby.rb b/test/cgi/test_cgi_modruby.rb
deleted file mode 100644
index 90132962b5..0000000000
--- a/test/cgi/test_cgi_modruby.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'cgi'
-require_relative 'update_env'
-
-
-class CGIModrubyTest < Test::Unit::TestCase
- include UpdateEnv
-
-
- def setup
- @environ = {}
- update_env(
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- 'REQUEST_METHOD' => 'GET',
- #'QUERY_STRING' => 'a=foo&b=bar',
- )
- CGI.class_eval { const_set(:MOD_RUBY, true) }
- Apache._reset()
- #@cgi = CGI.new
- #@req = Apache.request
- end
-
-
- def teardown
- ENV.update(@environ)
- CGI.class_eval { remove_const(:MOD_RUBY) }
- end
-
-
- def test_cgi_modruby_simple
- req = Apache.request
- cgi = CGI.new
- assert(req._setup_cgi_env_invoked?)
- assert(! req._send_http_header_invoked?)
- actual = cgi.http_header
- assert_equal('', actual)
- assert_equal('text/html', req.content_type)
- assert(req._send_http_header_invoked?)
- end
-
-
- def test_cgi_modruby_complex
- req = Apache.request
- cgi = CGI.new
- options = {
- 'status' => 'FORBIDDEN',
- 'location' => 'http://www.example.com/',
- 'type' => 'image/gif',
- 'content-encoding' => 'deflate',
- 'cookie' => [ CGI::Cookie.new('name1', 'abc', '123'),
- CGI::Cookie.new('name'=>'name2', 'value'=>'value2', 'secure'=>true),
- ],
- }
- assert(req._setup_cgi_env_invoked?)
- assert(! req._send_http_header_invoked?)
- actual = cgi.http_header(options)
- assert_equal('', actual)
- assert_equal('image/gif', req.content_type)
- assert_equal('403 Forbidden', req.status_line)
- assert_equal(403, req.status)
- assert_equal('deflate', req.content_encoding)
- assert_equal('http://www.example.com/', req.headers_out['location'])
- assert_equal(["name1=abc&123; path=", "name2=value2; path=; secure"],
- req.headers_out['Set-Cookie'])
- assert(req._send_http_header_invoked?)
- end
-
-
- def test_cgi_modruby_location
- req = Apache.request
- cgi = CGI.new
- options = {
- 'status' => '200 OK',
- 'location' => 'http://www.example.com/',
- }
- cgi.http_header(options)
- assert_equal('200 OK', req.status_line) # should be '302 Found' ?
- assert_equal(302, req.status)
- assert_equal('http://www.example.com/', req.headers_out['location'])
- end
-
-
- def test_cgi_modruby_requestparams
- req = Apache.request
- req.args = 'a=foo&b=bar'
- cgi = CGI.new
- assert_equal('foo', cgi['a'])
- assert_equal('bar', cgi['b'])
- end
-
-
- instance_methods.each do |method|
- private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
- end if ENV['TEST']
-
-end
-
-
-
-## dummy class for mod_ruby
-class Apache #:nodoc:
-
- def self._reset
- @request = Request.new
- end
-
- def self.request
- return @request
- end
-
- class Request
-
- def initialize
- hash = {}
- def hash.add(name, value)
- (self[name] ||= []) << value
- end
- @http_header = nil
- @headers_out = hash
- @status_line = nil
- @status = nil
- @content_type = nil
- @content_encoding = nil
- end
- attr_accessor :headers_out, :status_line, :status, :content_type, :content_encoding
-
- attr_accessor :args
- #def args
- # return ENV['QUERY_STRING']
- #end
-
- def send_http_header
- @http_header = '*invoked*'
- end
- def _send_http_header_invoked?
- @http_header ? true : false
- end
-
- def setup_cgi_env
- @cgi_env = '*invoked*'
- end
- def _setup_cgi_env_invoked?
- @cgi_env ? true : false
- end
-
- end
-
-end
diff --git a/test/cgi/test_cgi_multipart.rb b/test/cgi/test_cgi_multipart.rb
deleted file mode 100644
index 5e8ec25390..0000000000
--- a/test/cgi/test_cgi_multipart.rb
+++ /dev/null
@@ -1,385 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'cgi'
-require 'tempfile'
-require 'stringio'
-require_relative 'update_env'
-
-
-##
-## usage:
-## boundary = 'foobar1234' # or nil
-## multipart = MultiPart.new(boundary)
-## multipart.append('name1', 'value1')
-## multipart.append('file1', File.read('file1.html'), 'file1.html')
-## str = multipart.close()
-## str.each_line {|line| p line }
-## ## output:
-## # "--foobar1234\r\n"
-## # "Content-Disposition: form-data: name=\"name1\"\r\n"
-## # "\r\n"
-## # "value1\r\n"
-## # "--foobar1234\r\n"
-## # "Content-Disposition: form-data: name=\"file1\"; filename=\"file1.html\"\r\n"
-## # "Content-Type: text/html\r\n"
-## # "\r\n"
-## # "<html>\n"
-## # "<body><p>Hello</p></body>\n"
-## # "</html>\n"
-## # "\r\n"
-## # "--foobar1234--\r\n"
-##
-class MultiPart
-
- def initialize(boundary=nil)
- @boundary = boundary || create_boundary()
- @buf = ''.dup
- @buf.force_encoding(::Encoding::ASCII_8BIT) if defined?(::Encoding)
- end
- attr_reader :boundary
-
- def append(name, value, filename=nil, content_type=nil)
- content_type = detect_content_type(filename) if filename && content_type.nil?
- s = filename ? "; filename=\"#{filename}\"" : ''
- buf = @buf
- buf << "--#{boundary}\r\n"
- buf << "Content-Disposition: form-data: name=\"#{name}\"#{s}\r\n"
- buf << "Content-Type: #{content_type}\r\n" if content_type
- buf << "\r\n"
- buf << value.b
- buf << "\r\n"
- return self
- end
-
- def close
- buf = @buf
- @buf = ''.dup
- return buf << "--#{boundary}--\r\n"
- end
-
- def create_boundary() #:nodoc:
- return "--boundary#{rand().to_s[2..-1]}"
- end
-
- def detect_content_type(filename) #:nodoc:
- filename =~ /\.(\w+)\z/
- return MIME_TYPES[$1] || 'application/octet-stream'
- end
-
- MIME_TYPES = {
- 'gif' => 'image/gif',
- 'jpg' => 'image/jpeg',
- 'jpeg' => 'image/jpeg',
- 'png' => 'image/png',
- 'bmp' => 'image/bmp',
- 'tif' => 'image/tiff',
- 'tiff' => 'image/tiff',
- 'htm' => 'text/html',
- 'html' => 'text/html',
- 'xml' => 'text/xml',
- 'txt' => 'text/plain',
- 'text' => 'text/plain',
- 'css' => 'text/css',
- 'mpg' => 'video/mpeg',
- 'mpeg' => 'video/mpeg',
- 'mov' => 'video/quicktime',
- 'avi' => 'video/x-msvideo',
- 'mp3' => 'audio/mpeg',
- 'mid' => 'audio/midi',
- 'wav' => 'audio/x-wav',
- 'zip' => 'application/zip',
- #'tar.gz' => 'application/gtar',
- 'gz' => 'application/gzip',
- 'bz2' => 'application/bzip2',
- 'rtf' => 'application/rtf',
- 'pdf' => 'application/pdf',
- 'ps' => 'application/postscript',
- 'js' => 'application/x-javascript',
- 'xls' => 'application/vnd.ms-excel',
- 'doc' => 'application/msword',
- 'ppt' => 'application/vnd.ms-powerpoint',
- }
-
-end
-
-
-
-class CGIMultipartTest < Test::Unit::TestCase
- include UpdateEnv
-
-
- def setup
- @environ = {}
- update_env(
- 'REQUEST_METHOD' => 'POST',
- 'CONTENT_TYPE' => nil,
- 'CONTENT_LENGTH' => nil,
- )
- @tempfiles = []
- end
-
- def teardown
- ENV.update(@environ)
- $stdin.close() if $stdin.is_a?(Tempfile)
- $stdin = STDIN
- @tempfiles.each {|t|
- t.close!
- }
- end
-
- def _prepare(data)
- ## create multipart input
- multipart = MultiPart.new(defined?(@boundary) ? @boundary : nil)
- data.each do |hash|
- multipart.append(hash[:name], hash[:value], hash[:filename])
- end
- input = multipart.close()
- input = yield(input) if block_given?
- #$stderr.puts "*** debug: input=\n#{input.collect{|line| line.inspect}.join("\n")}"
- @boundary ||= multipart.boundary
- ## set environment
- ENV['CONTENT_TYPE'] = "multipart/form-data; boundary=#{@boundary}"
- ENV['CONTENT_LENGTH'] = input.length.to_s
- ENV['REQUEST_METHOD'] = 'POST'
- ## set $stdin
- tmpfile = Tempfile.new('test_cgi_multipart')
- @tempfiles << tmpfile
- tmpfile.binmode
- tmpfile << input
- tmpfile.rewind()
- $stdin = tmpfile
- end
-
- def _test_multipart(cgi_options={})
- caller(0).find {|s| s =~ /in `test_(.*?)'/ }
- #testname = $1
- #$stderr.puts "*** debug: testname=#{testname.inspect}"
- _prepare(@data)
- options = {:accept_charset=>"UTF-8"}
- options.merge! cgi_options
- cgi = CGI.new(options)
- expected_names = @data.collect{|hash| hash[:name] }.sort
- assert_equal(expected_names, cgi.params.keys.sort)
- threshold = 1024*10
- @data.each do |hash|
- name = hash[:name]
- expected = hash[:value]
- if hash[:filename] #if file
- expected_class = @expected_class || (hash[:value].length < threshold ? StringIO : Tempfile)
- assert(cgi.files.keys.member?(hash[:name]))
- else
- expected_class = String
- assert_equal(expected, cgi[name])
- assert_equal(false,cgi.files.keys.member?(hash[:name]))
- end
- assert_kind_of(expected_class, cgi[name])
- assert_equal(expected, cgi[name].read())
- assert_equal(hash[:filename] || '', cgi[name].original_filename) #if hash[:filename]
- assert_equal(hash[:content_type] || '', cgi[name].content_type) #if hash[:content_type]
- end
- ensure
- if cgi
- cgi.params.each {|name, vals|
- vals.each {|val|
- if val.kind_of?(Tempfile) && val.path
- val.close!
- end
- }
- }
- end
- end
-
-
- def _read(basename)
- filename = File.join(File.dirname(__FILE__), 'testdata', basename)
- s = File.open(filename, 'rb') {|f| f.read() }
-
- return s
- end
-
-
- def test_cgi_multipart_stringio
- @boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX'
- @data = [
- {:name=>'hidden1', :value=>'foobar'},
- {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A".dup},
- {:name=>'file1', :value=>_read('file1.html'),
- :filename=>'file1.html', :content_type=>'text/html'},
- {:name=>'image1', :value=>_read('small.png'),
- :filename=>'small.png', :content_type=>'image/png'}, # small image
- ]
- @data[1][:value].force_encoding(::Encoding::UTF_8) if defined?(::Encoding)
- @expected_class = StringIO
- _test_multipart()
- end
-
-
- def test_cgi_multipart_tempfile
- @boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX'
- @data = [
- {:name=>'hidden1', :value=>'foobar'},
- {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A".dup},
- {:name=>'file1', :value=>_read('file1.html'),
- :filename=>'file1.html', :content_type=>'text/html'},
- {:name=>'image1', :value=>_read('large.png'),
- :filename=>'large.png', :content_type=>'image/png'}, # large image
- ]
- @data[1][:value].force_encoding(::Encoding::UTF_8) if defined?(::Encoding)
- @expected_class = Tempfile
- _test_multipart()
- end
-
-
- def _set_const(klass, name, value)
- old = nil
- klass.class_eval do
- old = const_get(name)
- remove_const(name)
- const_set(name, value)
- end
- return old
- end
-
-
- def test_cgi_multipart_maxmultipartlength
- @data = [
- {:name=>'image1', :value=>_read('large.png'),
- :filename=>'large.png', :content_type=>'image/png'}, # large image
- ]
- begin
- ex = assert_raise(StandardError) do
- _test_multipart(:max_multipart_length=>2 * 1024) # set via simple scalar
- end
- assert_equal("too large multipart data.", ex.message)
- ensure
- end
- end
-
-
- def test_cgi_multipart_maxmultipartlength_lambda
- @data = [
- {:name=>'image1', :value=>_read('large.png'),
- :filename=>'large.png', :content_type=>'image/png'}, # large image
- ]
- begin
- ex = assert_raise(StandardError) do
- _test_multipart(:max_multipart_length=>lambda{2*1024}) # set via lambda
- end
- assert_equal("too large multipart data.", ex.message)
- ensure
- end
- end
-
-
- def test_cgi_multipart_maxmultipartcount
- @data = [
- {:name=>'file1', :value=>_read('file1.html'),
- :filename=>'file1.html', :content_type=>'text/html'},
- ]
- item = @data.first
- 500.times { @data << item }
- #original = _set_const(CGI, :MAX_MULTIPART_COUNT, 128)
- begin
- ex = assert_raise(StandardError) do
- _test_multipart()
- end
- assert_equal("too many parameters.", ex.message)
- ensure
- #_set_const(CGI, :MAX_MULTIPART_COUNT, original)
- end
- end if CGI.const_defined?(:MAX_MULTIPART_COUNT)
-
-
- def test_cgi_multipart_badbody ## [ruby-dev:28470]
- @data = [
- {:name=>'file1', :value=>_read('file1.html'),
- :filename=>'file1.html', :content_type=>'text/html'},
- ]
- _prepare(@data) do |input|
- input2 = input.sub(/--(\r\n)?\z/, "\r\n")
- assert input2 != input
- #p input2
- input2
- end
- ex = assert_raise(EOFError) do
- CGI.new(:accept_charset=>"UTF-8")
- end
- assert_equal("bad content body", ex.message)
- #
- _prepare(@data) do |input|
- input2 = input.sub(/--(\r\n)?\z/, "")
- assert input2 != input
- #p input2
- input2
- end
- ex = assert_raise(EOFError) do
- CGI.new(:accept_charset=>"UTF-8")
- end
- assert_equal("bad content body", ex.message)
- end
-
-
- def test_cgi_multipart_quoteboundary ## [JVN#84798830]
- @boundary = '(.|\n)*'
- @data = [
- {:name=>'hidden1', :value=>'foobar'},
- {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A".dup},
- {:name=>'file1', :value=>_read('file1.html'),
- :filename=>'file1.html', :content_type=>'text/html'},
- {:name=>'image1', :value=>_read('small.png'),
- :filename=>'small.png', :content_type=>'image/png'}, # small image
- ]
- @data[1][:value].force_encoding("UTF-8")
- _prepare(@data)
- cgi = CGI.new(:accept_charset=>"UTF-8")
- assert_equal('file1.html', cgi['file1'].original_filename)
- end
-
- def test_cgi_multipart_boundary_10240 # [Bug #3866]
- @boundary = 'AaB03x'
- @data = [
- {:name=>'file', :value=>"b"*10134,
- :filename=>'file.txt', :content_type=>'text/plain'},
- {:name=>'foo', :value=>"bar"},
- ]
- _prepare(@data)
- cgi = CGI.new(:accept_charset=>"UTF-8")
- assert_equal(cgi['foo'], 'bar')
- assert_equal(cgi['file'].read, 'b'*10134)
- cgi['file'].close! if cgi['file'].kind_of? Tempfile
- end
-
- def test_cgi_multipart_without_tempfile
- assert_in_out_err([], <<-'EOM')
- require 'cgi'
- require 'stringio'
- ENV['REQUEST_METHOD'] = 'POST'
- ENV['CONTENT_TYPE'] = 'multipart/form-data; boundary=foobar1234'
- body = <<-BODY.gsub(/\n/, "\r\n")
---foobar1234
-Content-Disposition: form-data: name=\"name1\"
-
-value1
---foobar1234
-Content-Disposition: form-data: name=\"file1\"; filename=\"file1.html\"
-Content-Type: text/html
-
-<html>
-<body><p>Hello</p></body>
-</html>
-
---foobar1234--
-BODY
- ENV['CONTENT_LENGTH'] = body.size.to_s
- $stdin = StringIO.new(body)
- CGI.new
- EOM
- end
-
- ###
-
- self.instance_methods.each do |method|
- private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
- end if ENV['TEST']
-
-end
diff --git a/test/cgi/test_cgi_session.rb b/test/cgi/test_cgi_session.rb
deleted file mode 100644
index 32b907d741..0000000000
--- a/test/cgi/test_cgi_session.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'cgi'
-require 'cgi/session'
-require 'cgi/session/pstore'
-require 'stringio'
-require 'tmpdir'
-require_relative 'update_env'
-
-class CGISessionTest < Test::Unit::TestCase
- include UpdateEnv
-
- def setup
- @environ = {}
- @session_dir = Dir.mktmpdir(%w'session dir')
- end
-
- def teardown
- ENV.update(@environ)
- $stdout = STDOUT
- FileUtils.rm_rf(@session_dir)
- end
-
- def test_cgi_session_filestore
- update_env(
- 'REQUEST_METHOD' => 'GET',
- # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F',
- # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- value1="value1"
- value2="\x8F\xBC\x8D]".dup
- value2.force_encoding("SJIS") if defined?(::Encoding)
- cgi = CGI.new
- session = CGI::Session.new(cgi,"tmpdir"=>@session_dir)
- session["key1"]=value1
- session["key2"]=value2
- assert_equal(value1,session["key1"])
- assert_equal(value2,session["key2"])
- session.close
- $stdout = StringIO.new
- cgi.out{""}
-
- update_env(
- 'REQUEST_METHOD' => 'GET',
- # 'HTTP_COOKIE' => "_session_id=#{session_id}",
- 'QUERY_STRING' => "_session_id=#{session.session_id}",
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- cgi = CGI.new
- session = CGI::Session.new(cgi,"tmpdir"=>@session_dir)
- $stdout = StringIO.new
- assert_equal(value1,session["key1"])
- assert_equal(value2,session["key2"])
- session.close
-
- end
- def test_cgi_session_pstore
- update_env(
- 'REQUEST_METHOD' => 'GET',
- # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F',
- # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- value1="value1"
- value2="\x8F\xBC\x8D]".dup
- value2.force_encoding("SJIS") if defined?(::Encoding)
- cgi = CGI.new
- session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"database_manager"=>CGI::Session::PStore)
- session["key1"]=value1
- session["key2"]=value2
- assert_equal(value1,session["key1"])
- assert_equal(value2,session["key2"])
- session.close
- $stdout = StringIO.new
- cgi.out{""}
-
- update_env(
- 'REQUEST_METHOD' => 'GET',
- # 'HTTP_COOKIE' => "_session_id=#{session_id}",
- 'QUERY_STRING' => "_session_id=#{session.session_id}",
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- cgi = CGI.new
- session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"database_manager"=>CGI::Session::PStore)
- $stdout = StringIO.new
- assert_equal(value1,session["key1"])
- assert_equal(value2,session["key2"])
- session.close
- end if defined?(::PStore)
- def test_cgi_session_specify_session_id
- update_env(
- 'REQUEST_METHOD' => 'GET',
- # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F',
- # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- value1="value1"
- value2="\x8F\xBC\x8D]".dup
- value2.force_encoding("SJIS") if defined?(::Encoding)
- cgi = CGI.new
- session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"session_id"=>"foo")
- session["key1"]=value1
- session["key2"]=value2
- assert_equal(value1,session["key1"])
- assert_equal(value2,session["key2"])
- assert_equal("foo",session.session_id)
- #session_id=session.session_id
- session.close
- $stdout = StringIO.new
- cgi.out{""}
-
- update_env(
- 'REQUEST_METHOD' => 'GET',
- # 'HTTP_COOKIE' => "_session_id=#{session_id}",
- 'QUERY_STRING' => "_session_id=#{session.session_id}",
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- cgi = CGI.new
- session = CGI::Session.new(cgi,"tmpdir"=>@session_dir)
- $stdout = StringIO.new
- assert_equal(value1,session["key1"])
- assert_equal(value2,session["key2"])
- assert_equal("foo",session.session_id)
- session.close
- end
- def test_cgi_session_specify_session_key
- update_env(
- 'REQUEST_METHOD' => 'GET',
- # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F',
- # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- value1="value1"
- value2="\x8F\xBC\x8D]".dup
- value2.force_encoding("SJIS") if defined?(::Encoding)
- cgi = CGI.new
- session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"session_key"=>"bar")
- session["key1"]=value1
- session["key2"]=value2
- assert_equal(value1,session["key1"])
- assert_equal(value2,session["key2"])
- session_id=session.session_id
- session.close
- $stdout = StringIO.new
- cgi.out{""}
-
- update_env(
- 'REQUEST_METHOD' => 'GET',
- 'HTTP_COOKIE' => "bar=#{session_id}",
- # 'QUERY_STRING' => "bar=#{session.session_id}",
- 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
- )
- cgi = CGI.new
- session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"session_key"=>"bar")
- $stdout = StringIO.new
- assert_equal(value1,session["key1"])
- assert_equal(value2,session["key2"])
- session.close
- end
-end
diff --git a/test/cgi/test_cgi_tag_helper.rb b/test/cgi/test_cgi_tag_helper.rb
deleted file mode 100644
index 0b99dfc1bc..0000000000
--- a/test/cgi/test_cgi_tag_helper.rb
+++ /dev/null
@@ -1,355 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'cgi'
-require 'stringio'
-require_relative 'update_env'
-
-
-class CGITagHelperTest < Test::Unit::TestCase
- include UpdateEnv
-
-
- def setup
- @environ = {}
- #@environ = {
- # 'SERVER_PROTOCOL' => 'HTTP/1.1',
- # 'REQUEST_METHOD' => 'GET',
- # 'SERVER_SOFTWARE' => 'Apache 2.2.0',
- #}
- #ENV.update(@environ)
- end
-
-
- def teardown
- ENV.update(@environ)
- $stdout = STDOUT
- end
-
-
- def test_cgi_tag_helper_html3
- update_env(
- 'REQUEST_METHOD' => 'GET',
- )
- ## html3
- cgi = CGI.new('html3')
- assert_equal('<A HREF=""></A>',cgi.a)
- assert_equal('<A HREF="bar"></A>',cgi.a('bar'))
- assert_equal('<A HREF="">foo</A>',cgi.a{'foo'})
- assert_equal('<A HREF="bar">foo</A>',cgi.a('bar'){'foo'})
- assert_equal('<TT></TT>',cgi.tt)
- assert_equal('<TT></TT>',cgi.tt('bar'))
- assert_equal('<TT>foo</TT>',cgi.tt{'foo'})
- assert_equal('<TT>foo</TT>',cgi.tt('bar'){'foo'})
- assert_equal('<I></I>',cgi.i)
- assert_equal('<I></I>',cgi.i('bar'))
- assert_equal('<I>foo</I>',cgi.i{'foo'})
- assert_equal('<I>foo</I>',cgi.i('bar'){'foo'})
- assert_equal('<B></B>',cgi.b)
- assert_equal('<B></B>',cgi.b('bar'))
- assert_equal('<B>foo</B>',cgi.b{'foo'})
- assert_equal('<B>foo</B>',cgi.b('bar'){'foo'})
- assert_equal('<U></U>',cgi.u)
- assert_equal('<U></U>',cgi.u('bar'))
- assert_equal('<U>foo</U>',cgi.u{'foo'})
- assert_equal('<U>foo</U>',cgi.u('bar'){'foo'})
- assert_equal('<STRIKE></STRIKE>',cgi.strike)
- assert_equal('<STRIKE></STRIKE>',cgi.strike('bar'))
- assert_equal('<STRIKE>foo</STRIKE>',cgi.strike{'foo'})
- assert_equal('<STRIKE>foo</STRIKE>',cgi.strike('bar'){'foo'})
- assert_equal('<BIG></BIG>',cgi.big)
- assert_equal('<BIG></BIG>',cgi.big('bar'))
- assert_equal('<BIG>foo</BIG>',cgi.big{'foo'})
- assert_equal('<BIG>foo</BIG>',cgi.big('bar'){'foo'})
- assert_equal('<SMALL></SMALL>',cgi.small)
- assert_equal('<SMALL></SMALL>',cgi.small('bar'))
- assert_equal('<SMALL>foo</SMALL>',cgi.small{'foo'})
- assert_equal('<SMALL>foo</SMALL>',cgi.small('bar'){'foo'})
- assert_equal('<SUB></SUB>',cgi.sub)
- assert_equal('<SUB></SUB>',cgi.sub('bar'))
- assert_equal('<SUB>foo</SUB>',cgi.sub{'foo'})
- assert_equal('<SUB>foo</SUB>',cgi.sub('bar'){'foo'})
- assert_equal('<SUP></SUP>',cgi.sup)
- assert_equal('<SUP></SUP>',cgi.sup('bar'))
- assert_equal('<SUP>foo</SUP>',cgi.sup{'foo'})
- assert_equal('<SUP>foo</SUP>',cgi.sup('bar'){'foo'})
- assert_equal('<EM></EM>',cgi.em)
- assert_equal('<EM></EM>',cgi.em('bar'))
- assert_equal('<EM>foo</EM>',cgi.em{'foo'})
- assert_equal('<EM>foo</EM>',cgi.em('bar'){'foo'})
- assert_equal('<STRONG></STRONG>',cgi.strong)
- assert_equal('<STRONG></STRONG>',cgi.strong('bar'))
- assert_equal('<STRONG>foo</STRONG>',cgi.strong{'foo'})
- assert_equal('<STRONG>foo</STRONG>',cgi.strong('bar'){'foo'})
- assert_equal('<DFN></DFN>',cgi.dfn)
- assert_equal('<DFN></DFN>',cgi.dfn('bar'))
- assert_equal('<DFN>foo</DFN>',cgi.dfn{'foo'})
- assert_equal('<DFN>foo</DFN>',cgi.dfn('bar'){'foo'})
- assert_equal('<CODE></CODE>',cgi.code)
- assert_equal('<CODE></CODE>',cgi.code('bar'))
- assert_equal('<CODE>foo</CODE>',cgi.code{'foo'})
- assert_equal('<CODE>foo</CODE>',cgi.code('bar'){'foo'})
- assert_equal('<SAMP></SAMP>',cgi.samp)
- assert_equal('<SAMP></SAMP>',cgi.samp('bar'))
- assert_equal('<SAMP>foo</SAMP>',cgi.samp{'foo'})
- assert_equal('<SAMP>foo</SAMP>',cgi.samp('bar'){'foo'})
- assert_equal('<KBD></KBD>',cgi.kbd)
- assert_equal('<KBD></KBD>',cgi.kbd('bar'))
- assert_equal('<KBD>foo</KBD>',cgi.kbd{'foo'})
- assert_equal('<KBD>foo</KBD>',cgi.kbd('bar'){'foo'})
- assert_equal('<VAR></VAR>',cgi.var)
- assert_equal('<VAR></VAR>',cgi.var('bar'))
- assert_equal('<VAR>foo</VAR>',cgi.var{'foo'})
- assert_equal('<VAR>foo</VAR>',cgi.var('bar'){'foo'})
- assert_equal('<CITE></CITE>',cgi.cite)
- assert_equal('<CITE></CITE>',cgi.cite('bar'))
- assert_equal('<CITE>foo</CITE>',cgi.cite{'foo'})
- assert_equal('<CITE>foo</CITE>',cgi.cite('bar'){'foo'})
- assert_equal('<FONT></FONT>',cgi.font)
- assert_equal('<FONT></FONT>',cgi.font('bar'))
- assert_equal('<FONT>foo</FONT>',cgi.font{'foo'})
- assert_equal('<FONT>foo</FONT>',cgi.font('bar'){'foo'})
- assert_equal('<ADDRESS></ADDRESS>',cgi.address)
- assert_equal('<ADDRESS></ADDRESS>',cgi.address('bar'))
- assert_equal('<ADDRESS>foo</ADDRESS>',cgi.address{'foo'})
- assert_equal('<ADDRESS>foo</ADDRESS>',cgi.address('bar'){'foo'})
- assert_equal('<DIV></DIV>',cgi.div)
- assert_equal('<DIV></DIV>',cgi.div('bar'))
- assert_equal('<DIV>foo</DIV>',cgi.div{'foo'})
- assert_equal('<DIV>foo</DIV>',cgi.div('bar'){'foo'})
- assert_equal('<CENTER></CENTER>',cgi.center)
- assert_equal('<CENTER></CENTER>',cgi.center('bar'))
- assert_equal('<CENTER>foo</CENTER>',cgi.center{'foo'})
- assert_equal('<CENTER>foo</CENTER>',cgi.center('bar'){'foo'})
- assert_equal('<MAP></MAP>',cgi.map)
- assert_equal('<MAP></MAP>',cgi.map('bar'))
- assert_equal('<MAP>foo</MAP>',cgi.map{'foo'})
- assert_equal('<MAP>foo</MAP>',cgi.map('bar'){'foo'})
- assert_equal('<APPLET></APPLET>',cgi.applet)
- assert_equal('<APPLET></APPLET>',cgi.applet('bar'))
- assert_equal('<APPLET>foo</APPLET>',cgi.applet{'foo'})
- assert_equal('<APPLET>foo</APPLET>',cgi.applet('bar'){'foo'})
- assert_equal('<PRE></PRE>',cgi.pre)
- assert_equal('<PRE></PRE>',cgi.pre('bar'))
- assert_equal('<PRE>foo</PRE>',cgi.pre{'foo'})
- assert_equal('<PRE>foo</PRE>',cgi.pre('bar'){'foo'})
- assert_equal('<XMP></XMP>',cgi.xmp)
- assert_equal('<XMP></XMP>',cgi.xmp('bar'))
- assert_equal('<XMP>foo</XMP>',cgi.xmp{'foo'})
- assert_equal('<XMP>foo</XMP>',cgi.xmp('bar'){'foo'})
- assert_equal('<LISTING></LISTING>',cgi.listing)
- assert_equal('<LISTING></LISTING>',cgi.listing('bar'))
- assert_equal('<LISTING>foo</LISTING>',cgi.listing{'foo'})
- assert_equal('<LISTING>foo</LISTING>',cgi.listing('bar'){'foo'})
- assert_equal('<DL></DL>',cgi.dl)
- assert_equal('<DL></DL>',cgi.dl('bar'))
- assert_equal('<DL>foo</DL>',cgi.dl{'foo'})
- assert_equal('<DL>foo</DL>',cgi.dl('bar'){'foo'})
- assert_equal('<OL></OL>',cgi.ol)
- assert_equal('<OL></OL>',cgi.ol('bar'))
- assert_equal('<OL>foo</OL>',cgi.ol{'foo'})
- assert_equal('<OL>foo</OL>',cgi.ol('bar'){'foo'})
- assert_equal('<UL></UL>',cgi.ul)
- assert_equal('<UL></UL>',cgi.ul('bar'))
- assert_equal('<UL>foo</UL>',cgi.ul{'foo'})
- assert_equal('<UL>foo</UL>',cgi.ul('bar'){'foo'})
- assert_equal('<DIR></DIR>',cgi.dir)
- assert_equal('<DIR></DIR>',cgi.dir('bar'))
- assert_equal('<DIR>foo</DIR>',cgi.dir{'foo'})
- assert_equal('<DIR>foo</DIR>',cgi.dir('bar'){'foo'})
- assert_equal('<MENU></MENU>',cgi.menu)
- assert_equal('<MENU></MENU>',cgi.menu('bar'))
- assert_equal('<MENU>foo</MENU>',cgi.menu{'foo'})
- assert_equal('<MENU>foo</MENU>',cgi.menu('bar'){'foo'})
- assert_equal('<SELECT></SELECT>',cgi.select)
- assert_equal('<SELECT></SELECT>',cgi.select('bar'))
- assert_equal('<SELECT>foo</SELECT>',cgi.select{'foo'})
- assert_equal('<SELECT>foo</SELECT>',cgi.select('bar'){'foo'})
- assert_equal('<TABLE></TABLE>',cgi.table)
- assert_equal('<TABLE></TABLE>',cgi.table('bar'))
- assert_equal('<TABLE>foo</TABLE>',cgi.table{'foo'})
- assert_equal('<TABLE>foo</TABLE>',cgi.table('bar'){'foo'})
- assert_equal('<TITLE></TITLE>',cgi.title)
- assert_equal('<TITLE></TITLE>',cgi.title('bar'))
- assert_equal('<TITLE>foo</TITLE>',cgi.title{'foo'})
- assert_equal('<TITLE>foo</TITLE>',cgi.title('bar'){'foo'})
- assert_equal('<STYLE></STYLE>',cgi.style)
- assert_equal('<STYLE></STYLE>',cgi.style('bar'))
- assert_equal('<STYLE>foo</STYLE>',cgi.style{'foo'})
- assert_equal('<STYLE>foo</STYLE>',cgi.style('bar'){'foo'})
- assert_equal('<SCRIPT></SCRIPT>',cgi.script)
- assert_equal('<SCRIPT></SCRIPT>',cgi.script('bar'))
- assert_equal('<SCRIPT>foo</SCRIPT>',cgi.script{'foo'})
- assert_equal('<SCRIPT>foo</SCRIPT>',cgi.script('bar'){'foo'})
- assert_equal('<H1></H1>',cgi.h1)
- assert_equal('<H1></H1>',cgi.h1('bar'))
- assert_equal('<H1>foo</H1>',cgi.h1{'foo'})
- assert_equal('<H1>foo</H1>',cgi.h1('bar'){'foo'})
- assert_equal('<H2></H2>',cgi.h2)
- assert_equal('<H2></H2>',cgi.h2('bar'))
- assert_equal('<H2>foo</H2>',cgi.h2{'foo'})
- assert_equal('<H2>foo</H2>',cgi.h2('bar'){'foo'})
- assert_equal('<H3></H3>',cgi.h3)
- assert_equal('<H3></H3>',cgi.h3('bar'))
- assert_equal('<H3>foo</H3>',cgi.h3{'foo'})
- assert_equal('<H3>foo</H3>',cgi.h3('bar'){'foo'})
- assert_equal('<H4></H4>',cgi.h4)
- assert_equal('<H4></H4>',cgi.h4('bar'))
- assert_equal('<H4>foo</H4>',cgi.h4{'foo'})
- assert_equal('<H4>foo</H4>',cgi.h4('bar'){'foo'})
- assert_equal('<H5></H5>',cgi.h5)
- assert_equal('<H5></H5>',cgi.h5('bar'))
- assert_equal('<H5>foo</H5>',cgi.h5{'foo'})
- assert_equal('<H5>foo</H5>',cgi.h5('bar'){'foo'})
- assert_equal('<H6></H6>',cgi.h6)
- assert_equal('<H6></H6>',cgi.h6('bar'))
- assert_equal('<H6>foo</H6>',cgi.h6{'foo'})
- assert_equal('<H6>foo</H6>',cgi.h6('bar'){'foo'})
- assert_match(/^<TEXTAREA .*><\/TEXTAREA>$/,cgi.textarea)
- assert_match(/COLS="70"/,cgi.textarea)
- assert_match(/ROWS="10"/,cgi.textarea)
- assert_match(/NAME=""/,cgi.textarea)
- assert_match(/^<TEXTAREA .*><\/TEXTAREA>$/,cgi.textarea("bar"))
- assert_match(/COLS="70"/,cgi.textarea("bar"))
- assert_match(/ROWS="10"/,cgi.textarea("bar"))
- assert_match(/NAME="bar"/,cgi.textarea("bar"))
- assert_match(/^<TEXTAREA .*>foo<\/TEXTAREA>$/,cgi.textarea{"foo"})
- assert_match(/COLS="70"/,cgi.textarea{"foo"})
- assert_match(/ROWS="10"/,cgi.textarea{"foo"})
- assert_match(/NAME=""/,cgi.textarea{"foo"})
- assert_match(/^<TEXTAREA .*>foo<\/TEXTAREA>$/,cgi.textarea("bar"){"foo"})
- assert_match(/COLS="70"/,cgi.textarea("bar"){"foo"})
- assert_match(/ROWS="10"/,cgi.textarea("bar"){"foo"})
- assert_match(/NAME="bar"/,cgi.textarea("bar"){"foo"})
- assert_match(/^<FORM .*><\/FORM>$/,cgi.form)
- assert_match(/METHOD="post"/,cgi.form)
- assert_match(/ENCTYPE="application\/x-www-form-urlencoded"/,cgi.form)
- assert_match(/^<FORM .*><\/FORM>$/,cgi.form("bar"))
- assert_match(/METHOD="bar"/,cgi.form("bar"))
- assert_match(/ENCTYPE="application\/x-www-form-urlencoded"/,cgi.form("bar"))
- assert_match(/^<FORM .*>foo<\/FORM>$/,cgi.form{"foo"})
- assert_match(/METHOD="post"/,cgi.form{"foo"})
- assert_match(/ENCTYPE="application\/x-www-form-urlencoded"/,cgi.form{"foo"})
- assert_match(/^<FORM .*>foo<\/FORM>$/,cgi.form("bar"){"foo"})
- assert_match(/METHOD="bar"/,cgi.form("bar"){"foo"})
- assert_match(/ENCTYPE="application\/x-www-form-urlencoded"/,cgi.form("bar"){"foo"})
- assert_equal('<BLOCKQUOTE></BLOCKQUOTE>',cgi.blockquote)
- assert_equal('<BLOCKQUOTE CITE="bar"></BLOCKQUOTE>',cgi.blockquote('bar'))
- assert_equal('<BLOCKQUOTE>foo</BLOCKQUOTE>',cgi.blockquote{'foo'})
- assert_equal('<BLOCKQUOTE CITE="bar">foo</BLOCKQUOTE>',cgi.blockquote('bar'){'foo'})
- assert_equal('<CAPTION></CAPTION>',cgi.caption)
- assert_equal('<CAPTION ALIGN="bar"></CAPTION>',cgi.caption('bar'))
- assert_equal('<CAPTION>foo</CAPTION>',cgi.caption{'foo'})
- assert_equal('<CAPTION ALIGN="bar">foo</CAPTION>',cgi.caption('bar'){'foo'})
- assert_equal('<IMG SRC="" ALT="">',cgi.img)
- assert_equal('<IMG SRC="bar" ALT="">',cgi.img('bar'))
- assert_equal('<IMG SRC="" ALT="">',cgi.img{'foo'})
- assert_equal('<IMG SRC="bar" ALT="">',cgi.img('bar'){'foo'})
- assert_equal('<BASE HREF="">',cgi.base)
- assert_equal('<BASE HREF="bar">',cgi.base('bar'))
- assert_equal('<BASE HREF="">',cgi.base{'foo'})
- assert_equal('<BASE HREF="bar">',cgi.base('bar'){'foo'})
- assert_equal('<BASEFONT>',cgi.basefont)
- assert_equal('<BASEFONT>',cgi.basefont('bar'))
- assert_equal('<BASEFONT>',cgi.basefont{'foo'})
- assert_equal('<BASEFONT>',cgi.basefont('bar'){'foo'})
- assert_equal('<BR>',cgi.br)
- assert_equal('<BR>',cgi.br('bar'))
- assert_equal('<BR>',cgi.br{'foo'})
- assert_equal('<BR>',cgi.br('bar'){'foo'})
- assert_equal('<AREA>',cgi.area)
- assert_equal('<AREA>',cgi.area('bar'))
- assert_equal('<AREA>',cgi.area{'foo'})
- assert_equal('<AREA>',cgi.area('bar'){'foo'})
- assert_equal('<LINK>',cgi.link)
- assert_equal('<LINK>',cgi.link('bar'))
- assert_equal('<LINK>',cgi.link{'foo'})
- assert_equal('<LINK>',cgi.link('bar'){'foo'})
- assert_equal('<PARAM>',cgi.param)
- assert_equal('<PARAM>',cgi.param('bar'))
- assert_equal('<PARAM>',cgi.param{'foo'})
- assert_equal('<PARAM>',cgi.param('bar'){'foo'})
- assert_equal('<HR>',cgi.hr)
- assert_equal('<HR>',cgi.hr('bar'))
- assert_equal('<HR>',cgi.hr{'foo'})
- assert_equal('<HR>',cgi.hr('bar'){'foo'})
- assert_equal('<INPUT>',cgi.input)
- assert_equal('<INPUT>',cgi.input('bar'))
- assert_equal('<INPUT>',cgi.input{'foo'})
- assert_equal('<INPUT>',cgi.input('bar'){'foo'})
- assert_equal('<ISINDEX>',cgi.isindex)
- assert_equal('<ISINDEX>',cgi.isindex('bar'))
- assert_equal('<ISINDEX>',cgi.isindex{'foo'})
- assert_equal('<ISINDEX>',cgi.isindex('bar'){'foo'})
- assert_equal('<META>',cgi.meta)
- assert_equal('<META>',cgi.meta('bar'))
- assert_equal('<META>',cgi.meta{'foo'})
- assert_equal('<META>',cgi.meta('bar'){'foo'})
- assert_equal('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>',cgi.html)
- assert_equal('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>foo</HTML>',cgi.html{'foo'})
- assert_equal('<HEAD>',cgi.head)
- assert_equal('<HEAD>foo</HEAD>',cgi.head{'foo'})
- assert_equal('<BODY>',cgi.body)
- assert_equal('<BODY>foo</BODY>',cgi.body{'foo'})
- assert_equal('<P>',cgi.p)
- assert_equal('<P>foo</P>',cgi.p{'foo'})
- assert_equal('<PLAINTEXT>',cgi.plaintext)
- assert_equal('<PLAINTEXT>foo</PLAINTEXT>',cgi.plaintext{'foo'})
- assert_equal('<DT>',cgi.dt)
- assert_equal('<DT>foo</DT>',cgi.dt{'foo'})
- assert_equal('<DD>',cgi.dd)
- assert_equal('<DD>foo</DD>',cgi.dd{'foo'})
- assert_equal('<LI>',cgi.li)
- assert_equal('<LI>foo</LI>',cgi.li{'foo'})
- assert_equal('<OPTION>',cgi.option)
- assert_equal('<OPTION>foo</OPTION>',cgi.option{'foo'})
- assert_equal('<TR>',cgi.tr)
- assert_equal('<TR>foo</TR>',cgi.tr{'foo'})
- assert_equal('<TH>',cgi.th)
- assert_equal('<TH>foo</TH>',cgi.th{'foo'})
- assert_equal('<TD>',cgi.td)
- assert_equal('<TD>foo</TD>',cgi.td{'foo'})
- str=cgi.checkbox_group("foo",["aa","bb"],["cc","dd"])
- assert_match(/^<INPUT .*VALUE="aa".*>bb<INPUT .*VALUE="cc".*>dd$/,str)
- assert_match(/^<INPUT .*TYPE="checkbox".*>bb<INPUT .*TYPE="checkbox".*>dd$/,str)
- assert_match(/^<INPUT .*NAME="foo".*>bb<INPUT .*NAME="foo".*>dd$/,str)
- str=cgi.radio_group("foo",["aa","bb"],["cc","dd"])
- assert_match(/^<INPUT .*VALUE="aa".*>bb<INPUT .*VALUE="cc".*>dd$/,str)
- assert_match(/^<INPUT .*TYPE="radio".*>bb<INPUT .*TYPE="radio".*>dd$/,str)
- assert_match(/^<INPUT .*NAME="foo".*>bb<INPUT .*NAME="foo".*>dd$/,str)
- str=cgi.checkbox_group("foo",["aa","bb"],["cc","dd",true])
- assert_match(/^<INPUT .*VALUE="aa".*>bb<INPUT .*VALUE="cc".*>dd$/,str)
- assert_match(/^<INPUT .*TYPE="checkbox".*>bb<INPUT .*TYPE="checkbox".*>dd$/,str)
- assert_match(/^<INPUT .*NAME="foo".*>bb<INPUT .*NAME="foo".*>dd$/,str)
- assert_match(/^<INPUT .*>bb<INPUT .*CHECKED.*>dd$/,str)
- assert_match(/<INPUT .*TYPE="text".*>/,cgi.text_field(:name=>"name",:value=>"value"))
- str=cgi.radio_group("foo",["aa","bb"],["cc","dd",false])
- assert_match(/^<INPUT .*VALUE="aa".*>bb<INPUT .*VALUE="cc".*>dd$/,str)
- assert_match(/^<INPUT .*TYPE="radio".*>bb<INPUT .*TYPE="radio".*>dd$/,str)
- assert_match(/^<INPUT .*NAME="foo".*>bb<INPUT .*NAME="foo".*>dd$/,str)
- end
-
-=begin
- def test_cgi_tag_helper_html4
- ## html4
- cgi = CGI.new('html4')
- ## html4 transitional
- cgi = CGI.new('html4Tr')
- ## html4 frameset
- cgi = CGI.new('html4Fr')
- end
-=end
-
- def test_cgi_tag_helper_html5
- update_env(
- 'REQUEST_METHOD' => 'GET',
- )
- ## html5
- cgi = CGI.new('html5')
- assert_equal('<HEADER></HEADER>',cgi.header)
- assert_equal('<FOOTER></FOOTER>',cgi.footer)
- assert_equal('<ARTICLE></ARTICLE>',cgi.article)
- assert_equal('<SECTION></SECTION>',cgi.section)
- assert_equal('<!DOCTYPE HTML><HTML BLA="TEST"></HTML>',cgi.html("BLA"=>"TEST"){})
- end
-
-end
diff --git a/test/cgi/test_cgi_util.rb b/test/cgi/test_cgi_util.rb
deleted file mode 100644
index 50f85e3967..0000000000
--- a/test/cgi/test_cgi_util.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'cgi/util'
-
-class CGIUtilTest < Test::Unit::TestCase
-
- def test_cgi_pretty
- assert_equal("<HTML>\n <BODY>\n </BODY>\n</HTML>\n",CGI.pretty("<HTML><BODY></BODY></HTML>"))
- assert_equal("<HTML>\n\t<BODY>\n\t</BODY>\n</HTML>\n",CGI.pretty("<HTML><BODY></BODY></HTML>","\t"))
- end
-
-end
diff --git a/test/cgi/testdata/file1.html b/test/cgi/testdata/file1.html
deleted file mode 100644
index 2ceaf6bc39..0000000000
--- a/test/cgi/testdata/file1.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
- <head>
- <title>ムスカ大佐のひとりごと</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF8">
- </head>
- <body>
- <p>バカどもにはちょうどいい目くらましだ。</p>
- </body>
-</html>
diff --git a/test/cgi/testdata/large.png b/test/cgi/testdata/large.png
deleted file mode 100644
index d716396fa3..0000000000
--- a/test/cgi/testdata/large.png
+++ /dev/null
Binary files differ
diff --git a/test/cgi/testdata/small.png b/test/cgi/testdata/small.png
deleted file mode 100644
index 753d58e3cb..0000000000
--- a/test/cgi/testdata/small.png
+++ /dev/null
Binary files differ