| Module | Merb::Parse |
| In: |
merb-core/lib/merb-core/dispatch/request_parsers.rb
|
| NAME_REGEX | = | /Content-Disposition:.* name="?([^\";]*)"?/ni.freeze |
| CONTENT_TYPE_REGEX | = | /Content-Type: (.*)\r\n/ni.freeze |
| FILENAME_REGEX | = | /Content-Disposition:.* filename="?([^\";]*)"?/ni.freeze |
| CRLF | = | "\r\n".freeze |
| EOL | = | CRLF |
| s<String>: | String to URL escape. |
| String: | The escaped string. |
:api: public
# File merb-core/lib/merb-core/dispatch/request_parsers.rb, line 178
178: def self.escape(s)
179: s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
180: '%'+$1.unpack('H2'*$1.size).join('%').upcase
181: }.tr(' ', '+')
182: end
| request<IO>: | The raw request. |
| boundary<String>: | The boundary string. |
| content_length<Fixnum>: | The length of the content. |
| ControllerExceptions::MultiPartParseError: | Failed to parse request. |
| Hash: | The parsed request. |
:api: plugin
# File merb-core/lib/merb-core/dispatch/request_parsers.rb, line 49
49: def self.multipart(request, boundary, content_length)
50: boundary = "--#{boundary}"
51: paramhsh = {}
52: buf = ""
53: input = request
54: input.binmode if defined? input.binmode
55: boundary_size = boundary.size + EOL.size
56: bufsize = 16384
57: content_length -= boundary_size
58: # status is boundary delimiter line
59: status = input.read(boundary_size)
60: return {} if status == nil || status.empty?
61: raise ControllerExceptions::MultiPartParseError, "bad content body:\n'#{status}' should == '#{boundary + EOL}'" unless status == boundary + EOL
62: # second argument to Regexp.quote is for KCODE
63: rx = /(?:#{EOL})?#{Regexp.quote(boundary,'n')}(#{EOL}|--)/
64: loop {
65: head = nil
66: body = ''
67: filename = content_type = name = nil
68: read_size = 0
69: until head && buf =~ rx
70: i = buf.index("\r\n\r\n")
71: if( i == nil && read_size == 0 && content_length == 0 )
72: content_length = -1
73: break
74: end
75: if !head && i
76: head = buf.slice!(0, i+2) # First \r\n
77: buf.slice!(0, 2) # Second \r\n
78:
79: # String#[] with 2nd arg here is returning
80: # a group from match data
81: filename = head[FILENAME_REGEX, 1]
82: content_type = head[CONTENT_TYPE_REGEX, 1]
83: name = head[NAME_REGEX, 1]
84:
85: if filename && !filename.empty?
86: body = Tempfile.new(:Merb)
87: body.binmode if defined? body.binmode
88: end
89: next
90: end
91:
92: # Save the read body part.
93: if head && (boundary_size+4 < buf.size)
94: body << buf.slice!(0, buf.size - (boundary_size+4))
95: end
96:
97: read_size = bufsize < content_length ? bufsize : content_length
98: if( read_size > 0 )
99: c = input.read(read_size)
100: raise ControllerExceptions::MultiPartParseError, "bad content body" if c.nil? || c.empty?
101: buf << c
102: content_length -= c.size
103: end
104: end
105:
106: # Save the rest.
107: if i = buf.index(rx)
108: # correct value of i for some edge cases
109: if (i > 2) && (j = buf.index(rx, i-2)) && (j < i)
110: i = j
111: end
112: body << buf.slice!(0, i)
113: buf.slice!(0, boundary_size+2)
114:
115: content_length = -1 if $1 == "--"
116: end
117:
118: if filename && !filename.empty?
119: body.rewind
120: data = {
121: :filename => File.basename(filename),
122: :content_type => content_type,
123: :tempfile => body,
124: :size => File.size(body.path)
125: }
126: else
127: data = body
128: end
129: paramhsh = normalize_params(paramhsh,name,data)
130: break if buf.empty? || content_length == -1
131: }
132: paramhsh
133: end
| value<Array, Hash, Dictionary ~to_s>: | The value for the query string. |
| prefix<~to_s>: | The prefix to add to the query string keys. |
| String: | The query string. |
If the value is a string, the prefix will be used as the key.
params_to_query_string(10, "page")
# => "page=10"
params_to_query_string({ :page => 10, :word => "ruby" })
# => "page=10&word=ruby"
params_to_query_string({ :page => 10, :word => "ruby" }, "search")
# => "search[page]=10&search[word]=ruby"
params_to_query_string([ "ice-cream", "cake" ], "shopping_list")
# => "shopping_list[]=ice-cream&shopping_list[]=cake"
:api: plugin
# File merb-core/lib/merb-core/dispatch/request_parsers.rb, line 156
156: def self.params_to_query_string(value, prefix = nil)
157: case value
158: when Array
159: value.map { |v|
160: params_to_query_string(v, "#{prefix}[]")
161: } * "&"
162: when Hash, Dictionary
163: value.map { |k, v|
164: params_to_query_string(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
165: } * "&"
166: else
167: "#{prefix}=#{escape(value)}"
168: end
169: end
| query_string<String>: | The query string. |
| delimiter<String>: | The query string divider. Defaults to "&". |
| preserve_order<Boolean>: | Preserve order of args. Defaults to false. |
| Mash: | The parsed query string (Dictionary if preserve_order is set). |
Merb::Parse.query("bar=nik&post[body]=heya")
# => { :bar => "nik", :post => { :body => "heya" } }
:api: plugin
# File merb-core/lib/merb-core/dispatch/request_parsers.rb, line 17
17: def self.query(query_string, delimiter = '&;', preserve_order = false)
18: query = preserve_order ? Dictionary.new : {}
19: for pair in (query_string || '').split(/[#{delimiter}] */n)
20: key, value = unescape(pair).split('=',2)
21: next if key.nil?
22: if key.include?('[')
23: normalize_params(query, key, value)
24: else
25: query[key] = value
26: end
27: end
28: preserve_order ? query : query.to_mash
29: end
Converts a query string snippet to a hash and adds it to existing parameters.
| parms<Hash>: | Parameters to add the normalized parameters to. |
| name<String>: | The key of the parameter to normalize. |
| val<String>: | The value of the parameter. |
| Hash: | Normalized parameters |
:api: private
# File merb-core/lib/merb-core/dispatch/request_parsers.rb, line 222
222: def self.normalize_params(parms, name, val=nil)
223: name =~ %r([\[\]]*([^\[\]]+)\]*)
224: key = $1 || ''
225: after = $' || ''
226:
227: if after == ""
228: parms[key] = val
229: elsif after == "[]"
230: (parms[key] ||= []) << val
231: elsif after =~ %r(^\[\]\[([^\[\]]+)\]$)
232: child_key = $1
233: parms[key] ||= []
234: if parms[key].last.is_a?(Hash) && !parms[key].last.key?(child_key)
235: parms[key].last.update(child_key => val)
236: else
237: parms[key] << { child_key => val }
238: end
239: else
240: parms[key] ||= {}
241: parms[key] = normalize_params(parms[key], after, val)
242: end
243: parms
244: end