From 94c2e6f18a7e3146802ebc5c08b4cbec627143f5 Mon Sep 17 00:00:00 2001 From: gsinclair Date: Tue, 19 Aug 2003 14:39:47 +0000 Subject: RD -> RDoc, with embellishments, by William Webber. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4413 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/cgi.rb | 1779 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 1055 insertions(+), 724 deletions(-) diff --git a/lib/cgi.rb b/lib/cgi.rb index 705b0ccf13..ee315cc48d 100644 --- a/lib/cgi.rb +++ b/lib/cgi.rb @@ -1,194 +1,297 @@ -=begin - -== NAME - -cgi.rb - cgi support library - -Copyright (C) 2000 Network Applied Communication Laboratory, Inc. - -Copyright (C) 2000 Information-technology Promotion Agency, Japan - -Wakou Aoyama - - - -== EXAMPLE - -=== 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! cgi['field_name'] retuen Array with old cgi.rb(included 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"} - -and see MAKE COOKIE OBJECT. - - -=== GET ENVIRONMENT VALUE - - require "cgi" - cgi = CGI.new - value = cgi.auth_type - # ENV["AUTH_TYPE"] - -see http://www.w3.org/CGI/ - -AUTH_TYPE CONTENT_LENGTH 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_PORT -SERVER_PROTOCOL SERVER_SOFTWARE - -content_length and server_port return Integer. and the others return String. - -and HTTP_COOKIE, HTTP_COOKIE2 - - value = cgi.raw_cookie - # ENV["HTTP_COOKIE"] - value = cgi.raw_cookie2 - # ENV["HTTP_COOKIE2"] - -and other HTTP_* - - value = cgi.accept - # ENV["HTTP_ACCEPT"] - value = cgi.accept_charset - # ENV["HTTP_ACCEPT_CHARSET"] - -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 - - -=== PRINT HTTP HEADER AND HTML STRING TO $DEFAULT_OUTPUT ($>) - - require "cgi" - cgi = CGI.new("html3") # add HTML generation methods - cgi.out() do - cgi.html() do - cgi.head{ cgi.title{"TITLE"} } + - cgi.body() do - cgi.form() do - cgi.textarea("get_text") + - cgi.br + - cgi.submit - 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 - - -=end +# +# cgi.rb - cgi support library +# +# Copyright (C) 2000 Network Applied Communication Laboratory, Inc. +# +# Copyright (C) 2000 Information-technology Promotion Agency, Japan +# +# Author: Wakou Aoyama +# +# 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. See the +# class documentation for more details and examples of use. +# +# The file cgi/session.rb provides session management +# functionality; see that file for more details. +# +# See http://www.w3.org/CGI/ for more information on the CGI +# protocol. raise "Please, use ruby1.5.4 or later." if RUBY_VERSION < "1.5.4" require 'English' +# CGI class. See documentation for the file cgi.rb for an overview +# of 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 behaviour 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 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 #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. +# +# == 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! cgi['field_name'] 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("html3") # add HTML generation methods +# cgi.out() do +# cgi.html() do +# cgi.head{ cgi.title{"TITLE"} } + +# cgi.body() do +# cgi.form() do +# cgi.textarea("get_text") + +# cgi.br + +# cgi.submit +# 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 +# class CGI + # :stopdoc: + + # String for carriage return CR = "\015" + + # String for linefeed LF = "\012" + + # Standard internet newline sequence EOL = CR + LF - REVISION = '$Id$' - NEEDS_BINMODE = true if /WIN/ni.match(RUBY_PLATFORM) + REVISION = '$Id$' #:nodoc: + + NEEDS_BINMODE = true if /WIN/ni.match(RUBY_PLATFORM) + + # Path separators in different environments. PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'} + # HTTP status codes. HTTP_STATUS = { "OK" => "200 OK", "PARTIAL_CONTENT" => "206 Partial Content", @@ -210,10 +313,15 @@ class CGI "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates" } + # Abbreviated day-of-week names specified by RFC 822 RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ] + + # Abbreviated month names specified by RFC 822 RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ] - def env_table + # :startdoc: + + def env_table ENV end @@ -227,14 +335,9 @@ class CGI private :env_table, :stdinput, :stdoutput -=begin -== METHODS -=end - -=begin -=== ESCAPE URL ENCODE - url_encoded_string = CGI::escape("string") -=end + # URL-encode a string. + # url_encoded_string = CGI::escape("'Stop!' said Fred") + # # => "%27Stop%21%27+said+Fred" def CGI::escape(string) string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do '%' + $1.unpack('H2' * $1.size).join('%').upcase @@ -242,10 +345,9 @@ class CGI end -=begin -=== UNESCAPE URL ENCODED - string = CGI::unescape("url encoded string") -=end + # URL-decode a string. + # string = CGI::unescape("%27Stop%21%27+said+Fred") + # # => "'Stop!' said Fred" def CGI::unescape(string) string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do [$1.delete('%')].pack('H*') @@ -253,19 +355,17 @@ class CGI end -=begin -=== ESCAPE HTML &\"<> - CGI::escapeHTML("string") -=end + # Escape special characters in HTML, namely &\"<> + # CGI::escapeHTML('Usage: foo "bar" ') + # # => "Usage: foo "bar" <baz>" def CGI::escapeHTML(string) string.gsub(/&/n, '&').gsub(/\"/n, '"').gsub(/>/n, '>').gsub(/ "Usage: foo \"bar\" " def CGI::unescapeHTML(string) string.gsub(/&(.*?);/n) do match = $1.dup @@ -301,14 +401,19 @@ class CGI end -=begin -=== ESCAPE ELEMENT - print CGI::escapeElement('
', "A", "IMG") - # "
<A HREF="url"></A>" - - print CGI::escapeElement('
', ["A", "IMG"]) - # "
<A HREF="url"></A>" -=end + # Escape only the tags of certain HTML elements in +string+. + # + # Takes an element or elements or array of elements. Each element + # is specified by the name of the element, without angle brackets. + # This matches both the start and the end tag of that element. + # The attribute list of the open tag will also be escaped (for + # instance, the double-quotes surrounding attribute values). + # + # print CGI::escapeElement('
', "A", "IMG") + # # "
<A HREF="url"></A>" + # + # print CGI::escapeElement('
', ["A", "IMG"]) + # # "
<A HREF="url"></A>" def CGI::escapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? @@ -321,16 +426,15 @@ class CGI end -=begin -=== UNESCAPE ELEMENT - print CGI::unescapeElement( - CGI::escapeHTML('
'), "A", "IMG") - # "<BR>" - - print CGI::unescapeElement( - CGI::escapeHTML('
'), ["A", "IMG"]) - # "<BR>" -=end + # Undo escaping such as that done by CGI::escapeElement() + # + # print CGI::unescapeElement( + # CGI::escapeHTML('
'), "A", "IMG") + # # "<BR>" + # + # print CGI::unescapeElement( + # CGI::escapeHTML('
'), ["A", "IMG"]) + # # "<BR>" def CGI::unescapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? @@ -343,11 +447,10 @@ class CGI end -=begin -=== MAKE RFC1123 DATE STRING - CGI::rfc1123_date(Time.now) - # Sat, 01 Jan 2000 00:00:00 GMT -=end + # 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 CGI::rfc1123_date(time) t = time.clone.gmtime return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", @@ -356,52 +459,83 @@ class CGI end -=begin -=== MAKE HTTP HEADER STRING - header - # Content-Type: text/html - - header("text/plain") - # Content-Type: text/plain - - 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 - "language" => "ja", - "expires" => Time.now + 30, - "cookie" => [cookie1, cookie2], - "my_header1" => "my_value" - "my_header2" => "my_value"}) - -header will not convert charset. - -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 Rrecondition 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" - -=end + # Create an HTTP header block as a string. + # + # Includes the empty line that ends the header block. + # + # +options+ can be a string specifying the Content-Type (defaults + # to text/html), or a hash of header key/value pairs. 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, returned as the Status header. See the + # list of available status codes below. + # 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 header lines can also be set; they are appended as key: value. + # + # header + # # Content-Type: text/html + # + # header("text/plain") + # # Content-Type: text/plain + # + # 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") + # + # The status codes 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 Rrecondition 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" + # + # This method does not perform charset conversion. + # def header(options = "text/html") buf = "" @@ -523,41 +657,49 @@ status: end # header() -=begin -=== PRINT HTTP HEADER AND STRING TO $DEFAULT_OUTPUT ($>) - 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" } - -if "HEAD" == REQUEST_METHOD then output only HTTP header. - -if charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then -convert string charset, and set language to "ja". - -=end - def out(options = "text/html") + # Print an HTTP header and body to $DEFAULT_OUTPUT ($>) + # + # The header is provided by +options+, as for #header(). + # The body of the document is that returned by the passed- + # in block. This block takes no arguments. It is required. + # + # 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" } + # + # Content-Length is automatically calculated from the size of + # the String returned by the content block. + # + # If ENV['REQUEST_METHOD'] == "HEAD", then only the header + # is outputted (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". + def out(options = "text/html") # :yield: options = { "type" => options } if options.kind_of?(String) content = yield @@ -585,47 +727,69 @@ convert string charset, and set language to "ja". end -=begin -=== PRINT - cgi = CGI.new - cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print -=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 - -=begin -=== MAKE COOKIE OBJECT - 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 - }) - - cgi.out({"cookie" => [cookie1, cookie2]}){ "string" } - - name = cookie1.name - values = cookie1.value - path = cookie1.path - domain = cookie1.domain - expires = cookie1.expires - secure = cookie1.secure - - cookie1.name = 'name' - cookie1.value = ['value1', 'value2', ...] - cookie1.path = 'path' - cookie1.domain = 'domain' - cookie1.expires = Time.now + 30 - cookie1.secure = true -=end require "delegate" + + # 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 + # ) + # + # cgi.out("cookie" => [cookie1, cookie2]) { "string" } + # + # name = cookie1.name + # values = cookie1.value + # path = cookie1.path + # domain = cookie1.domain + # expires = cookie1.expires + # secure = cookie1.secure + # + # cookie1.name = 'name' + # cookie1.value = ['value1', 'value2', ...] + # cookie1.path = 'path' + # cookie1.domain = 'domain' + # cookie1.expires = Time.now + 30 + # cookie1.secure = true class Cookie < SimpleDelegator + # Create a new CGI::Cookie object. + # + # The contents of the cookie can be specified as a +name+ and one + # or more +value+ arguments. Alternatively, the contents can + # be specified as a single hash argument. The possible keywords of + # this hash are as follows: + # + # 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 + # base directory of the CGI script. + # domain:: the 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. + # + # These keywords correspond to attributes of the cookie object. def initialize(name = "", *value) options = if name.kind_of?(String) { "name" => name, "value" => value } @@ -654,11 +818,16 @@ convert string charset, and set language to "ja". attr_accessor("name", "value", "path", "domain", "expires") attr_reader("secure") + + # 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 + # Convert the Cookie to its string representation. def to_s buf = "" buf += @name + '=' @@ -691,11 +860,12 @@ convert string charset, and set language to "ja". end # class Cookie -=begin -=== PARSE RAW COOKIE STRING - cookies = CGI::Cookie::parse("raw_cookie_string") - # { "name1" => cookie1, "name2" => cookie2, ... } -=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 Cookie::parse(raw_cookie) cookies = Hash.new([]) return cookies unless raw_cookie @@ -713,13 +883,12 @@ convert string charset, and set language to "ja". cookies end - -=begin -=== PARSE QUERY STRING - params = CGI::parse("query_string") - # {"name1" => ["value1", "value2", ...], - # "name2" => ["value1", "value2", ...], ... } -=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 CGI::parse(query) params = Hash.new([]) @@ -735,7 +904,20 @@ convert string charset, and set language to "ja". params end - + # Mixin module. It provides the follow functionality groups: + # + # 1. Access to CGI environment variables as methods. See + # documentation to the CGI class for a list of these variables. + # + # 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 initialising the above + # mechanisms, handling multipart forms, and allowing the + # class to be used in "offline" mode. + # module QueryExtension for env in %w[ CONTENT_LENGTH SERVER_PORT ] @@ -761,16 +943,24 @@ convert string charset, and set language to "ja". 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("params") + + # Set all the parameters. def params=(hash) @params.clear @params.update(hash) @@ -913,6 +1103,10 @@ convert string charset, and set language to "ja". end private :read_from_cmdline + # 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=\"?([^\";,]+)\"?|n.match(env_table['CONTENT_TYPE']) @@ -942,7 +1136,7 @@ convert string charset, and set language to "ja". end private :initialize_query - class Value < String + class Value < String # :nodoc: def initialize(str, params) @params = params super(str) @@ -964,6 +1158,10 @@ convert string charset, and set language to "ja". end 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] value = params[0] @@ -980,10 +1178,12 @@ convert string charset, and set language to "ja". end end + # Return all parameter keys as an array. def keys(*args) @params.keys(*args) end + # Returns true if a given parameter key exists in the query. def has_key?(*args) @params.has_key?(*args) end @@ -993,20 +1193,23 @@ convert string charset, and set language to "ja". end # QueryExtension -=begin -=== HTML PRETTY FORMAT - print CGI::pretty("") - # - # - # - # - - print CGI::pretty("", "\t") - # - # - # - # -=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("") + # # + # # + # # + # # + # + # print CGI::pretty("", "\t") + # # + # # + # # + # # + # def CGI::pretty(string, shift = " ") lines = string.gsub(/(?!\A)<(?:.|\n)*?>/n, "\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/n, "\\0\n") end_pos = 0 @@ -1019,27 +1222,15 @@ convert string charset, and set language to "ja". end -=begin -== HTML ELEMENTS - - cgi = CGI.new("html3") # add HTML generation methods - cgi.element - cgi.element{ "string" } - cgi.element({ "ATTRIBUTE1" => "value1", "ATTRIBUTE2" => "value2" }) - cgi.element({ "ATTRIBUTE1" => "value1", "ATTRIBUTE2" => "value2" }){ "string" } - - # add HTML generation methods - CGI.new("html3") # html3.2 - CGI.new("html4") # html4.0 (Strict) - CGI.new("html4Tr") # html4.0 Transitional - CGI.new("html4Fr") # html4.0 Frameset - -=end - - - module TagMaker + # 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_def(element) <<-END.gsub(/element\.downcase/n, element.downcase).gsub(/element\.upcase/n, element.upcase) " "Example" + # + # Modules Http3, Http4, etc., contain more basic HTML-generation methods + # (:title, :center, etc.). + # + # See class CGI for a detailed example. + # module HtmlExtension -=begin -=== A ELEMENT - a("url") - # = a({ "HREF" => "url" }) -=end - def a(href = "") + # 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 elements's attributes. + # + # The body of the element is the string returned by the no-argument + # block passed in. + # + # a("http://www.example.com") { "Example" } + # # => "Example" + # + # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" } + # # => "Example" + # + def a(href = "") # :yield: attributes = if href.kind_of?(String) { "HREF" => href } else @@ -1119,13 +1337,16 @@ convert string charset, and set language to "ja". end end - -=begin -=== BASE ELEMENT - base("url") - # = base({ "HREF" => "url" }) -=end - def base(href = "") + # 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") + # # => "" + def base(href = "") # :yield: attributes = if href.kind_of?(String) { "HREF" => href } else @@ -1138,13 +1359,17 @@ convert string charset, and set language to "ja". end end - -=begin -=== BLOCKQUOTE ELEMENT - blockquote("url"){ "string" } - # = blockquote({ "CITE" => "url" }){ "string" } -=end - def blockquote(cite = nil) + # 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!" } + # #=> "
Foo!
+ def blockquote(cite = nil) # :yield: attributes = if cite.kind_of?(String) { "CITE" => cite } else @@ -1158,12 +1383,17 @@ convert string charset, and set language to "ja". end -=begin -=== CAPTION ELEMENT - caption("align"){ "string" } - # = caption({ "ALIGN" => "align" }){ "string" } -=end - def caption(align = nil) + # 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" } + # # => Capital Cities + def caption(align = nil) # :yield: attributes = if align.kind_of?(String) { "ALIGN" => align } else @@ -1177,17 +1407,22 @@ convert string charset, and set language to "ja". end -=begin -=== CHECKBOX - checkbox("name") - # = checkbox({ "NAME" => "name" }) - - checkbox("name", "value") - # = checkbox({ "NAME" => "name", "VALUE" => "value" }) - - checkbox("name", "value", true) - # = checkbox({ "NAME" => "name", "VALUE" => "value", "CHECKED" => true }) -=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, @@ -1199,33 +1434,49 @@ convert string charset, and set language to "ja". input(attributes) end - -=begin -=== CHECKBOX_GROUP - checkbox_group("name", "foo", "bar", "baz") - # foo - # bar - # baz - - checkbox_group("name", ["foo"], ["bar", true], "baz") - # foo - # bar - # baz - - checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") - # Foo - # Bar - # 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"] }) -=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") + # # foo + # # bar + # # baz + # + # checkbox_group("name", ["foo"], ["bar", true], "baz") + # # foo + # # bar + # # baz + # + # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") + # # Foo + # # Bar + # # 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"] @@ -1247,20 +1498,27 @@ convert string charset, and set language to "ja". end -=begin -=== FILE_FIELD - file_field("name") - # - - file_field("name", 40) - # - - file_field("name", 40, 100) - # - - file_field({ "NAME" => "name", "SIZE" => 40 }) - # -=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") + # # + # + # file_field("name", 40) + # # + # + # file_field("name", 40, 100) + # # + # + # file_field("NAME" => "name", "SIZE" => 40) + # # def file_field(name = "", size = 20, maxlength = nil) attributes = if name.kind_of?(String) { "TYPE" => "file", "NAME" => name, @@ -1274,22 +1532,27 @@ convert string charset, and set language to "ja". end -=begin -=== FORM ELEMENT - form{ "string" } - #
string
- - form("get"){ "string" } - #
string
- - form("get", "url"){ "string" } - #
string
- - form({"METHOD" => "post", "ENCTYPE" => "enctype"}){ "string" } - #
string
- -The hash keys are case sensitive. Ask the samples. -=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" } + # #
string
+ # + # form("get") { "string" } + # #
string
+ # + # form("get", "url") { "string" } + # #
string
+ # + # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" } + # #
string
def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded") attributes = if method.kind_of?(String) { "METHOD" => method, "ACTION" => action, @@ -1321,17 +1584,21 @@ The hash keys are case sensitive. Ask the samples. super(attributes){body} end -=begin -=== HIDDEN FIELD - hidden("name") - # - - hidden("name", "value") - # - - hidden({ "NAME" => "name", "VALUE" => "reset", "ID" => "foo" }) - # -=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") + # # + # + # hidden("name", "value") + # # + # + # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo") + # # def hidden(name = "", value = nil) attributes = if name.kind_of?(String) { "TYPE" => "hidden", "NAME" => name, "VALUE" => value } @@ -1342,43 +1609,49 @@ The hash keys are case sensitive. Ask the samples. input(attributes) end - -=begin -=== HTML ELEMENT - - html{ "string" } - # string - - html({ "LANG" => "ja" }){ "string" } - # string - - html({ "DOCTYPE" => false }){ "string" } - # string - - html({ "DOCTYPE" => '' }){ "string" } - # string - - html({ "PRETTY" => " " }){ "" } - # - # - # - # - # - - html({ "PRETTY" => "\t" }){ "" } - # - # - # - # - # - - html("PRETTY"){ "" } - # = html({ "PRETTY" => " " }){ "" } - - html(if $VERBOSE then "PRETTY" end){ "HTML string" } - -=end - def html(attributes = {}) + # Generate a top-level HTML element as a string. + # + # The attributes of the element are specified as a hash. The + # psuedo-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 psuedo-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" } + # # string + # + # html("LANG" => "ja") { "string" } + # # string + # + # html("DOCTYPE" => false) { "string" } + # # string + # + # html("DOCTYPE" => '') { "string" } + # # string + # + # html("PRETTY" => " ") { "" } + # # + # # + # # + # # + # # + # + # html("PRETTY" => "\t") { "" } + # # + # # + # # + # # + # # + # + # html("PRETTY") { "" } + # # = html("PRETTY" => " ") { "" } + # + # html(if $VERBOSE then "PRETTY" end) { "HTML string" } + # + def html(attributes = {}) # :yield: if nil == attributes attributes = {} elsif "PRETTY" == attributes @@ -1412,18 +1685,21 @@ The hash keys are case sensitive. Ask the samples. end - -=begin -=== IMAGE_BUTTON - image_button("url") - # - - image_button("url", "name", "string") - # - - image_button({ "SRC" => "url", "ATL" => "strng" }) - # -=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") + # # + # + # image_button("url", "name", "string") + # # + # + # image_button("SRC" => "url", "ATL" => "strng") + # # def image_button(src = "", name = nil, alt = nil) attributes = if src.kind_of?(String) { "TYPE" => "image", "SRC" => src, "NAME" => name, @@ -1437,14 +1713,19 @@ The hash keys are case sensitive. Ask the samples. end -=begin -=== IMG ELEMENT - img("src", "alt", 100, 50) - # alt - - img({ "SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50 }) - # alt -=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) + # # alt + # + # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50) + # # alt def img(src = "", alt = "", width = nil, height = nil) attributes = if src.kind_of?(String) { "SRC" => src, "ALT" => alt } @@ -1457,14 +1738,20 @@ The hash keys are case sensitive. Ask the samples. end -=begin -=== MULTIPART FORM - multipart_form{ "string" } - #
string
- - multipart_form("url"){ "string" } - #
string
-=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" } + # #
string
+ # + # multipart_form("url") { "string" } + # #
string
def multipart_form(action = nil, enctype = "multipart/form-data") attributes = if action == nil { "METHOD" => "post", "ENCTYPE" => enctype } @@ -1488,20 +1775,25 @@ The hash keys are case sensitive. Ask the samples. end -=begin -=== PASSWORD_FIELD - password_field("name") - # - - password_field("name", "value") - # - - password_field("password", "value", 80, 200) - # - - password_field({ "NAME" => "name", "VALUE" => "value" }) - # -=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") + # # + # + # password_field("name", "value") + # # + # + # password_field("password", "value", 80, 200) + # # + # + # password_field("NAME" => "name", "VALUE" => "value") + # # def password_field(name = "", value = nil, size = 40, maxlength = nil) attributes = if name.kind_of?(String) { "TYPE" => "password", "NAME" => name, @@ -1514,38 +1806,49 @@ The hash keys are case sensitive. Ask the samples. input(attributes) end - -=begin -=== POPUP_MENU - popup_menu("name", "foo", "bar", "baz") - # - - popup_menu("name", ["foo"], ["bar", true], "baz") - # - - popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz") - # - - popup_menu({"NAME" => "name", "SIZE" => 2, "MULTIPLE" => true, - "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"] }) - # -=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") + # # + # + # popup_menu("name", ["foo"], ["bar", true], "baz") + # # + # + # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz") + # # + # + # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true, + # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) + # # def popup_menu(name = "", *values) if name.kind_of?(Hash) @@ -1579,18 +1882,22 @@ The hash keys are case sensitive. Ask the samples. end - -=begin -=== RADIO_BUTTON - radio_button("name", "value") - # - - radio_button("name", "value", true) - # - - radio_button({ "NAME" => "name", "VALUE" => "value", "ID" => "foo" }) - # -=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") + # # + # + # radio_button("name", "value", true) + # # + # + # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo") + # # def radio_button(name = "", value = nil, checked = nil) attributes = if name.kind_of?(String) { "TYPE" => "radio", "NAME" => name, @@ -1602,33 +1909,34 @@ The hash keys are case sensitive. Ask the samples. input(attributes) end - -=begin -=== RADIO_GROUP - radio_group("name", "foo", "bar", "baz") - # foo - # bar - # baz - - radio_group("name", ["foo"], ["bar", true], "baz") - # foo - # bar - # baz - - radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") - # Foo - # Bar - # 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"] }) -=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") + # # foo + # # bar + # # baz + # + # radio_group("name", ["foo"], ["bar", true], "baz") + # # foo + # # bar + # # baz + # + # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") + # # Foo + # # Bar + # # 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"] @@ -1649,18 +1957,21 @@ The hash keys are case sensitive. Ask the samples. }.to_s end - -=begin -=== RESET BUTTON - reset - # - - reset("reset") - # - - reset({ "VALUE" => "reset", "ID" => "foo" }) - # -=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 + # # + # + # reset("reset") + # # + # + # 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 } @@ -1671,34 +1982,26 @@ The hash keys are case sensitive. Ask the samples. input(attributes) end - -=begin -=== SCROLLING_LIST - scrolling_list({"NAME" => "name", "SIZE" => 2, "MULTIPLE" => true, - "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"] }) - # -=end alias scrolling_list popup_menu - -=begin -=== SUBMIT BUTTON - submit - # - - submit("ok") - # - - submit("ok", "button1") - # - - submit({ "VALUE" => "ok", "NAME" => "button1", "ID" => "foo" }) - # -=end + # 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 + # # + # + # submit("ok") + # # + # + # submit("ok", "button1") + # # + # + # 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 } @@ -1709,24 +2012,28 @@ The hash keys are case sensitive. Ask the samples. input(attributes) end - -=begin -=== TEXT_FIELD - text_field("name") - # - - text_field("name", "value") - # - - text_field("name", "value", 80) - # - - text_field("name", "value", 80, 200) - # - - text_field({ "NAME" => "name", "VALUE" => "value" }) - # -=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") + # # + # + # text_field("name", "value") + # # + # + # text_field("name", "value", 80) + # # + # + # text_field("name", "value", 80, 200) + # # + # + # text_field("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, @@ -1739,16 +2046,21 @@ The hash keys are case sensitive. Ask the samples. input(attributes) end - -=begin -=== TEXTAREA ELEMENT - textarea("name") - # = textarea({ "NAME" => "name", "COLS" => 70, "ROWS" => 10 }) - - textarea("name", 40, 5) - # = textarea({ "NAME" => "name", "COLS" => 40, "ROWS" => 5 }) -=end - def textarea(name = "", cols = 70, rows = 10) + # 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 } @@ -1765,12 +2077,15 @@ The hash keys are case sensitive. Ask the samples. end # HtmlExtension - module Html3 + # Mixin module for HTML version 3 generation methods. + module Html3 # :nodoc: + # The DOCTYPE declaration for this version of HTML def doctype %|| end + # Initialise the HTML generation methods for this version. def element_init extend TagMaker methods = "" @@ -1812,12 +2127,15 @@ The hash keys are case sensitive. Ask the samples. end # Html3 - module Html4 + # Mixin module for HTML version 4 generation methods. + module Html4 # :nodoc: + # The DOCTYPE declaration for this version of HTML def doctype %|| end + # Initialise the HTML generation methods for this version. def element_init extend TagMaker methods = "" @@ -1858,12 +2176,15 @@ The hash keys are case sensitive. Ask the samples. end # Html4 - module Html4Tr + # Mixin module for HTML version 4 transitional generation methods. + module Html4Tr # :nodoc: + # The DOCTYPE declaration for this version of HTML def doctype %|| end + # Initialise the HTML generation methods for this version. def element_init extend TagMaker methods = "" @@ -1906,12 +2227,15 @@ The hash keys are case sensitive. Ask the samples. end # Html4Tr - module Html4Fr + # Mixin module for generating HTML version 4 with framesets. + module Html4Fr # :nodoc: + # The DOCTYPE declaration for this version of HTML def doctype %|| end + # Initialise the HTML generation methods for this version. def element_init methods = "" # - - @@ -1937,6 +2261,24 @@ The hash keys are case sensitive. Ask the samples. end # Html4Fr + # Creates a new CGI instance. + # + # +type+ specifies which version of HTML to load the HTML generation + # methods for. The following versions of HTML are supported: + # + # html3:: HTML 3.x + # html4:: HTML 4.0 + # html4Tr:: HTML 4.0 Transitional + # html4Fr:: HTML 4.0 with Framesets + # + # If not specified, no HTML generation methods will be loaded. + # + # 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(type = "query") if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE") Apache.request.setup_cgi_env @@ -1989,18 +2331,7 @@ The hash keys are case sensitive. Ask the samples. element_init() extend HtmlExtension end - end -end - - -=begin - -== HISTORY - -delete. see cvs log. - -=end +end # class CGI -# vi:set tw=0: -- cgit v1.2.3