模組 CGI::QueryExtension
提供以下功能的 Mixin 模組
屬性
files[R]
取得上傳的檔案,格式為 name=>values 的雜湊
params[R]
取得參數,格式為 name=>values 的雜湊,其中 values 為 Array
。
公開實例方法
[](key) 按一下以切換來源
取得具有給定金鑰的參數值。
如果參數有多個值,只會擷取第一個值;請使用 params
來取得值陣列。
# File lib/cgi/core.rb, line 714 def [](key) params = @params[key] return '' unless params value = params[0] if @multipart if value return value elsif defined? StringIO StringIO.new("".b) else Tempfile.new("CGI",encoding: Encoding::ASCII_8BIT) end else str = if value then value.dup else "" end str end end
has_key?(*args) 按一下以切換來源
如果給定的查詢字串參數存在,則傳回 true。
# File lib/cgi/core.rb, line 738 def has_key?(*args) @params.has_key?(*args) end
keys(*args) 按一下以切換來源
傳回所有查詢參數名稱,格式為 String
陣列。
# File lib/cgi/core.rb, line 733 def keys(*args) @params.keys(*args) end
multipart?() 按一下以切換原始碼
傳回表單是否包含 multipart/form-data
# File lib/cgi/core.rb, line 706 def multipart? @multipart end
params=(hash) 按一下以切換原始碼
集合
所有參數。
# File lib/cgi/core.rb, line 474 def params=(hash) @params.clear @params.update(hash) end
私人實例方法
initialize_query() 按一下以切換原始碼
包裝類別,將 StringIO
物件用作主體,並在通過傳遞的閾值時切換到 TempFile。從查詢初始化資料。
處理多部分表單(特別是包含檔案上傳的表單)。讀取 @params 欄位中的查詢參數,並將 cookie 讀取到 @cookies。
# File lib/cgi/core.rb, line 661 def initialize_query() if ("POST" == env_table['REQUEST_METHOD']) and %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?| =~ env_table['CONTENT_TYPE'] current_max_multipart_length = @max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : @max_multipart_length raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length boundary = $1.dup @multipart = true @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) else @multipart = false @params = CGI.parse( case env_table['REQUEST_METHOD'] when "GET", "HEAD" if defined?(MOD_RUBY) Apache::request.args or "" else env_table['QUERY_STRING'] or "" end when "POST" stdinput.binmode if defined? stdinput.binmode stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or '' else read_from_cmdline end.dup.force_encoding(@accept_charset) ) unless Encoding.find(@accept_charset) == Encoding::ASCII_8BIT @params.each do |key,values| values.each do |value| unless value.valid_encoding? if @accept_charset_error_block @accept_charset_error_block.call(key,value) else raise InvalidEncoding,"Accept-Charset encoding error" end end end end end end @cookies = CGI::Cookie.parse((env_table['HTTP_COOKIE'] or env_table['COOKIE'])) end
read_from_cmdline() 按一下以切換原始碼
離線模式。讀取標準輸入上的 name=value 成對資料。
# File lib/cgi/core.rb, line 626 def read_from_cmdline require "shellwords" string = unless ARGV.empty? ARGV.join(' ') else if STDIN.tty? STDERR.print( %|(offline mode: enter name=value pairs on standard input)\n| ) end array = readlines rescue nil if not array.nil? array.join(' ').gsub(/\n/n, '') else "" end end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26') words = Shellwords.shellwords(string) if words.find{|x| /=/n.match(x) } words.join('&') else words.join('+') end end
read_multipart(boundary, content_length) 按一下以切換原始碼
根據下列內容剖析多部分表單元素
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
傳回多部分表單參數的雜湊,主體類型為 StringIO
或 Tempfile
,視多部分表單元素是否超過 10 KB
params[name => body]
# File lib/cgi/core.rb, line 488 def read_multipart(boundary, content_length) ## read first boundary stdin = stdinput first_line = "--#{boundary}#{EOL}" content_length -= first_line.bytesize status = stdin.read(first_line.bytesize) raise EOFError.new("no content body") unless status raise EOFError.new("bad content body") unless first_line == status ## parse and set params params = {} @files = {} boundary_rexp = /--#{Regexp.quote(boundary)}(#{EOL}|--)/ boundary_size = "#{EOL}--#{boundary}#{EOL}".bytesize buf = ''.dup bufsize = 10 * 1024 max_count = MAX_MULTIPART_COUNT n = 0 tempfiles = [] while true (n += 1) < max_count or raise StandardError.new("too many parameters.") ## create body (StringIO or Tempfile) body = create_body(bufsize < content_length) tempfiles << body if defined?(Tempfile) && body.kind_of?(Tempfile) class << body if method_defined?(:path) alias local_path path else def local_path nil end end attr_reader :original_filename, :content_type end ## find head and boundary head = nil separator = EOL * 2 until head && matched = boundary_rexp.match(buf) if !head && pos = buf.index(separator) len = pos + EOL.bytesize head = buf[0, len] buf = buf[(pos+separator.bytesize)..-1] else if head && buf.size > boundary_size len = buf.size - boundary_size body.print(buf[0, len]) buf[0, len] = '' end c = stdin.read(bufsize < content_length ? bufsize : content_length) raise EOFError.new("bad content body") if c.nil? || c.empty? buf << c content_length -= c.bytesize end end ## read to end of boundary m = matched len = m.begin(0) s = buf[0, len] if s =~ /(\r?\n)\z/ s = buf[0, len - $1.bytesize] end body.print(s) buf = buf[m.end(0)..-1] boundary_end = m[1] content_length = -1 if boundary_end == '--' ## reset file cursor position body.rewind ## original filename /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/i.match(head) filename = $1 || $2 || ''.dup filename = CGI.unescape(filename) if unescape_filename?() body.instance_variable_set(:@original_filename, filename) ## content type /Content-Type: (.*)/i.match(head) (content_type = $1 || ''.dup).chomp! body.instance_variable_set(:@content_type, content_type) ## query parameter name /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head) name = $1 || $2 || '' if body.original_filename.empty? value=body.read.dup.force_encoding(@accept_charset) body.close! if defined?(Tempfile) && body.kind_of?(Tempfile) (params[name] ||= []) << value unless value.valid_encoding? if @accept_charset_error_block @accept_charset_error_block.call(name,value) else raise InvalidEncoding,"Accept-Charset encoding error" end end class << params[name].last;self;end.class_eval do define_method(:read){self} define_method(:original_filename){""} define_method(:content_type){""} end else (params[name] ||= []) << body @files[name]=body end ## break loop break if content_length == -1 end raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/ params.default = [] params rescue Exception if tempfiles tempfiles.each {|t| if t.path t.close! end } end raise end