Conditions | 89 |
Paths | > 20000 |
Total Lines | 334 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | <?php |
||
164 | public function sendRequest($url,$data='',$method='GET'){ |
||
165 | $this->start = $this->time(); |
||
166 | $this->error = ''; |
||
167 | $this->status = 0; |
||
168 | $this->resp_body = ''; |
||
169 | $this->resp_headers = array(); |
||
170 | |||
171 | // don't accept gzip if truncated bodies might occur |
||
172 | if($this->max_bodysize && |
||
173 | !$this->max_bodysize_abort && |
||
174 | $this->headers['Accept-encoding'] == 'gzip'){ |
||
175 | unset($this->headers['Accept-encoding']); |
||
176 | } |
||
177 | |||
178 | // parse URL into bits |
||
179 | $uri = parse_url($url); |
||
180 | $server = $uri['host']; |
||
181 | $path = !empty($uri['path']) ? $uri['path'] : '/'; |
||
182 | $uriPort = !empty($uri['port']) ? $uri['port'] : null; |
||
183 | if(!empty($uri['query'])) $path .= '?'.$uri['query']; |
||
184 | if(isset($uri['user'])) $this->user = $uri['user']; |
||
185 | if(isset($uri['pass'])) $this->pass = $uri['pass']; |
||
186 | |||
187 | // proxy setup |
||
188 | if($this->useProxyForUrl($url)){ |
||
189 | $request_url = $url; |
||
190 | $server = $this->proxy_host; |
||
191 | $port = $this->proxy_port; |
||
192 | if (empty($port)) $port = 8080; |
||
193 | $use_tls = $this->proxy_ssl; |
||
194 | }else{ |
||
195 | $request_url = $path; |
||
196 | if (!isset($port)) $port = ($uri['scheme'] == 'https') ? 443 : 80; |
||
|
|||
197 | $use_tls = ($uri['scheme'] == 'https'); |
||
198 | } |
||
199 | |||
200 | // add SSL stream prefix if needed - needs SSL support in PHP |
||
201 | if($use_tls) { |
||
202 | if(!in_array('ssl', stream_get_transports())) { |
||
203 | $this->status = -200; |
||
204 | $this->error = 'This PHP version does not support SSL - cannot connect to server'; |
||
205 | } |
||
206 | $server = 'ssl://'.$server; |
||
207 | } |
||
208 | |||
209 | // prepare headers |
||
210 | $headers = $this->headers; |
||
211 | $headers['Host'] = $uri['host'] |
||
212 | . ($uriPort ? ':' . $uriPort : ''); |
||
213 | $headers['User-Agent'] = $this->agent; |
||
214 | $headers['Referer'] = $this->referer; |
||
215 | |||
216 | if($method == 'POST'){ |
||
217 | if(is_array($data)){ |
||
218 | if (empty($headers['Content-Type'])) { |
||
219 | $headers['Content-Type'] = null; |
||
220 | } |
||
221 | switch ($headers['Content-Type']) { |
||
222 | case 'multipart/form-data': |
||
223 | $headers['Content-Type'] = 'multipart/form-data; boundary=' . $this->boundary; |
||
224 | $data = $this->postMultipartEncode($data); |
||
225 | break; |
||
226 | default: |
||
227 | $headers['Content-Type'] = 'application/x-www-form-urlencoded'; |
||
228 | $data = $this->postEncode($data); |
||
229 | } |
||
230 | } |
||
231 | }elseif($method == 'GET'){ |
||
232 | $data = ''; //no data allowed on GET requests |
||
233 | } |
||
234 | |||
235 | $contentlength = strlen($data); |
||
236 | if($contentlength) { |
||
237 | $headers['Content-Length'] = $contentlength; |
||
238 | } |
||
239 | |||
240 | if($this->user) { |
||
241 | $headers['Authorization'] = 'Basic '.base64_encode($this->user.':'.$this->pass); |
||
242 | } |
||
243 | if($this->proxy_user) { |
||
244 | $headers['Proxy-Authorization'] = 'Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass); |
||
245 | } |
||
246 | |||
247 | // already connected? |
||
248 | $connectionId = $this->uniqueConnectionId($server,$port); |
||
249 | $this->debug('connection pool', self::$connections); |
||
250 | $socket = null; |
||
251 | if (isset(self::$connections[$connectionId])) { |
||
252 | $this->debug('reusing connection', $connectionId); |
||
253 | $socket = self::$connections[$connectionId]; |
||
254 | } |
||
255 | if (is_null($socket) || feof($socket)) { |
||
256 | $this->debug('opening connection', $connectionId); |
||
257 | // open socket |
||
258 | $socket = @fsockopen($server,$port,$errno, $errstr, $this->timeout); |
||
259 | if (!$socket){ |
||
260 | $this->status = -100; |
||
261 | $this->error = "Could not connect to $server:$port\n$errstr ($errno)"; |
||
262 | return false; |
||
263 | } |
||
264 | |||
265 | // try establish a CONNECT tunnel for SSL |
||
266 | try { |
||
267 | if($this->ssltunnel($socket, $request_url)){ |
||
268 | // no keep alive for tunnels |
||
269 | $this->keep_alive = false; |
||
270 | // tunnel is authed already |
||
271 | if(isset($headers['Proxy-Authentication'])) unset($headers['Proxy-Authentication']); |
||
272 | } |
||
273 | } catch (HTTPClientException $e) { |
||
274 | $this->status = $e->getCode(); |
||
275 | $this->error = $e->getMessage(); |
||
276 | fclose($socket); |
||
277 | return false; |
||
278 | } |
||
279 | |||
280 | // keep alive? |
||
281 | if ($this->keep_alive) { |
||
282 | self::$connections[$connectionId] = $socket; |
||
283 | } else { |
||
284 | unset(self::$connections[$connectionId]); |
||
285 | } |
||
286 | } |
||
287 | |||
288 | if ($this->keep_alive && !$this->useProxyForUrl($request_url)) { |
||
289 | // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive |
||
290 | // connection token to a proxy server. We still do keep the connection the |
||
291 | // proxy alive (well except for CONNECT tunnels) |
||
292 | $headers['Connection'] = 'Keep-Alive'; |
||
293 | } else { |
||
294 | $headers['Connection'] = 'Close'; |
||
295 | } |
||
296 | |||
297 | try { |
||
298 | //set non-blocking |
||
299 | stream_set_blocking($socket, 0); |
||
300 | |||
301 | // build request |
||
302 | $request = "$method $request_url HTTP/".$this->http.HTTP_NL; |
||
303 | $request .= $this->buildHeaders($headers); |
||
304 | $request .= $this->getCookies(); |
||
305 | $request .= HTTP_NL; |
||
306 | $request .= $data; |
||
307 | |||
308 | $this->debug('request',$request); |
||
309 | $this->sendData($socket, $request, 'request'); |
||
310 | |||
311 | // read headers from socket |
||
312 | $r_headers = ''; |
||
313 | do{ |
||
314 | $r_line = $this->readLine($socket, 'headers'); |
||
315 | $r_headers .= $r_line; |
||
316 | }while($r_line != "\r\n" && $r_line != "\n"); |
||
317 | |||
318 | $this->debug('response headers',$r_headers); |
||
319 | |||
320 | // check if expected body size exceeds allowance |
||
321 | if($this->max_bodysize && preg_match('/\r?\nContent-Length:\s*(\d+)\r?\n/i',$r_headers,$match)){ |
||
322 | if($match[1] > $this->max_bodysize){ |
||
323 | if ($this->max_bodysize_abort) |
||
324 | throw new HTTPClientException('Reported content length exceeds allowed response size'); |
||
325 | else |
||
326 | $this->error = 'Reported content length exceeds allowed response size'; |
||
327 | } |
||
328 | } |
||
329 | |||
330 | // get Status |
||
331 | if (!preg_match('/^HTTP\/(\d\.\d)\s*(\d+).*?\n/s', $r_headers, $m)) |
||
332 | throw new HTTPClientException('Server returned bad answer '.$r_headers); |
||
333 | |||
334 | $this->status = $m[2]; |
||
335 | |||
336 | // handle headers and cookies |
||
337 | $this->resp_headers = $this->parseHeaders($r_headers); |
||
338 | if(isset($this->resp_headers['set-cookie'])){ |
||
339 | foreach ((array) $this->resp_headers['set-cookie'] as $cookie){ |
||
340 | list($cookie) = explode(';',$cookie,2); |
||
341 | list($key,$val) = explode('=',$cookie,2); |
||
342 | $key = trim($key); |
||
343 | if($val == 'deleted'){ |
||
344 | if(isset($this->cookies[$key])){ |
||
345 | unset($this->cookies[$key]); |
||
346 | } |
||
347 | }elseif($key){ |
||
348 | $this->cookies[$key] = $val; |
||
349 | } |
||
350 | } |
||
351 | } |
||
352 | |||
353 | $this->debug('Object headers',$this->resp_headers); |
||
354 | |||
355 | // check server status code to follow redirect |
||
356 | if($this->status == 301 || $this->status == 302 ){ |
||
357 | if (empty($this->resp_headers['location'])){ |
||
358 | throw new HTTPClientException('Redirect but no Location Header found'); |
||
359 | }elseif($this->redirect_count == $this->max_redirect){ |
||
360 | throw new HTTPClientException('Maximum number of redirects exceeded'); |
||
361 | }else{ |
||
362 | // close the connection because we don't handle content retrieval here |
||
363 | // that's the easiest way to clean up the connection |
||
364 | fclose($socket); |
||
365 | unset(self::$connections[$connectionId]); |
||
366 | |||
367 | $this->redirect_count++; |
||
368 | $this->referer = $url; |
||
369 | // handle non-RFC-compliant relative redirects |
||
370 | if (!preg_match('/^http/i', $this->resp_headers['location'])){ |
||
371 | if($this->resp_headers['location'][0] != '/'){ |
||
372 | $this->resp_headers['location'] = $uri['scheme'].'://'.$uri['host'].':'.$uriPort. |
||
373 | dirname($path).'/'.$this->resp_headers['location']; |
||
374 | }else{ |
||
375 | $this->resp_headers['location'] = $uri['scheme'].'://'.$uri['host'].':'.$uriPort. |
||
376 | $this->resp_headers['location']; |
||
377 | } |
||
378 | } |
||
379 | // perform redirected request, always via GET (required by RFC) |
||
380 | return $this->sendRequest($this->resp_headers['location'],array(),'GET'); |
||
381 | } |
||
382 | } |
||
383 | |||
384 | // check if headers are as expected |
||
385 | if($this->header_regexp && !preg_match($this->header_regexp,$r_headers)) |
||
386 | throw new HTTPClientException('The received headers did not match the given regexp'); |
||
387 | |||
388 | //read body (with chunked encoding if needed) |
||
389 | $r_body = ''; |
||
390 | if( |
||
391 | ( |
||
392 | isset($this->resp_headers['transfer-encoding']) && |
||
393 | $this->resp_headers['transfer-encoding'] == 'chunked' |
||
394 | ) || ( |
||
395 | isset($this->resp_headers['transfer-coding']) && |
||
396 | $this->resp_headers['transfer-coding'] == 'chunked' |
||
397 | ) |
||
398 | ) { |
||
399 | $abort = false; |
||
400 | do { |
||
401 | $chunk_size = ''; |
||
402 | while (preg_match('/^[a-zA-Z0-9]?$/',$byte=$this->readData($socket,1,'chunk'))){ |
||
403 | // read chunksize until \r |
||
404 | $chunk_size .= $byte; |
||
405 | if (strlen($chunk_size) > 128) // set an abritrary limit on the size of chunks |
||
406 | throw new HTTPClientException('Allowed response size exceeded'); |
||
407 | } |
||
408 | $this->readLine($socket, 'chunk'); // readtrailing \n |
||
409 | $chunk_size = hexdec($chunk_size); |
||
410 | |||
411 | if($this->max_bodysize && $chunk_size+strlen($r_body) > $this->max_bodysize){ |
||
412 | if ($this->max_bodysize_abort) |
||
413 | throw new HTTPClientException('Allowed response size exceeded'); |
||
414 | $this->error = 'Allowed response size exceeded'; |
||
415 | $chunk_size = $this->max_bodysize - strlen($r_body); |
||
416 | $abort = true; |
||
417 | } |
||
418 | |||
419 | if ($chunk_size > 0) { |
||
420 | $r_body .= $this->readData($socket, $chunk_size, 'chunk'); |
||
421 | $this->readData($socket, 2, 'chunk'); // read trailing \r\n |
||
422 | } |
||
423 | } while ($chunk_size && !$abort); |
||
424 | }elseif(isset($this->resp_headers['content-length']) && !isset($this->resp_headers['transfer-encoding'])){ |
||
425 | /* RFC 2616 |
||
426 | * If a message is received with both a Transfer-Encoding header field and a Content-Length |
||
427 | * header field, the latter MUST be ignored. |
||
428 | */ |
||
429 | |||
430 | // read up to the content-length or max_bodysize |
||
431 | // for keep alive we need to read the whole message to clean up the socket for the next read |
||
432 | if( |
||
433 | !$this->keep_alive && |
||
434 | $this->max_bodysize && |
||
435 | $this->max_bodysize < $this->resp_headers['content-length'] |
||
436 | ) { |
||
437 | $length = $this->max_bodysize + 1; |
||
438 | }else{ |
||
439 | $length = $this->resp_headers['content-length']; |
||
440 | } |
||
441 | |||
442 | $r_body = $this->readData($socket, $length, 'response (content-length limited)', true); |
||
443 | }elseif( !isset($this->resp_headers['transfer-encoding']) && $this->max_bodysize && !$this->keep_alive){ |
||
444 | $r_body = $this->readData($socket, $this->max_bodysize+1, 'response (content-length limited)', true); |
||
445 | } elseif ((int)$this->status === 204) { |
||
446 | // request has no content |
||
447 | } else{ |
||
448 | // read entire socket |
||
449 | while (!feof($socket)) { |
||
450 | $r_body .= $this->readData($socket, 4096, 'response (unlimited)', true); |
||
451 | } |
||
452 | } |
||
453 | |||
454 | // recheck body size, we might have read max_bodysize+1 or even the whole body, so we abort late here |
||
455 | if($this->max_bodysize){ |
||
456 | if(strlen($r_body) > $this->max_bodysize){ |
||
457 | if ($this->max_bodysize_abort) { |
||
458 | throw new HTTPClientException('Allowed response size exceeded'); |
||
459 | } else { |
||
460 | $this->error = 'Allowed response size exceeded'; |
||
461 | } |
||
462 | } |
||
463 | } |
||
464 | |||
465 | } catch (HTTPClientException $err) { |
||
466 | $this->error = $err->getMessage(); |
||
467 | if ($err->getCode()) |
||
468 | $this->status = $err->getCode(); |
||
469 | unset(self::$connections[$connectionId]); |
||
470 | fclose($socket); |
||
471 | return false; |
||
472 | } |
||
473 | |||
474 | if (!$this->keep_alive || |
||
475 | (isset($this->resp_headers['connection']) && $this->resp_headers['connection'] == 'Close')) { |
||
476 | // close socket |
||
477 | fclose($socket); |
||
478 | unset(self::$connections[$connectionId]); |
||
479 | } |
||
480 | |||
481 | // decode gzip if needed |
||
482 | if(isset($this->resp_headers['content-encoding']) && |
||
483 | $this->resp_headers['content-encoding'] == 'gzip' && |
||
484 | strlen($r_body) > 10 && substr($r_body,0,3)=="\x1f\x8b\x08"){ |
||
485 | $this->resp_body = @gzinflate(substr($r_body, 10)); |
||
486 | if($this->resp_body === false){ |
||
487 | $this->error = 'Failed to decompress gzip encoded content'; |
||
488 | $this->resp_body = $r_body; |
||
489 | } |
||
490 | }else{ |
||
491 | $this->resp_body = $r_body; |
||
492 | } |
||
493 | |||
494 | $this->debug('response body',$this->resp_body); |
||
495 | $this->redirect_count = 0; |
||
496 | return true; |
||
497 | } |
||
498 | |||
885 |
This check marks calls to
isset(...)
orempty(...)
that are found before the variable itself is defined. These will always have the same result.This is likely the result of code being shifted around. Consider removing these calls.