diff options
Diffstat (limited to 'lib/cgi')
| -rw-r--r-- | lib/cgi/cgi.gemspec | 42 | ||||
| -rw-r--r-- | lib/cgi/cookie.rb | 57 | ||||
| -rw-r--r-- | lib/cgi/core.rb | 78 | ||||
| -rw-r--r-- | lib/cgi/html.rb | 6 | ||||
| -rw-r--r-- | lib/cgi/session.rb | 72 | ||||
| -rw-r--r-- | lib/cgi/session/pstore.rb | 19 | ||||
| -rw-r--r-- | lib/cgi/util.rb | 121 |
7 files changed, 135 insertions, 260 deletions
diff --git a/lib/cgi/cgi.gemspec b/lib/cgi/cgi.gemspec deleted file mode 100644 index 381c55a5ca..0000000000 --- a/lib/cgi/cgi.gemspec +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Yukihiro Matsumoto"] - spec.email = ["matz@ruby-lang.org"] - - spec.summary = %q{Support for the Common Gateway Interface protocol.} - spec.description = %q{Support for the Common Gateway Interface protocol.} - spec.homepage = "https://github.com/ruby/cgi" - spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.required_ruby_version = ">= 2.5.0" - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - spec.executables = [] - - spec.files = [ - "LICENSE.txt", - "README.md", - *Dir["lib{.rb,/**/*.rb}", "bin/*"] ] - - spec.require_paths = ["lib"] - - if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' - spec.platform = 'java' - spec.require_paths << "ext/java/org/jruby/ext/cgi/escape/lib" - spec.files += Dir["ext/java/**/*.{rb}", "lib/cgi/escape.jar"] - else - spec.files += Dir["ext/cgi/**/*.{rb,c,h,sh}", "ext/cgi/escape/depend", "lib/cgi/escape.so"] - spec.extensions = ["ext/cgi/escape/extconf.rb"] - end -end diff --git a/lib/cgi/cookie.rb b/lib/cgi/cookie.rb index 9498e2f9fa..a2155edb77 100644 --- a/lib/cgi/cookie.rb +++ b/lib/cgi/cookie.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require_relative 'util' +require 'cgi/util' class CGI # Class representing an HTTP cookie. # @@ -40,10 +40,6 @@ class CGI class Cookie < Array @@accept_charset="UTF-8" unless defined?(@@accept_charset) - TOKEN_RE = %r"\A[[!-~]&&[^()<>@,;:\\\"/?=\[\]{}]]+\z" - PATH_VALUE_RE = %r"\A[[ -~]&&[^;]]*\z" - DOMAIN_VALUE_RE = %r"\A\.?(?<label>(?!-)[-A-Za-z0-9]+(?<!-))(?:\.\g<label>)*\z" - # Create a new CGI::Cookie object. # # :call-seq: @@ -61,7 +57,7 @@ class CGI # # 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 + # path:: the path for which this cookie applies. Defaults to the # the value of the +SCRIPT_NAME+ environment variable. # domain:: the domain for which this cookie applies. # expires:: the time at which this cookie expires, as a +Time+ object. @@ -76,8 +72,9 @@ class CGI @domain = nil @expires = nil if name.kind_of?(String) - self.name = name - self.path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "") + @name = name + %r|^(.*/)|.match(ENV["SCRIPT_NAME"]) + @path = ($1 or "") @secure = false @httponly = false return super(value) @@ -88,11 +85,16 @@ class CGI raise ArgumentError, "`name' required" end - self.name = options["name"] + @name = options["name"] value = Array(options["value"]) # simple support for IE - self.path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "") - self.domain = options["domain"] + if options["path"] + @path = options["path"] + else + %r|^(.*/)|.match(ENV["SCRIPT_NAME"]) + @path = ($1 or "") + end + @domain = options["domain"] @expires = options["expires"] @secure = options["secure"] == true @httponly = options["httponly"] == true @@ -101,35 +103,11 @@ class CGI end # Name of this cookie, as a +String+ - attr_reader :name - # Set name of this cookie - def name=(str) - if str and !TOKEN_RE.match?(str) - raise ArgumentError, "invalid name: #{str.dump}" - end - @name = str - end - + attr_accessor :name # Path for which this cookie applies, as a +String+ - attr_reader :path - # Set path for which this cookie applies - def path=(str) - if str and !PATH_VALUE_RE.match?(str) - raise ArgumentError, "invalid path: #{str.dump}" - end - @path = str - end - + attr_accessor :path # Domain for which this cookie applies, as a +String+ - attr_reader :domain - # Set domain for which this cookie applies - def domain=(str) - if str and ((str = str.b).bytesize > 255 or !DOMAIN_VALUE_RE.match?(str)) - raise ArgumentError, "invalid domain: #{str.dump}" - end - @domain = str - end - + attr_accessor :domain # Time at which this cookie expires, as a +Time+ attr_accessor :expires # True if this cookie is secure; false otherwise @@ -168,7 +146,7 @@ class CGI buf = "#{@name}=#{val}".dup buf << "; domain=#{@domain}" if @domain buf << "; path=#{@path}" if @path - buf << "; expires=#{CGI.rfc1123_date(@expires)}" if @expires + buf << "; expires=#{CGI::rfc1123_date(@expires)}" if @expires buf << "; secure" if @secure buf << "; HttpOnly" if @httponly buf @@ -187,6 +165,7 @@ class CGI raw_cookie.split(/;\s?/).each do |pairs| name, values = pairs.split('=',2) next unless name and values + name = CGI.unescape(name) values ||= "" values = values.split('&').collect{|v| CGI.unescape(v,@@accept_charset) } if cookies.has_key?(name) diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb index 62e606837a..73daae3e17 100644 --- a/lib/cgi/core.rb +++ b/lib/cgi/core.rb @@ -188,28 +188,17 @@ class CGI # Using #header with the HTML5 tag maker will create a <header> element. alias :header :http_header - def _no_crlf_check(str) - if str - str = str.to_s - raise "A HTTP status or header field must not include CR and LF" if str =~ /[\r\n]/ - str - else - nil - end - end - private :_no_crlf_check - def _header_for_string(content_type) #:nodoc: buf = ''.dup if nph?() - buf << "#{_no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'} 200 OK#{EOL}" + buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}" buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}" - buf << "Server: #{_no_crlf_check($CGI_ENV['SERVER_SOFTWARE'])}#{EOL}" + buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}" buf << "Connection: close#{EOL}" end - buf << "Content-Type: #{_no_crlf_check(content_type)}#{EOL}" + buf << "Content-Type: #{content_type}#{EOL}" if @output_cookies - @output_cookies.each {|cookie| buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" } + @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" } end return buf end # _header_for_string @@ -224,9 +213,9 @@ class CGI ## NPH options.delete('nph') if defined?(MOD_RUBY) if options.delete('nph') || nph?() - protocol = _no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0' + protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0' status = options.delete('status') - status = HTTP_STATUS[status] || _no_crlf_check(status) || '200 OK' + status = HTTP_STATUS[status] || status || '200 OK' buf << "#{protocol} #{status}#{EOL}" buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}" options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || '' @@ -234,45 +223,45 @@ class CGI end ## common headers status = options.delete('status') - buf << "Status: #{HTTP_STATUS[status] || _no_crlf_check(status)}#{EOL}" if status + buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status server = options.delete('server') - buf << "Server: #{_no_crlf_check(server)}#{EOL}" if server + buf << "Server: #{server}#{EOL}" if server connection = options.delete('connection') - buf << "Connection: #{_no_crlf_check(connection)}#{EOL}" if connection + buf << "Connection: #{connection}#{EOL}" if connection type = options.delete('type') - buf << "Content-Type: #{_no_crlf_check(type)}#{EOL}" #if type + buf << "Content-Type: #{type}#{EOL}" #if type length = options.delete('length') - buf << "Content-Length: #{_no_crlf_check(length)}#{EOL}" if length + buf << "Content-Length: #{length}#{EOL}" if length language = options.delete('language') - buf << "Content-Language: #{_no_crlf_check(language)}#{EOL}" if language + buf << "Content-Language: #{language}#{EOL}" if language expires = options.delete('expires') buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires ## cookie if cookie = options.delete('cookie') case cookie when String, Cookie - buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" + buf << "Set-Cookie: #{cookie}#{EOL}" when Array arr = cookie - arr.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" } + arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" } when Hash hash = cookie - hash.each_value {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" } + hash.each_value {|c| buf << "Set-Cookie: #{c}#{EOL}" } end end if @output_cookies - @output_cookies.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" } + @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" } end ## other headers options.each do |key, value| - buf << "#{_no_crlf_check(key)}: #{_no_crlf_check(value)}#{EOL}" + buf << "#{key}: #{value}#{EOL}" end return buf end # _header_for_hash private :_header_for_hash def nph? #:nodoc: - return /IIS\/(\d+)/ =~ $CGI_ENV['SERVER_SOFTWARE'] && $1.to_i < 5 + return /IIS\/(\d+)/.match($CGI_ENV['SERVER_SOFTWARE']) && $1.to_i < 5 end def _header_for_modruby(buf) #:nodoc: @@ -386,14 +375,14 @@ class CGI # Parse an HTTP query string into a hash of key=>value pairs. # - # params = CGI.parse("query_string") + # params = CGI::parse("query_string") # # {"name1" => ["value1", "value2", ...], # # "name2" => ["value1", "value2", ...], ... } # - def self.parse(query) + def CGI::parse(query) params = {} query.split(/[&;]/).each do |pairs| - key, value = pairs.split('=',2).collect{|v| CGI.unescape(v) } + key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) } next unless key @@ -432,7 +421,7 @@ class CGI module QueryExtension %w[ CONTENT_LENGTH SERVER_PORT ].each do |env| - define_method(env.delete_prefix('HTTP_').downcase) do + define_method(env.sub(/^HTTP_/, '').downcase) do (val = env_table[env]) && Integer(val) end end @@ -445,7 +434,7 @@ class CGI HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env| - define_method(env.delete_prefix('HTTP_').downcase) do + define_method(env.sub(/^HTTP_/, '').downcase) do env_table[env] end end @@ -555,11 +544,11 @@ class CGI /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) + body.instance_variable_set(:@original_filename, filename.taint) ## content type /Content-Type: (.*)/i.match(head) (content_type = $1 || ''.dup).chomp! - body.instance_variable_set(:@content_type, content_type) + body.instance_variable_set(:@content_type, content_type.taint) ## query parameter name /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head) name = $1 || $2 || '' @@ -618,7 +607,6 @@ class CGI end def unescape_filename? #:nodoc: user_agent = $CGI_ENV['HTTP_USER_AGENT'] - return false unless user_agent return /Mac/i.match(user_agent) && /Mozilla/i.match(user_agent) && !/MSIE/i.match(user_agent) end @@ -660,7 +648,7 @@ class CGI # Reads query parameters in the @params field, and cookies into @cookies. def initialize_query() if ("POST" == env_table['REQUEST_METHOD']) and - %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?| =~ env_table['CONTENT_TYPE'] + %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(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 @@ -668,7 +656,7 @@ class CGI @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) else @multipart = false - @params = CGI.parse( + @params = CGI::parse( case env_table['REQUEST_METHOD'] when "GET", "HEAD" if defined?(MOD_RUBY) @@ -698,7 +686,7 @@ class CGI end end - @cookies = CGI::Cookie.parse((env_table['HTTP_COOKIE'] or env_table['COOKIE'])) + @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE'])) end private :initialize_query @@ -874,24 +862,24 @@ class CGI case @options[:tag_maker] when "html3" - require_relative 'html' + require 'cgi/html' extend Html3 extend HtmlExtension when "html4" - require_relative 'html' + require 'cgi/html' extend Html4 extend HtmlExtension when "html4Tr" - require_relative 'html' + require 'cgi/html' extend Html4Tr extend HtmlExtension when "html4Fr" - require_relative 'html' + require 'cgi/html' extend Html4Tr extend Html4Fr extend HtmlExtension when "html5" - require_relative 'html' + require 'cgi/html' extend Html5 extend HtmlExtension end diff --git a/lib/cgi/html.rb b/lib/cgi/html.rb index 1543943320..02d847ebd3 100644 --- a/lib/cgi/html.rb +++ b/lib/cgi/html.rb @@ -30,10 +30,10 @@ class CGI attributes.each do|name, value| next unless value s << " " - s << CGI.escapeHTML(name.to_s) + s << CGI::escapeHTML(name.to_s) if value != true s << '="' - s << CGI.escapeHTML(value.to_s) + s << CGI::escapeHTML(value.to_s) s << '"' end end @@ -423,7 +423,7 @@ class CGI buf << super(attributes) if pretty - CGI.pretty(buf, pretty) + CGI::pretty(buf, pretty) else buf end diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb index aab60869bb..fbb42986a4 100644 --- a/lib/cgi/session.rb +++ b/lib/cgi/session.rb @@ -189,47 +189,6 @@ class CGI end private :create_new_id - - # Create a new file to store the session data. - # - # This file will be created if it does not exist, or opened if it - # does. - # - # This path is generated under _tmpdir_ from _prefix_, the - # digested session id, and _suffix_. - # - # +option+ is a hash of options for the initializer. The - # following options are recognised: - # - # tmpdir:: the directory to use for storing the FileStore - # file. Defaults to Dir::tmpdir (generally "/tmp" - # on Unix systems). - # prefix:: the prefix to add to the session id when generating - # the filename for this session's FileStore file. - # Defaults to "cgi_sid_". - # suffix:: the prefix to add to the session id when generating - # the filename for this session's FileStore file. - # Defaults to the empty string. - def new_store_file(option={}) # :nodoc: - dir = option['tmpdir'] || Dir::tmpdir - prefix = option['prefix'] - suffix = option['suffix'] - require 'digest/md5' - md5 = Digest::MD5.hexdigest(session_id)[0,16] - path = dir+"/" - path << prefix if prefix - path << md5 - path << suffix if suffix - if File::exist? path - hash = nil - elsif new_session - hash = {} - else - raise NoSession, "uninitialized session" - end - return path, hash - end - # Create a new CGI::Session object for +request+. # # +request+ is an instance of the +CGI+ class (see cgi.rb). @@ -279,7 +238,7 @@ class CGI # fields are surrounded by a <fieldset> tag in HTML 4 generation, which # is _not_ invisible on many browsers; you may wish to disable the # use of fieldsets with code similar to the following - # (see https://blade.ruby-lang.org/ruby-list/37805) + # (see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/37805) # # cgi = CGI.new("html4") # class << cgi @@ -414,8 +373,21 @@ class CGI # This session's FileStore file will be created if it does # not exist, or opened if it does. def initialize(session, option={}) - option = {'prefix' => 'cgi_sid_'}.update(option) - @path, @hash = session.new_store_file(option) + dir = option['tmpdir'] || Dir::tmpdir + prefix = option['prefix'] || 'cgi_sid_' + suffix = option['suffix'] || '' + id = session.session_id + require 'digest/md5' + md5 = Digest::MD5.hexdigest(id)[0,16] + @path = dir+"/"+prefix+md5+suffix + if File::exist? @path + @hash = nil + else + unless session.new_session + raise CGI::Session::NoSession, "uninitialized session" + end + @hash = {} + end end # Restore session state from the session's FileStore file. @@ -431,11 +403,11 @@ class CGI for line in f line.chomp! k, v = line.split('=',2) - @hash[CGI.unescape(k)] = Marshal.restore(CGI.unescape(v)) + @hash[CGI::unescape(k)] = Marshal.restore(CGI::unescape(v)) end ensure - f&.close - lockf&.close + f.close unless f.nil? + lockf.close if lockf end end @hash @@ -449,13 +421,13 @@ class CGI lockf.flock File::LOCK_EX f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600) for k,v in @hash - f.printf "%s=%s\n", CGI.escape(k), CGI.escape(String(Marshal.dump(v))) + f.printf "%s=%s\n", CGI::escape(k), CGI::escape(String(Marshal.dump(v))) end f.close File.rename @path+".new", @path ensure - f&.close - lockf&.close + f.close if f + lockf.close if lockf end end diff --git a/lib/cgi/session/pstore.rb b/lib/cgi/session/pstore.rb index 45d0d8ae2c..cb0370b619 100644 --- a/lib/cgi/session/pstore.rb +++ b/lib/cgi/session/pstore.rb @@ -10,7 +10,7 @@ # persistent of session data on top of the pstore library. See # cgi/session.rb for more details on session storage managers. -require_relative '../session' +require 'cgi/session' require 'pstore' class CGI @@ -44,8 +44,21 @@ class CGI # This session's PStore file will be created if it does # not exist, or opened if it does. def initialize(session, option={}) - option = {'suffix'=>''}.update(option) - path, @hash = session.new_store_file(option) + dir = option['tmpdir'] || Dir::tmpdir + prefix = option['prefix'] || '' + id = session.session_id + require 'digest/md5' + md5 = Digest::MD5.hexdigest(id)[0,16] + path = dir+"/"+prefix+md5 + path.untaint + if File::exist?(path) + @hash = nil + else + unless session.new_session + raise CGI::Session::NoSession, "uninitialized session" + end + @hash = {} + end @p = ::PStore.new(path) @p.transaction do |p| File.chmod(0600, p.path) diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb index 4986e544e0..464115262f 100644 --- a/lib/cgi/util.rb +++ b/lib/cgi/util.rb @@ -5,63 +5,27 @@ class CGI extend Util end module CGI::Util - @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset) - - # URL-encode a string into application/x-www-form-urlencoded. - # Space characters (+" "+) are encoded with plus signs (+"+"+) - # url_encoded_string = CGI.escape("'Stop!' said Fred") + @@accept_charset="UTF-8" unless defined?(@@accept_charset) + # URL-encode a string. + # url_encoded_string = CGI::escape("'Stop!' said Fred") # # => "%27Stop%21%27+said+Fred" def escape(string) encoding = string.encoding - buffer = string.b - buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m| + string.b.gsub(/([^ a-zA-Z0-9_.\-~]+)/) do |m| '%' + m.unpack('H2' * m.bytesize).join('%').upcase - end - buffer.tr!(' ', '+') - buffer.force_encoding(encoding) + end.tr(' ', '+').force_encoding(encoding) end - # URL-decode an application/x-www-form-urlencoded string with encoding(optional). - # string = CGI.unescape("%27Stop%21%27+said+Fred") + # URL-decode a string with encoding(optional). + # string = CGI::unescape("%27Stop%21%27+said+Fred") # # => "'Stop!' said Fred" - def unescape(string, encoding = @@accept_charset) - str = string.tr('+', ' ') - str = str.b - str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m| - [m.delete('%')].pack('H*') - end - str.force_encoding(encoding) - str.valid_encoding? ? str : str.force_encoding(string.encoding) - end - - # URL-encode a string following RFC 3986 - # Space characters (+" "+) are encoded with (+"%20"+) - # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred") - # # => "%27Stop%21%27%20said%20Fred" - def escapeURIComponent(string) - encoding = string.encoding - buffer = string.b - buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m| - '%' + m.unpack('H2' * m.bytesize).join('%').upcase - end - buffer.force_encoding(encoding) - end - alias escape_uri_component escapeURIComponent - - # URL-decode a string following RFC 3986 with encoding(optional). - # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred") - # # => "'Stop!'+said Fred" - def unescapeURIComponent(string, encoding = @@accept_charset) - str = string.b - str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m| + def unescape(string,encoding=@@accept_charset) + str=string.tr('+', ' ').b.gsub(/((?:%[0-9a-fA-F]{2})+)/) do |m| [m.delete('%')].pack('H*') - end - str.force_encoding(encoding) + end.force_encoding(encoding) str.valid_encoding? ? str : str.force_encoding(string.encoding) end - alias unescape_uri_component unescapeURIComponent - # The set of special characters and their escaped values TABLE_FOR_ESCAPE_HTML__ = { "'" => ''', @@ -72,7 +36,7 @@ module CGI::Util } # Escape special characters in HTML, namely '&\"<> - # CGI.escapeHTML('Usage: foo "bar" <baz>') + # CGI::escapeHTML('Usage: foo "bar" <baz>') # # => "Usage: foo "bar" <baz>" def escapeHTML(string) enc = string.encoding @@ -85,24 +49,18 @@ module CGI::Util table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}] string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table) string.encode!(origenc) if origenc - string - else - string = string.b - string.gsub!(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) - string.force_encoding(enc) + return string end + string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) end - # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there - unless RUBY_ENGINE == 'truffleruby' - begin - require 'cgi/escape' - rescue LoadError - end + begin + require 'cgi/escape' + rescue LoadError end # Unescape a string that has been HTML-escaped - # CGI.unescapeHTML("Usage: foo "bar" <baz>") + # CGI::unescapeHTML("Usage: foo "bar" <baz>") # # => "Usage: foo \"bar\" <baz>" def unescapeHTML(string) enc = string.encoding @@ -132,8 +90,7 @@ module CGI::Util when Encoding::ISO_8859_1; 256 else 128 end - string = string.b - string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do + string.gsub(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do match = $1.dup case match when 'apos' then "'" @@ -159,13 +116,12 @@ module CGI::Util "&#{match};" end end - string.force_encoding enc end - # Synonym for CGI.escapeHTML(str) + # Synonym for CGI::escapeHTML(str) alias escape_html escapeHTML - # Synonym for CGI.unescapeHTML(str) + # Synonym for CGI::unescapeHTML(str) alias unescape_html unescapeHTML # Escape only the tags of certain HTML elements in +string+. @@ -176,30 +132,30 @@ module CGI::Util # The attribute list of the open tag will also be escaped (for # instance, the double-quotes surrounding attribute values). # - # print CGI.escapeElement('<BR><A HREF="url"></A>', "A", "IMG") + # print CGI::escapeElement('<BR><A HREF="url"></A>', "A", "IMG") # # "<BR><A HREF="url"></A>" # - # print CGI.escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"]) + # print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"]) # # "<BR><A HREF="url"></A>" def escapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) unless elements.empty? string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do - CGI.escapeHTML($&) + CGI::escapeHTML($&) end else string end end - # Undo escaping such as that done by CGI.escapeElement() + # Undo escaping such as that done by CGI::escapeElement() # - # print CGI.unescapeElement( - # CGI.escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG") + # print CGI::unescapeElement( + # CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG") # # "<BR><A HREF="url"></A>" # - # print CGI.unescapeElement( - # CGI.escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"]) + # print CGI::unescapeElement( + # CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"]) # # "<BR><A HREF="url"></A>" def unescapeElement(string, *elements) elements = elements[0] if elements[0].kind_of?(Array) @@ -212,18 +168,27 @@ module CGI::Util end end - # Synonym for CGI.escapeElement(str) + # Synonym for CGI::escapeElement(str) alias escape_element escapeElement - # Synonym for CGI.unescapeElement(str) + # Synonym for CGI::unescapeElement(str) alias unescape_element unescapeElement + # 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 ] + # Format a +Time+ object as a String using the format specified by RFC 1123. # - # CGI.rfc1123_date(Time.now) + # CGI::rfc1123_date(Time.now) # # Sat, 01 Jan 2000 00:00:00 GMT def rfc1123_date(time) - time.getgm.strftime("%a, %d %b %Y %T GMT") + t = time.clone.gmtime + return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", + RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year, + t.hour, t.min, t.sec) end # Prettify (indent) an HTML string. @@ -231,13 +196,13 @@ module CGI::Util # +string+ is the HTML string to indent. +shift+ is the indentation # unit to use; it defaults to two spaces. # - # print CGI.pretty("<HTML><BODY></BODY></HTML>") + # print CGI::pretty("<HTML><BODY></BODY></HTML>") # # <HTML> # # <BODY> # # </BODY> # # </HTML> # - # print CGI.pretty("<HTML><BODY></BODY></HTML>", "\t") + # print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t") # # <HTML> # # <BODY> # # </BODY> |
