# File lib/protocols/httpclient.rb, line 165
165:   def receive_data data
166:     while data and data.length > 0
167:       case @read_state
168:       when :base
169:         # Perform any per-request initialization here and don't consume any data.
170:         @data = ""
171:         @headers = []
172:         @content_length = nil # not zero
173:         @content = ""
174:         @status = nil
175:         @read_state = :header
176:         @connection_close = nil
177:       when :header
178:         ary = data.split( /\r?\n/m, 2 )
179:         if ary.length == 2
180:           data = ary.last
181:           if ary.first == ""
182:               if (@content_length and @content_length > 0) || @connection_close
183:                   @read_state = :content
184:               else
185:                   dispatch_response
186:                   @read_state = :base
187:               end
188:           else
189:             @headers << ary.first
190:             if @headers.length == 1
191:               parse_response_line
192:             elsif ary.first =~ /\Acontent-length:\s*/i
193:               # Only take the FIRST content-length header that appears,
194:               # which we can distinguish because @content_length is nil.
195:               # TODO, it's actually a fatal error if there is more than one
196:               # content-length header, because the caller is presumptively
197:               # a bad guy. (There is an exploit that depends on multiple
198:               # content-length headers.)
199:               @content_length ||= $'.to_i
200:             elsif ary.first =~ /\Aconnection:\s*close/i
201:               @connection_close = true
202:             end
203:           end
204:         else
205:           @data << data
206:           data = ""
207:         end
208:       when :content
209:         # If there was no content-length header, we have to wait until the connection
210:         # closes. Everything we get until that point is content.
211:         # TODO: Must impose a content-size limit, and also must implement chunking.
212:         # Also, must support either temporary files for large content, or calling
213:         # a content-consumer block supplied by the user.
214:         if @content_length
215:           bytes_needed = @content_length - @content.length
216:           @content += data[0, bytes_needed]
217:           data = data[bytes_needed..-1] || ""
218:           if @content_length == @content.length
219:             dispatch_response
220:             @read_state = :base
221:           end
222:         else
223:           @content << data
224:           data = ""
225:         end
226:       end
227:     end
228:   end