1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/lib/cgi.rb
matz a9e9697994 19991104
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@557 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1999-11-04 08:39:57 +00:00

1949 lines
49 KiB
Ruby

=begin
$Date$
== CGI SUPPORT LIBRARY
CGI.rb
Version 1.00
Copyright (C) 1999 Network Applied Communication Laboratory, Inc.
Wakou Aoyama <wakou@fsinet.or.jp>
== EXAMPLE
=== GET FORM VALUES
require "cgi"
cgi = CGI.new
values = cgi['field_name'] # <== array of '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.key?('field_name')
cgi.include?('field_name')
=== 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
values = cgi['field_name'] # <== array of 'field_name'
values[0].read # <== body of values[0]
values[0].local_path # <== path to local file of values[0]
values[0].original_filename # <== original filename of values[0]
values[0].content_type # <== content_type of values[0]
and values[0] has Tempfile class methods.
(Tempfile class object has File 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 }){}
cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
require "cgi"
cgi = CGI.new
cgi.cookies['name'].expires = Time.now + 30
cgi.out({ "cookie" => cgi.cookies['name'] }){}
and see MAKE COOKIE OBJECT.
=== GET ENVIRONMENT VALUE
require "CGI"
cgi = CGI.new
value = cgi.auth_type
# ENV["AUTH_TYPE"]
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 $>
require "cgi"
cgi = CGI.new("html3") # add HTML generation methods
cgi.out{
cgi.html{
cgi.head{ cgi.title{"TITLE"} } +
cgi.body{
cgi.form{
cgi.textarea("get_text") +
cgi.br +
cgi.submit
} +
cgi.pre{
CGI::escapeHTML(
"params: " + cgi.params.inspect + "\n" +
"cookies: " + cgi.cookies.inspect + "\n" +
ENV.collect{|key, value|
key + " --> " + value + "\n"
}.to_s
)
}
}
}
}
# 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
class CGI
CR = "\015"
LF = "\012"
EOL = CR + LF
v = $-v
$-v = false
VERSION = "1.00"
RELEASE_DATE = "$Date$"
$-v = v
NEEDS_BINMODE = true if /WIN/ni === PLATFORM
PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
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 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"
}
RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
def env_table
ENV
end
def stdinput
$stdin
end
def stdoutput
$>
end
private :env_table, :stdinput, :stdoutput
=begin
== METHODS
=end
=begin
=== ESCAPE URL ENCODE
url_encoded_string = CGI::escape("string")
=end
def CGI::escape(string)
str = string.dup
str.gsub!(/[^a-zA-Z0-9_.-]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
str
end
=begin
=== UNESCAPE URL ENCODED
string = CGI::unescape("url encoded string")
=end
def CGI::unescape(string)
str = string.dup
str.gsub!(/\+/n, ' ')
str.gsub!(/%([0-9a-fA-F]{2})/n){ [$1.hex].pack("c") }
str
end
=begin
=== ESCAPE HTML &"<>
CGI::escapeHTML("string")
=end
def CGI::escapeHTML(string)
str = string.dup
str.gsub!(/&/n, '&amp;')
str.gsub!(/\"/n, '&quot;')
str.gsub!(/>/n, '&gt;')
str.gsub!(/</n, '&lt;')
str
end
=begin
=== UNESCAPE HTML
CGI::unescapeHTML("HTML escaped string")
=end
def CGI::unescapeHTML(string)
str = string.dup
str.gsub!(/&(.*?);/n){
match = $1.dup
case match
when /\Aamp\z/ni then '&'
when /\Aquot\z/ni then '"'
when /\Agt\z/ni then '>'
when /\Alt\z/ni then '<'
when /\A#(\d+)\z/n then Integer($1).chr
when /\A#x([0-9a-f]+)\z/ni then $1.hex.chr
end
}
str
end
=begin
=== ESCAPE ELEMENT
print CGI::escapeElement("<BR><A HREF="url"></A>", "A", "IMG")
# "<BR>&lt;A HREF="url"&gt;&lt;/A&gt"
print CGI::escapeElement("<BR><A HREF="url"></A>", ["A", "IMG"])
# "<BR>&lt;A HREF="url"&gt;&lt;/A&gt"
=end
def CGI::escapeElement(string, *element)
str = string.dup
str.gsub!(/<\/?(?:#{element.join("|")})(?!\w)(?:.|\n)*?>/ni){
CGI::escapeHTML($&)
}
str
end
=begin
=== UNESCAPE ELEMENT
print CGI::unescapeElement(
CGI::escapeHTML("<BR><A HREF="url"></A>"), "A", "IMG")
# "&lt;BR&gt;<A HREF="url"></A>"
print CGI::unescapeElement(
CGI::escapeHTML("<BR><A HREF="url"></A>"), ["A", "IMG"])
# "&lt;BR&gt;<A HREF="url"></A>"
=end
def CGI::unescapeElement(string, *element)
str = string.dup
str.gsub!(/&lt;\/?(?:#{element.join("|")})(?!\w)(?:.|\n)*?&gt;/ni){
CGI::unescapeHTML($&)
}
str
end
=begin
=== MAKE RFC1123 DATE STRING
CGI::rfc1123_date(Time.now)
# Sut, 1 Jan 2000 00:00:00 GMT
=end
def CGI::rfc1123_date(time)
t = time.clone.gmtime
return format("%s, %.2d %s %d %.2d:%.2d:%.2d GMT",
RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
t.hour, t.min, t.sec)
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
def header(options = "text/html")
buf = ""
if options.kind_of?(String)
options = { "type" => options }
end
unless options.key?("type")
options["type"] = "text/html"
end
if options.key?("charset")
options["type"].concat( "; charset=" )
options["type"].concat( options.delete("charset") )
end
if options.delete("nph") or (/IIS/n === env_table['SERVER_SOFTWARE'])
buf.concat( (env_table["SERVER_PROTOCOL"] or "HTTP/1.0") + " " )
buf.concat( (HTTP_STATUS[options["status"]] or
options["status"] or
"200 OK"
) + EOL
)
buf.concat(
"Date: " + CGI::rfc1123_date(Time.now) + EOL
)
unless options.key?("server")
options["server"] = (env_table['SERVER_SOFTWARE'] or "")
end
unless options.key?("connection")
options["connection"] = "close"
end
end
options.delete("status")
if options.key?("server")
buf.concat("Server: " + options.delete("server") + EOL)
end
if options.key?("connection")
buf.concat("Connection: " + options.delete("connection") + EOL)
end
buf.concat("Content-Type: " + options.delete("type") + EOL)
if options.key?("length")
buf.concat("Content-Length: " + options.delete("length").to_s + EOL)
end
if options.key?("language")
buf.concat("Content-Language: " + options.delete("language") + EOL)
end
if options.key?("expires")
buf.concat("Expires: " + CGI::rfc1123_date( options.delete("expires") ) + EOL)
end
if options.key?("cookie")
if options["cookie"].kind_of?(String) or
options["cookie"].kind_of?(Cookie)
buf.concat("Set-Cookie: " + options.delete("cookie").to_s + EOL)
elsif options["cookie"].kind_of?(Array)
options.delete("cookie").each{|cookie|
buf.concat("Set-Cookie: " + cookie.to_s + EOL)
}
elsif options["cookie"].kind_of?(Hash)
options.delete("cookie").each_value{|cookie|
buf.concat("Set-Cookie: " + cookie.to_s + EOL)
}
end
end
if @output_cookies
for cookie in @output_cookies
buf.concat("Set-Cookie: " + cookie.to_s + EOL)
end
end
options.each{|key, value|
buf.concat(key + ": " + value + EOL)
}
if env_table['MOD_RUBY']
buf.scan(/([^:]+): (.+)#{EOL}/n){
Apache::request[$1] = $2
}
Apache::request.send_http_header
''
else
buf + EOL
end
end # header()
=begin
=== PRINT HTTP HEADER AND STRING TO $>
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 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")
options = { "type" => options } if options.kind_of?(String)
content = yield
if options.key?("charset")
require "nkf"
case options["charset"]
when /iso-2022-jp/ni
content = NKF::nkf('-j', content)
options["language"] = "ja" unless options.key?("language")
when /euc-jp/ni
content = NKF::nkf('-e', content)
options["language"] = "ja" unless options.key?("language")
when /shift_jis/ni
content = NKF::nkf('-s', content)
options["language"] = "ja" unless options.key?("language")
end
end
options["length"] = content.length.to_s
output = stdoutput
output.binmode if defined? output.binmode
output.print header(options)
output.print content
end
=begin
=== PRINT
cgi = CGI.new
cgi.print # default: cgi.print == $>.print
=end
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 Cookie < SimpleDelegator
def initialize(name = "", *value)
options = if name.kind_of?(String)
{ "name" => name, "value" => value }
else
name
end
unless options.key?("name")
raise ArgumentError, "`name' required"
end
@name = options["name"]
@value = Array(options["value"])
@path = options["path"]
@domain = options["domain"]
@expires = options["expires"]
@secure = options["secure"] == true ? true : false
super(@value)
end
attr_accessor("name", "value", "path", "domain", "expires")
attr_reader("secure")
def secure=(val)
@secure = val if val == true or val == false
@secure
end
def to_s
buf = ""
buf.concat(@name + '=')
if @value.kind_of?(String)
buf.concat CGI::escape(@value)
else
buf.concat(@value.filter{|v| CGI::escape(v) }.join("&"))
end
if @domain
buf.concat('; domain=' + @domain)
end
if @path
buf.concat('; path=' + @path)
end
if @expires
buf.concat('; expires=' + CGI::rfc1123_date(@expires))
end
if @secure == true
buf.concat('; secure')
end
buf
end
end # class Cookie
=begin
=== PARSE RAW COOKIE STRING
cookies = CGI::Cookie::parse("raw_cookie_string")
# { "name1" => cookie1, "name2" => cookie2, ... }
=end
def Cookie::parse(raw_cookie)
cookies = Hash.new([])
raw_cookie.split('; ').each do |pairs|
name, values = pairs.split('=',2)
name = CGI::unescape(name)
values = values.split('&').filter{|v| CGI::unescape(v) }
if cookies.key?(name)
cookies[name].value.push(*values)
else
cookies[name] = Cookie::new({ "name" => name, "value" => values })
end
end
cookies
end
=begin
=== PARSE QUERY STRING
params = CGI::parse("query_string")
# {"name1" => ["value1", "value2", ...],
# "name2" => ["value1", "value2", ...], ... }
=end
def CGI::parse(query)
params = Hash.new([])
query.split(/[&;]/n).each do |pairs|
key, value = pairs.split('=',2).filter{|v| CGI::unescape(v) }
if params.key?(key)
params[key].push(value)
else
params[key] = [value]
end
end
params
end
module QueryExtension
%w[ CONTENT_LENGTH SERVER_PORT ].
each{|env|
eval( <<-END )
def #{env.sub(/^HTTP_/n, '').downcase}
env_table["#{env}"] && Integer(env_table["#{env}"])
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{|env|
eval( <<-END )
def #{env.sub(/^HTTP_/n, '').downcase}
env_table["#{env}"]
end
END
}
def raw_cookie
env_table["HTTP_COOKIE"]
end
def raw_cookie2
env_table["HTTP_COOKIE2"]
end
attr_accessor("cookies")
attr("params")
def params=(hash)
@params.clear
@params.update(hash)
end
def read_multipart(boundary, content_length)
params = Hash.new([])
boundary = "--" + boundary
buf = ""
bufsize = 10 * 1024
# start multipart/form-data
stdinput.binmode
content_length -= stdinput.read((boundary + EOL).size).size
require "tempfile.rb"
until -1 == content_length
head = nil
body = Tempfile.new("CGI")
body.binmode
until head and (/#{boundary}(?:#{EOL}|--)/n === buf)
if (not head) and (/#{EOL}#{EOL}/n === buf)
buf.sub!(/\A((?:.|\n)*?#{EOL})#{EOL}/n){
head = $1.dup
""
}
next
end
if head and ( (EOL + boundary + EOL).size < buf.size )
body.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
end
c = if bufsize < content_length
stdinput.read(bufsize) or ''
else
stdinput.read(content_length) or ''
end
buf.concat c
content_length -= c.size
end
buf.sub!(/\A((?:.|\n)*?)(?:#{EOL})?#{boundary}(#{EOL}|--)/n){
body.print $1
if "--" == $2
content_length = -1
end
""
}
body.rewind
eval <<-END
def body.local_path
#{body.path.dump}
end
END
/Content-Disposition:.* filename="?([^\";]*)"?/ni === head
eval <<-END
def body.original_filename
#{
filename = ($1 or "").dup
if (/Mac/ni === env_table['HTTP_USER_AGENT']) and
(/Mozilla/ni === env_table['HTTP_USER_AGENT']) and
(not /MSIE/ni === env_table['HTTP_USER_AGENT'])
CGI::unescape(filename)
else
filename
end.dump
}
end
END
/Content-Type: (.*)/ni === head
eval <<-END
def body.content_type
#{($1 or "").dump}
end
END
/Content-Disposition:.* name="?([^\";]*)"?/ni === head
name = $1.dup
if params.key?(name)
params[name].push(body)
else
params[name] = [body]
end
end
params
end # read_multipart
private :read_multipart
# offline mode. read name=value pairs on standard input.
def read_from_cmdline
require "shellwords.rb"
unless ARGV.empty?
str = ARGV.join(' ')
else
if STDIN.tty?
STDERR.print(
%|(offline mode: enter name=value pairs on standard input)\n|
)
end
str = readlines.join(' ')
str.gsub!(/\n/n, '')
end
str.gsub!(/\\=/n, '%3D')
str.gsub!(/\\&/n, '%26')
words = Shellwords.shellwords(str)
if words.find{|x| /=/n === x }
words.join('&')
else
words.join('+')
end
end
private :read_from_cmdline
def initialize_query()
if ("POST" == env_table['REQUEST_METHOD']) and
(%r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n ===
env_table['CONTENT_TYPE'])
boundary = $1.dup
@params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
else
@params = CGI::parse(
case env_table['REQUEST_METHOD']
when "GET", "HEAD"
if env_table['MOD_RUBY']
Apache::request.args or ""
else
env_table['QUERY_STRING'] or ""
end
when "POST"
stdinput.binmode
stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
else
read_from_cmdline
end
)
end
@cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or
env_table['COOKIE'] or ""))
end
private :initialize_query
def [](*args)
@params[*args]
end
def keys(*args)
@params.keys(*args)
end
def has_key?(*args)
@params.has_key?(*args)
end
alias key? has_key?
alias include? has_key?
end # QueryExtension
=begin
=== HTML PRETTY FORMAT
print CGI::pretty("<HTML><BODY></BODY></HTML>")
# <HTML>
# <BODY>
# </BODY>
# </HTML>
print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
# <HTML>
# <BODY>
# </BODY>
# </HTML>
=end
def CGI::pretty_shift(string, shift = " ")
shift = " " if true == shift
str = string.dup
str.gsub!(/\n(?!\z)/n, "\n" + shift)
str
end
def CGI::pretty_nest(string, shift = " ")
str = string.dup
str.gsub!(/(<(\w+).*?>)((?:.|\n)*?)(<\/\2>)/n){
$1 + CGI::pretty_shift(CGI::pretty_nest($3, shift), shift) + $4
}
str
end
def CGI::pretty(string, shift = " ")
str = string.dup
str.gsub!(/<(?:.|\n)*?>/n, "\n\\0")
str.gsub!(/<(?:.|\n)*?>(?!\n)/n, "\\0\n")
CGI::pretty_nest(str, shift)
end
=begin
== HTML ELEMENTS
cgi = CGI.new("html3") # add HTML generation methods
cgi.element
cgi.element{ "string" }
cgi.element({ "ATTRILUTE1" => "value1", "ATTRIBUTE2" => "value2" })
cgi.element({ "ATTRILUTE1" => "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
# - -
def nn_element_def(element)
<<-END.gsub(/element\.downcase/n, element.downcase).gsub(/element\.upcase/n, element.upcase)
"<element.upcase" + attributes.collect{|name, value|
" " + CGI::escapeHTML(name) +
if true == value
""
else
'="' + CGI::escapeHTML(value) + '"'
end
}.to_s + ">" +
if iterator?
yield.to_s
else
""
end +
"</element.upcase>"
END
end
# - O EMPTY
def nOE_element_def(element)
<<-END.gsub(/element\.downcase/n, element.downcase).gsub(/element\.upcase/n, element.upcase)
"<element.upcase" + attributes.collect{|name, value|
" " + CGI::escapeHTML(name) +
if true == value
""
else
'="' + CGI::escapeHTML(value) + '"'
end
}.to_s + ">"
END
end
# O O or - O
def nO_element_def(element)
<<-END.gsub(/element\.downcase/n, element.downcase).gsub(/element\.upcase/n, element.upcase)
"<element.upcase" + attributes.collect{|name, value|
" " + CGI::escapeHTML(name) +
if true == value
""
else
'="' + CGI::escapeHTML(value) + '"'
end
}.to_s + ">" +
if iterator?
yield.to_s + "</element.upcase>"
else
""
end
END
end
end # TagMaker
module HtmlExtension
extend TagMaker
=begin
=== A ELEMENT
a("url")
# = a({ "HREF" => "url" })
=end
def a(href = "")
attributes = if href.kind_of?(String)
{ "HREF" => href }
else
href
end
if iterator?
super(attributes){ yield }
else
super(attributes)
end
end
=begin
=== BASE ELEMENT
base("url")
# = base({ "HREF" => "url" })
=end
def base(href = "")
attributes = if href.kind_of?(String)
{ "HREF" => href }
else
href
end
if iterator?
super(attributes){ yield }
else
super(attributes)
end
end
=begin
=== BLOCKQUOTE ELEMENT
blockquote("url"){ "string" }
# = blockquote({ "CITE" => "url" }){ "string" }
=end
def blockquote(cite = nil)
attributes = if cite.kind_of?(String)
{ "CITE" => cite }
else
cite or ""
end
if iterator?
super(attributes){ yield }
else
super(attributes)
end
end
=begin
=== CAPTION ELEMENT
caption("align"){ "string" }
# = caption({ "ALIGN" => "align" }){ "string" }
=end
def caption(align = nil)
attributes = if align.kind_of?(String)
{ "ALIGN" => align }
else
align or ""
end
if iterator?
super(attributes){ yield }
else
super(attributes)
end
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
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
=begin
=== CHECKBOX_GROUP
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" SELECTED 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" SELECTED 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"] })
=end
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[value.size - 1] == true
checkbox(name, value[0], true) +
value[value.size - 2]
else
checkbox(name, value[0]) +
value[value.size - 1]
end
end
}.to_s
end
=begin
=== FILE_FIELD
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">
=end
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
=begin
=== FORM ELEMENT
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>
=end
def form(method = "post", action = nil, enctype = "application/x-www-form-urlencoded")
attributes = if method.kind_of?(String)
{ "METHOD" => method, "ACTION" => action,
"ENCTYPE" => enctype }
else
unless method.key?("METHOD")
method["METHOD"] = method
end
unless method.key?("ENCTYPE")
method["ENCTYPE"] = enctype
end
method
end
if iterator?
body = yield
else
body = ""
end
if @output_hidden
hidden = @output_hidden.collect{|k,v|
"<INPUT TYPE=HIDDEN NAME=\"#{k}\" VALUE=\"#{v}\">"
}.to_s
body.concat hidden
end
super(attributes){body}
end
=begin
=== HIDDEN FIELD
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">
=end
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
=begin
=== HTML ELEMENT
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" }
=end
def html(attributes = {})
if nil == attributes
attributes = {}
elsif "PRETTY" == attributes
attributes = { "PRETTY" => true }
end
pretty = attributes.delete("PRETTY")
buf = ""
if attributes.key?("DOCTYPE")
if attributes["DOCTYPE"]
buf.concat( attributes.delete("DOCTYPE") )
else
attributes.delete("DOCTYPE")
end
else
buf.concat( doctype )
end
if iterator?
buf.concat( super(attributes){ yield } )
else
buf.concat( super(attributes) )
end
if pretty
CGI::pretty(buf, pretty)
else
buf
end
end
=begin
=== IMAGE_BUTTON
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", "ATL" => "strng" })
# <INPUT TYPE="image" SRC="url" ALT="string">
=end
def image_button(src = "", name = nil, alt = nil)
attributes = if src.kind_of?(String)
{ "TYPE" => "image", "SRC" => src, "NAME" => name,
"ALT" => alt }
else
name["TYPE"] = "image"
name
end
input(attributes)
end
=begin
=== IMG ELEMENT
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">
=end
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
=begin
=== MULTIPART FORM
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>
=end
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.key?("METHOD")
action["METHOD"] = "post"
end
unless action.key?("ENCTYPE")
action["ENCTYPE"] = enctype
end
action
end
if iterator?
form(attributes){ yield }
else
form(attributes)
end
end
=begin
=== PASSWORD_FIELD
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">
=end
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
=begin
=== POPUP_MENU
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>
=end
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
}.to_s
}
end
=begin
=== RADIO_BUTTON
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">
=end
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
=begin
=== RADIO_GROUP
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" SELECTED 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" SELECTED 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"] })
=end
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[value.size - 1] == true
radio_button(name, value[0], true) +
value[value.size - 2]
else
radio_button(name, value[0]) +
value[value.size - 1]
end
end
}.to_s
end
=begin
=== RESET BUTTON
reset
# <INPUT TYPE="reset">
reset("reset")
# <INPUT TYPE="reset" VALUE="reset">
reset({ "VALUE" => "reset", "ID" => "foo" })
# <INPUT TYPE="reset" VALUE="reset" ID="foo">
=end
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
=begin
=== SCROLLING_LIST
scrolling_list({"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>
=end
alias scrolling_list popup_menu
=begin
=== SUBMIT BUTTON
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">
=end
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
=begin
=== TEXT_FIELD
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">
=end
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
=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)
attributes = if name.kind_of?(String)
{ "NAME" => name, "COLS" => cols.to_s,
"ROWS" => rows.to_s }
else
name
end
if iterator?
super(attributes){ yield }
else
super(attributes)
end
end
end # HtmlExtension
module Html3
extend TagMaker
def doctype
%|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">|
end
# - -
%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 ].
each{|element|
eval( <<-BEGIN + nn_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
# - O EMPTY
%w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT ISINDEX META ].
each{|element|
eval( <<-BEGIN + nOE_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
# O O or - O
%w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr th td ].
each{|element|
eval( <<-BEGIN + nO_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
end # Html3
module Html4
extend TagMaker
def doctype
%|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">|
end
# - -
%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 ].
each{|element|
eval( <<-BEGIN + nn_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
# - O EMPTY
%w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ].
each{|element|
eval( <<-BEGIN + nOE_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
# O O or - O
%w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY COLGROUP TR TH TD HEAD].
each{|element|
eval( <<-BEGIN + nO_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
end # Html4
module Html4Tr
extend TagMaker
def doctype
%|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">|
end
# - -
%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 ].
each{|element|
eval( <<-BEGIN + nn_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
# - O EMPTY
%w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT COL ISINDEX META ].
each{|element|
eval( <<-BEGIN + nOE_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
# O O or - O
%w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY COLGROUP TR TH TD HEAD ].
each{|element|
eval( <<-BEGIN + nO_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
end # Html4Tr
module Html4Fr
include Html4Tr
extend TagMaker
def doctype
%|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">|
end
# - -
%w[ FRAMESET ].
each{|element|
eval( <<-BEGIN + nn_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
# - O EMPTY
%w[ FRAME ].
each{|element|
eval( <<-BEGIN + nOE_element_def(element) + <<-END )
def #{element.downcase}(attributes = {})
BEGIN
end
END
}
end # Html4Fr
def initialize(type = "query")
extend QueryExtension
initialize_query()
# @params, @cookies initialized in initialize_query
case type
when "html3"
extend Html3
extend HtmlExtension
when "html4"
extend Html4
extend HtmlExtension
when "html4Tr"
extend Html4Tr
extend HtmlExtension
when "html4Fr"
extend Html4Fr
extend HtmlExtension
end
end
end
=begin
== HISTRY
=== Version 1.00 - wakou
1999/09/13 23:00:58
- COUTION! name change. CGI.rb --> cgi.rb
- CGI#auth_type, CGI#content_length, CGI#content_type, ...
if not ENV included it, then return nil.
- CGI#content_length and CGI#server_port return Integer.
- if not CGI#params.include?('name'), then CGI#params['name'] return [].
- if not CGI#cookies.include?('name'), then CGI#cookies['name'] return [].
=== Version 0.41 - wakou
1999/08/05 18:04:59
- typo. thanks to MJ Ray <markj@altern.org>
HTTP_STATUS["NOT_INPLEMENTED"] --> HTTP_STATUS["NOT_IMPLEMENTED"]
=== Version 0.40 - wakou
1999/07/20 20:44:31
- COUTION! incompatible change.
sorry, but probably this change is last big incompatible change.
- CGI::print --> CGI#out
cgi = CGI.new
cgi.out{"string"} # old: CGI::print{"string"}
- CGI::cookie --> CGI::Cookie::new
cookie1 = CGI::Cookie::new # old: CGI::cookie
- CGI::header --> CGI#header
=== Version 0.30 - wakou
1999/06/29 06:50:21
- COUTION! incompatible change.
query = CGI.new
cookies = query.cookies # old: query.cookie
values = query.cookies[name] # old: query.cookie[name]
=== Version 0.24 - wakou
1999/06/21 21:05:57
- CGI::Cookie::parse() return { name => CGI::Cookie object } pairs.
=== Version 0.23 - wakou
1999/06/20 23:29:12
- modified a bit to clear module separation.
=== Version 0.22 - matz
Mon Jun 14 17:49:32 JST 1999
- Cookies are now CGI::Cookie objects.
- Cookie modeled after CGI::Cookie.pm.
=== Version 0.21 - matz
Fri Jun 11 11:19:11 JST 1999
- modified a bit to clear module separation.
=== Version 0.20 - wakou
1999/06/03 06:48:15
- support for multipart form.
=== Version 0.10 - wakou
1999/05/24 07:05:41
- first release.
=end