lib/rack/utils.rb in rack-1.0.0 vs lib/rack/utils.rb in rack-1.0.1

- old
+ new

@@ -1,5 +1,7 @@ +# -*- encoding: binary -*- + require 'set' require 'tempfile' module Rack # Rack::Utils contains a grab-bag of useful methods for writing web @@ -9,11 +11,11 @@ # Performs URI escaping so that you can construct proper # query strings faster. Use this rather than the cgi.rb # version since it's faster. (Stolen from Camping). def escape(s) s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) { - '%'+$1.unpack('H2'*$1.size).join('%').upcase + '%'+$1.unpack('H2'*bytesize($1)).join('%').upcase }.tr(' ', '+') end module_function :escape # Unescapes a URI escaped string. (Stolen from Camping). @@ -22,20 +24,22 @@ [$1.delete('%')].pack('H*') } end module_function :unescape + DEFAULT_SEP = /[&;] */n + # Stolen from Mongrel, with some small modifications: # Parses a query string by breaking it up at the '&' # and ';' characters. You can also use this to parse # cookies by changing the characters used in the second # parameter (which defaults to '&;'). - def parse_query(qs, d = '&;') + def parse_query(qs, d = nil) params = {} - (qs || '').split(/[#{d}] */n).each do |p| - k, v = unescape(p).split('=', 2) + (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p| + k, v = p.split('=', 2).map { |x| unescape(x) } if cur = params[k] if cur.class == Array params[k] << v else @@ -48,24 +52,24 @@ return params end module_function :parse_query - def parse_nested_query(qs, d = '&;') + def parse_nested_query(qs, d = nil) params = {} - (qs || '').split(/[#{d}] */n).each do |p| + (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p| k, v = unescape(p).split('=', 2) normalize_params(params, k, v) end return params end module_function :parse_nested_query def normalize_params(params, name, v = nil) - name =~ %r([\[\]]*([^\[\]]+)\]*) + name =~ %r(\A[\[\]]*([^\[\]]+)\]*) k = $1 || '' after = $' || '' return if k.empty? @@ -97,11 +101,11 @@ def build_query(params) params.map { |k, v| if v.class == Array build_query(v.map { |x| [k, x] }) else - escape(k) + "=" + escape(v) + "#{escape(k)}=#{escape(v)}" end }.join("&") end module_function :build_query @@ -302,11 +306,11 @@ buf = "" content_length = env['CONTENT_LENGTH'].to_i input = env['rack.input'] input.rewind - boundary_size = boundary.size + EOL.size + boundary_size = Utils.bytesize(boundary) + EOL.size bufsize = 16384 content_length -= boundary_size read_buffer = '' @@ -324,10 +328,10 @@ until head && buf =~ rx if !head && i = buf.index(EOL+EOL) head = buf.slice!(0, i+2) # First \r\n buf.slice!(0, 2) # Second \r\n - filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1] + filename = head[/Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;\s]*))/ni, 1] content_type = head[/Content-Type: (.*)#{EOL}/ni, 1] name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1] if content_type || filename body = Tempfile.new("RackMultipart")