Parent

Class Index [+]

Quicksearch

Rack::Multipart::Parser

Constants

BUFSIZE

Public Class Methods

new(env) click to toggle source
    # File lib/rack/multipart/parser.rb, line 8
 8:       def initialize(env)
 9:         @env = env
10:       end

Public Instance Methods

parse() click to toggle source
    # File lib/rack/multipart/parser.rb, line 12
12:       def parse
13:         return nil unless setup_parse
14: 
15:         fast_forward_to_first_boundary
16: 
17:         loop do
18:           head, filename, content_type, name, body =
19:             get_current_head_and_filename_and_content_type_and_name_and_body
20: 
21:           # Save the rest.
22:           if i = @buf.index(rx)
23:             body << @buf.slice!(0, i)
24:             @buf.slice!(0, @boundary_size+2)
25: 
26:             @content_length = 1  if $1 == "--"
27:           end
28: 
29:           filename, data = get_data(filename, body, content_type, name, head)
30: 
31:           Utils.normalize_params(@params, name, data) unless data.nil?
32: 
33:           # break if we're at the end of a buffer, but not if it is the end of a field
34:           break if (@buf.empty? && $1 != EOL) || @content_length == 1
35:         end
36: 
37:         @io.rewind
38: 
39:         @params.to_params_hash
40:       end

Private Instance Methods

fast_forward_to_first_boundary() click to toggle source
    # File lib/rack/multipart/parser.rb, line 69
69:       def fast_forward_to_first_boundary
70:         loop do
71:           read_buffer = @io.gets
72:           break if read_buffer == full_boundary
73:           raise EOFError, "bad content body" if read_buffer.nil?
74:         end
75:       end
full_boundary() click to toggle source
    # File lib/rack/multipart/parser.rb, line 61
61:       def full_boundary
62:         @boundary + EOL
63:       end
get_current_head_and_filename_and_content_type_and_name_and_body() click to toggle source
     # File lib/rack/multipart/parser.rb, line 77
 77:       def get_current_head_and_filename_and_content_type_and_name_and_body
 78:         head = nil
 79:         body = ''
 80:         filename = content_type = name = nil
 81:         content = nil
 82: 
 83:         until head && @buf =~ rx
 84:           if !head && i = @buf.index(EOL+EOL)
 85:             head = @buf.slice!(0, i+2) # First \r\n
 86: 
 87:             @buf.slice!(0, 2)          # Second \r\n
 88: 
 89:             content_type = head[MULTIPART_CONTENT_TYPE, 1]
 90:             name = head[MULTIPART_CONTENT_DISPOSITION, 1] || head[MULTIPART_CONTENT_ID, 1]
 91: 
 92:             filename = get_filename(head)
 93: 
 94:             if filename
 95:               body = Tempfile.new("RackMultipart")
 96:               body.binmode  if body.respond_to?(:binmode)
 97:             end
 98: 
 99:             next
100:           end
101: 
102:           # Save the read body part.
103:           if head && (@boundary_size+4 < @buf.size)
104:             body << @buf.slice!(0, @buf.size - (@boundary_size+4))
105:           end
106: 
107:           content = @io.read(BUFSIZE < @content_length ? BUFSIZE : @content_length)
108:           raise EOFError, "bad content body"  if content.nil? || content.empty?
109: 
110:           @buf << content
111:           @content_length -= content.size
112:         end
113: 
114:         [head, filename, content_type, name, body]
115:       end
get_data(filename, body, content_type, name, head) click to toggle source
     # File lib/rack/multipart/parser.rb, line 137
137:       def get_data(filename, body, content_type, name, head)
138:         data = nil
139:         if filename == ""
140:           # filename is blank which means no file has been selected
141:           return data
142:         elsif filename
143:           body.rewind
144: 
145:           # Take the basename of the upload's original filename.
146:           # This handles the full Windows paths given by Internet Explorer
147:           # (and perhaps other broken user agents) without affecting
148:           # those which give the lone filename.
149:           filename = filename.split(/[\/\\]/).last
150: 
151:           data = {:filename => filename, :type => content_type,
152:                   :name => name, :tempfile => body, :head => head}
153:         elsif !filename && content_type && body.is_a?(IO)
154:           body.rewind
155: 
156:           # Generic multipart cases, not coming from a form
157:           data = {:type => content_type,
158:                   :name => name, :tempfile => body, :head => head}
159:         else
160:           data = body
161:         end
162: 
163:         [filename, data]
164:       end
get_filename(head) click to toggle source
     # File lib/rack/multipart/parser.rb, line 117
117:       def get_filename(head)
118:         filename = nil
119:         if head =~ RFC2183
120:           filename = Hash[head.scan(DISPPARM)]['filename']
121:           filename = $1 if filename and filename =~ /^"(.*)"$/
122:         elsif head =~ BROKEN_QUOTED
123:           filename = $1
124:         elsif head =~ BROKEN_UNQUOTED
125:           filename = $1
126:         end
127: 
128:         if filename && filename.scan(/%.?.?/).all? { |s| s =~ /%[0-9a-fA-F]{2}/ }
129:           filename = Utils.unescape(filename)
130:         end
131:         if filename && filename !~ /\\[^\\"]/
132:           filename = filename.gsub(/\\(.)/, '\1')
133:         end
134:         filename
135:       end
rx() click to toggle source
    # File lib/rack/multipart/parser.rb, line 65
65:       def rx
66:         @rx ||= /(?:#{EOL})?#{Regexp.quote(@boundary)}(#{EOL}|--)/
67:       end
setup_parse() click to toggle source
    # File lib/rack/multipart/parser.rb, line 43
43:       def setup_parse
44:         return false unless @env['CONTENT_TYPE'] =~ MULTIPART
45: 
46:         @boundary = "--#{$1}"
47: 
48:         @buf = ""
49:         @params = Utils::KeySpaceConstrainedParams.new
50: 
51:         @content_length = @env['CONTENT_LENGTH'].to_i
52:         @io = @env['rack.input']
53:         @io.rewind
54: 
55:         @boundary_size = Utils.bytesize(@boundary) + EOL.size
56: 
57:         @content_length -= @boundary_size
58:         true
59:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.