diff options
author | Hiroshi SHIBATA <[email protected]> | 2025-05-08 19:21:47 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2025-05-09 14:27:28 +0900 |
commit | 600c616507b258cdf9dbfbc822deb267f3202325 (patch) | |
tree | aff8f5b0847a0301391f2dc5463049b0d7cd4e33 | |
parent | a61f51f66d7dff966dd17915c854fea08763722d (diff) |
Removed CGI library without CGI::Escape features
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/13275
-rw-r--r-- | lib/cgi.rb | 298 | ||||
-rw-r--r-- | lib/cgi/cgi.gemspec | 43 | ||||
-rw-r--r-- | lib/cgi/cookie.rb | 210 | ||||
-rw-r--r-- | lib/cgi/core.rb | 900 | ||||
-rw-r--r-- | lib/cgi/html.rb | 1035 | ||||
-rw-r--r-- | lib/cgi/session.rb | 562 | ||||
-rw-r--r-- | lib/cgi/session/pstore.rb | 91 | ||||
-rw-r--r-- | lib/cgi/util.rb | 44 | ||||
-rw-r--r-- | test/cgi/test_cgi_cookie.rb | 211 | ||||
-rw-r--r-- | test/cgi/test_cgi_core.rb | 307 | ||||
-rw-r--r-- | test/cgi/test_cgi_header.rb | 192 | ||||
-rw-r--r-- | test/cgi/test_cgi_modruby.rb | 149 | ||||
-rw-r--r-- | test/cgi/test_cgi_multipart.rb | 385 | ||||
-rw-r--r-- | test/cgi/test_cgi_session.rb | 169 | ||||
-rw-r--r-- | test/cgi/test_cgi_tag_helper.rb | 355 | ||||
-rw-r--r-- | test/cgi/test_cgi_util.rb | 12 | ||||
-rw-r--r-- | test/cgi/testdata/file1.html | 10 | ||||
-rw-r--r-- | test/cgi/testdata/large.png | bin | 156414 -> 0 bytes | |||
-rw-r--r-- | test/cgi/testdata/small.png | bin | 82 -> 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 Binary files differdeleted file mode 100644 index d716396fa3..0000000000 --- a/test/cgi/testdata/large.png +++ /dev/null diff --git a/test/cgi/testdata/small.png b/test/cgi/testdata/small.png Binary files differdeleted file mode 100644 index 753d58e3cb..0000000000 --- a/test/cgi/testdata/small.png +++ /dev/null |