Bug #479 » cgi_backport_18.patch
lib/cgi.rb (作業コピー) | ||
---|---|---|
# url_encoded_string = CGI::escape("'Stop!' said Fred")
|
||
# # => "%27Stop%21%27+said+Fred"
|
||
def CGI::escape(string)
|
||
string.gsub(/([^ a-zA-Z0-9_.-]+)/) do
|
||
string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
|
||
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
|
||
end.tr(' ', '+')
|
||
end
|
||
... | ... | |
# # => "'Stop!' said Fred"
|
||
def CGI::unescape(string)
|
||
enc = string.encoding
|
||
string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
|
||
string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
|
||
[$1.delete('%')].pack('H*').force_encoding(enc)
|
||
end
|
||
end
|
||
TABLE_FOR_ESCAPE_HTML__ = {
|
||
'&' => '&',
|
||
'"' => '"',
|
||
'<' => '<',
|
||
'>' => '>',
|
||
}
|
||
# Escape special characters in HTML, namely &\"<>
|
||
# CGI::escapeHTML('Usage: foo "bar" <baz>')
|
||
# # => "Usage: foo "bar" <baz>"
|
||
def CGI::escapeHTML(string)
|
||
string.gsub(/[&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
|
||
string.gsub(/&/n, '&').gsub(/\"/n, '"').gsub(/>/n, '>').gsub(/</n, '<')
|
||
end
|
||
... | ... | |
# # => "Usage: foo \"bar\" <baz>"
|
||
def CGI::unescapeHTML(string)
|
||
enc = string.encoding
|
||
string.gsub(/&(amp|quot|gt|lt|\#[0-9]+|\#x[0-9A-Fa-f]+);/) do
|
||
string.gsub(/&(amp|quot|gt|lt|\#[0-9]+|\#x[0-9A-Fa-f]+);/n) do
|
||
match = $1.dup
|
||
case match
|
||
when 'amp' then '&'
|
||
when 'quot' then '"'
|
||
when 'gt' then '>'
|
||
when 'lt' then '<'
|
||
when /\A#0*(\d+)\z/ then
|
||
when /\A#0*(\d+)\z/n then
|
||
if Integer($1) < 256
|
||
Integer($1).chr.force_encoding(enc)
|
||
else
|
||
"&##{$1};"
|
||
if Integer($1) < 65536 and enc==Encoding::UTF_8
|
||
[Integer($1)].pack("U")
|
||
else
|
||
"&##{$1};"
|
||
end
|
||
end
|
||
when /\A#x([0-9a-f]+)\z/i then
|
||
when /\A#x([0-9a-f]+)\z/ni then
|
||
if $1.hex < 256
|
||
$1.hex.chr.force_encoding(enc)
|
||
else
|
||
"&#x#{$1};"
|
||
if $1.hex < 65536 and enc==Encoding::UTF_8
|
||
[$1.hex].pack("U")
|
||
else
|
||
"&#x#{$1};"
|
||
end
|
||
end
|
||
else
|
||
"&#{match};"
|
||
end
|
||
end
|
||
end
|
||
def CGI::escape_html(str)
|
||
escapeHTML(str)
|
||
end
|
||
def CGI::unescape_html(str)
|
||
unescapeHTML(str)
|
||
end
|
||
# Escape only the tags of certain HTML elements in +string+.
|
||
#
|
||
... | ... | |
def read_multipart(boundary, content_length)
|
||
params = Hash.new([])
|
||
boundary = "--" + boundary
|
||
quoted_boundary = Regexp.quote(boundary)
|
||
quoted_boundary = Regexp.quote(boundary,"n")
|
||
buf = ""
|
||
bufsize = 10 * 1024
|
||
boundary_end=""
|
||
... | ... | |
loop do
|
||
head = nil
|
||
body = MorphingBody.new
|
||
if 10240 < content_length
|
||
require "tempfile"
|
||
body = Tempfile.new("CGI")
|
||
else
|
||
begin
|
||
require "stringio"
|
||
body = StringIO.new
|
||
rescue LoadError
|
||
require "tempfile"
|
||
body = Tempfile.new("CGI")
|
||
end
|
||
end
|
||
body.binmode if defined? body.binmode
|
||
until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
|
||
if (not head) and /#{EOL}#{EOL}/n.match(buf)
|
||
... | ... | |
end
|
||
private :read_from_cmdline
|
||
# A wrapper class to use a StringIO object as the body and switch
|
||
# to a TempFile when the passed threshold is passed.
|
||
class MorphingBody
|
||
begin
|
||
require "stringio"
|
||
@@small_buffer = lambda{StringIO.new}
|
||
rescue LoadError
|
||
require "tempfile"
|
||
@@small_buffer = lambda{
|
||
n = Tempfile.new("CGI")
|
||
n.binmode
|
||
n
|
||
}
|
||
end
|
||
def initialize(morph_threshold = 10240)
|
||
@threshold = morph_threshold
|
||
@body = @@small_buffer.call
|
||
@cur_size = 0
|
||
@morph_check = true
|
||
end
|
||
def print(data)
|
||
if @morph_check && (@cur_size + data.bytesize > @threshold)
|
||
convert_body
|
||
end
|
||
@body.print data
|
||
end
|
||
def rewind
|
||
@body.rewind
|
||
end
|
||
def path
|
||
@body.path
|
||
end
|
||
# returns the true body object.
|
||
def extract
|
||
@body
|
||
end
|
||
private
|
||
def convert_body
|
||
new_body = TempFile.new("CGI")
|
||
new_body.binmode if defined? @body.binmode
|
||
new_body.binmode if defined? new_body.binmode
|
||
@body.rewind
|
||
new_body.print @body.read
|
||
@body = new_body
|
||
@morph_check = false
|
||
end
|
||
end
|
||
# Initialize the data from the query.
|
||
#
|
||
# Handles multipart forms (in particular, forms that involve file uploads).
|
||
... | ... | |
def multipart?
|
||
@multipart
|
||
end
|
||
module Value # :nodoc:
|
||
def set_params(params)
|
||
@params = params
|
||
end
|
||
def [](idx, *args)
|
||
if args.bytesize == 0
|
||
warn "#{caller(1)[0]}:CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key']"
|
||
@params[idx]
|
||
else
|
||
super[idx,*args]
|
||
end
|
||
end
|
||
def first
|
||
warn "#{caller(1)[0]}:CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key']"
|
||
self
|
||
end
|
||
alias last first
|
||
def to_a
|
||
@params || [self]
|
||
end
|
||
alias to_ary to_a # to be rhs of multiple assignment
|
||
end
|
||
# Get the value for the parameter with a given key.
|
||
#
|
||
# If the parameter has multiple values, only the first will be
|
||
... | ... | |
end
|
||
else
|
||
str = if value then value.dup else "" end
|
||
str.extend(Value)
|
||
str.set_params(params)
|
||
str
|
||
end
|
||
end
|
||
... | ... | |
Apache.request.setup_cgi_env
|
||
end
|
||
(class << self; self; end).class_eval do
|
||
const_set(:CGI_PARAMS, [1])
|
||
const_set(:CGI_COOKIES, [2])
|
||
end
|
||
extend QueryExtension
|
||
@multipart = false
|
||
initialize_query() # set @params, @cookies
|
||
if defined?(CGI_PARAMS)
|
||
warn "do not use CGI_PARAMS and CGI_COOKIES"
|
||
@params = CGI_PARAMS.dup
|
||
@cookies = CGI_COOKIES.dup
|
||
else
|
||
initialize_query() # set @params, @cookies
|
||
end
|
||
@output_cookies = nil
|
||
@output_hidden = nil
|
||