diff options
Diffstat (limited to 'apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl')
4 files changed, 147 insertions, 96 deletions
diff --git a/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlHandle.php b/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlHandle.php index 78f9bde87f6..63c6d4206ba 100644 --- a/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlHandle.php +++ b/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlHandle.php @@ -48,9 +48,16 @@ class CurlHandle $method = $request->getMethod(); $bodyAsString = $requestCurlOptions->get(self::BODY_AS_STRING); + // Prepare url + $url = (string)$request->getUrl(); + if(($pos = strpos($url, '#')) !== false ){ + // strip fragment from url + $url = substr($url, 0, $pos); + } + // Array of default cURL options. $curlOptions = array( - CURLOPT_URL => $request->getUrl(), + CURLOPT_URL => $url, CURLOPT_CONNECTTIMEOUT => 150, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, @@ -200,6 +207,12 @@ class CurlHandle $curlOptions[CURLOPT_PROGRESSFUNCTION] = function () use ($mediator, $handle) { $args = func_get_args(); $args[] = $handle; + + // PHP 5.5 pushed the handle onto the start of the args + if (is_resource($args[0])) { + array_shift($args); + } + call_user_func_array(array($mediator, 'progress'), $args); }; $curlOptions[CURLOPT_NOPROGRESS] = false; diff --git a/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlMulti.php b/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlMulti.php index a8c569984d2..9e4e637222d 100644 --- a/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlMulti.php +++ b/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlMulti.php @@ -7,6 +7,8 @@ use Guzzle\Common\Event; use Guzzle\Http\Exception\MultiTransferException; use Guzzle\Http\Exception\CurlException; use Guzzle\Http\Message\RequestInterface; +use Guzzle\Http\Message\EntityEnclosingRequestInterface; +use Guzzle\Http\Exception\RequestException; /** * Send {@see RequestInterface} objects in parallel using curl_multi @@ -39,8 +41,12 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface CURLM_INTERNAL_ERROR => array('CURLM_INTERNAL_ERROR', 'This can only be returned if libcurl bugs. Please report it to us!') ); - public function __construct() + /** @var float */ + protected $selectTimeout; + + public function __construct($selectTimeout = 1.0) { + $this->selectTimeout = $selectTimeout; $this->multiHandle = curl_multi_init(); // @codeCoverageIgnoreStart if ($this->multiHandle === false) { @@ -76,13 +82,12 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface public function remove(RequestInterface $request) { $this->removeHandle($request); - foreach ($this->requests as $i => $r) { - if ($request === $r) { - unset($this->requests[$i]); - $this->requests = array_values($this->requests); - $this->dispatch(self::REMOVE_REQUEST, array('request' => $request)); - return true; - } + if (($index = array_search($request, $this->requests, true)) !== false) { + $request = $this->requests[$index]; + unset($this->requests[$index]); + $this->requests = array_values($this->requests); + $this->dispatch(self::REMOVE_REQUEST, array('request' => $request)); + return true; } return false; @@ -130,8 +135,7 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface $multiException = new MultiTransferException('Errors during multi transfer'); while ($e = array_shift($exceptions)) { - $multiException->add($e['exception']); - $multiException->addFailedRequest($e['request']); + $multiException->addFailedRequestWithException($e['request'], $e['exception']); } // Add successful requests @@ -155,10 +159,10 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface try { $state = $request->setState(RequestInterface::STATE_TRANSFER); if ($state == RequestInterface::STATE_TRANSFER) { - // Add the request curl handle to the multi handle - $this->checkCurlResult(curl_multi_add_handle($this->multiHandle, $this->createCurlHandle($request)->getHandle())); + $this->addHandle($request); } else { - // Requests might decide they don't need to be sent just before transfer (e.g. CachePlugin) + // Requests might decide they don't need to be sent just before + // transfer (e.g. CachePlugin) $this->remove($request); if ($state == RequestInterface::STATE_COMPLETE) { $this->successful[] = $request; @@ -170,6 +174,14 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface } } + private function addHandle(RequestInterface $request) + { + $handle = $this->createCurlHandle($request)->getHandle(); + $this->checkCurlResult( + curl_multi_add_handle($this->multiHandle, $handle) + ); + } + /** * Create a curl handle for a request * @@ -191,18 +203,9 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface */ protected function perform() { - if (!$this->requests) { - return; - } - - // Initialize the handles with a very quick select timeout - $active = $mrc = null; - $this->executeHandles($active, $mrc, 0.001); $event = new Event(array('curl_multi' => $this)); - $this->processMessages(); while ($this->requests) { - // Notify each request as polling $blocking = $total = 0; foreach ($this->requests as $request) { @@ -214,33 +217,45 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface ++$blocking; } } - if ($blocking == $total) { // Sleep to prevent eating CPU because no requests are actually pending a select call usleep(500); } else { - do { - $this->executeHandles($active, $mrc, 1); - } while ($active); + $this->executeHandles(); } - $this->processMessages(); } } /** + * Execute and select curl handles + */ + private function executeHandles() + { + // The first curl_multi_select often times out no matter what, but is usually required for fast transfers + $selectTimeout = 0.001; + $active = false; + do { + while (($mrc = curl_multi_exec($this->multiHandle, $active)) == CURLM_CALL_MULTI_PERFORM); + $this->checkCurlResult($mrc); + $this->processMessages(); + if ($active && curl_multi_select($this->multiHandle, $selectTimeout) === -1) { + // Perform a usleep if a select returns -1: https://bugs.php.net/bug.php?id=61141 + usleep(150); + } + $selectTimeout = $this->selectTimeout; + } while ($active); + } + + /** * Process any received curl multi messages */ private function processMessages() { - // Get messages from curl handles while ($done = curl_multi_info_read($this->multiHandle)) { + $request = $this->resourceHash[(int) $done['handle']]; try { - $request = $this->resourceHash[(int) $done['handle']]; $this->processResponse($request, $this->handles[$request], $done); $this->successful[] = $request; - } catch (MultiTransferException $e) { - $this->removeErroredRequest($request, $e, false); - throw $e; } catch (\Exception $e) { $this->removeErroredRequest($request, $e); } @@ -248,43 +263,14 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface } /** - * Execute and select curl handles until there is activity - * - * @param int $active Active value to update - * @param int $mrc Multi result value to update - * @param int $timeout Select timeout in seconds - */ - private function executeHandles(&$active, &$mrc, $timeout = 1) - { - do { - $mrc = curl_multi_exec($this->multiHandle, $active); - } while ($mrc == CURLM_CALL_MULTI_PERFORM && $active); - $this->checkCurlResult($mrc); - - // @codeCoverageIgnoreStart - // Select the curl handles until there is any activity on any of the open file descriptors - // See https://github.com/php/php-src/blob/master/ext/curl/multi.c#L170 - if ($active && $mrc == CURLM_OK && curl_multi_select($this->multiHandle, $timeout) == -1) { - // Perform a usleep if a previously executed select returned -1 - // @see https://bugs.php.net/bug.php?id=61141 - usleep(100); - } - // @codeCoverageIgnoreEnd - } - - /** * Remove a request that encountered an exception * * @param RequestInterface $request Request to remove * @param \Exception $e Exception encountered - * @param bool $buffer Set to false to not buffer the exception */ - protected function removeErroredRequest(RequestInterface $request, \Exception $e = null, $buffer = true) + protected function removeErroredRequest(RequestInterface $request, \Exception $e = null) { - if ($buffer) { - $this->exceptions[] = array('request' => $request, 'exception' => $e); - } - + $this->exceptions[] = array('request' => $request, 'exception' => $e); $this->remove($request); $this->dispatch(self::MULTI_EXCEPTION, array('exception' => $e, 'all_exceptions' => $this->exceptions)); } @@ -310,23 +296,31 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface $this->removeHandle($request); if (!$curlException) { - $state = $request->setState(RequestInterface::STATE_COMPLETE, array('handle' => $handle)); - // Only remove the request if it wasn't resent as a result of the state change - if ($state != RequestInterface::STATE_TRANSFER) { - $this->remove($request); - } - } else { - // Set the state of the request to an error - $state = $request->setState(RequestInterface::STATE_ERROR, array('exception' => $curlException)); - // Allow things to ignore the error if possible - if ($state != RequestInterface::STATE_TRANSFER) { - $this->remove($request); - } - // The error was not handled, so fail - if ($state == RequestInterface::STATE_ERROR) { - /** @var CurlException $curlException */ - throw $curlException; + if ($this->validateResponseWasSet($request)) { + $state = $request->setState( + RequestInterface::STATE_COMPLETE, + array('handle' => $handle) + ); + // Only remove the request if it wasn't resent as a result of + // the state change + if ($state != RequestInterface::STATE_TRANSFER) { + $this->remove($request); + } } + return; + } + + // Set the state of the request to an error + $state = $request->setState(RequestInterface::STATE_ERROR, array('exception' => $curlException)); + // Allow things to ignore the error if possible + if ($state != RequestInterface::STATE_TRANSFER) { + $this->remove($request); + } + + // The error was not handled, so fail + if ($state == RequestInterface::STATE_ERROR) { + /** @var CurlException $curlException */ + throw $curlException; } } @@ -339,9 +333,9 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface { if (isset($this->handles[$request])) { $handle = $this->handles[$request]; + curl_multi_remove_handle($this->multiHandle, $handle->getHandle()); unset($this->handles[$request]); unset($this->resourceHash[(int) $handle->getHandle()]); - curl_multi_remove_handle($this->multiHandle, $handle->getHandle()); $handle->close(); } } @@ -387,4 +381,43 @@ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface ); } } + + /** + * @link https://github.com/guzzle/guzzle/issues/710 + */ + private function validateResponseWasSet(RequestInterface $request) + { + if ($request->getResponse()) { + return true; + } + + $body = $request instanceof EntityEnclosingRequestInterface + ? $request->getBody() + : null; + + if (!$body) { + $rex = new RequestException( + 'No response was received for a request with no body. This' + . ' could mean that you are saturating your network.' + ); + $rex->setRequest($request); + $this->removeErroredRequest($request, $rex); + } elseif (!$body->isSeekable() || !$body->seek(0)) { + // Nothing we can do with this. Sorry! + $rex = new RequestException( + 'The connection was unexpectedly closed. The request would' + . ' have been retried, but attempting to rewind the' + . ' request body failed.' + ); + $rex->setRequest($request); + $this->removeErroredRequest($request, $rex); + } else { + $this->remove($request); + // Add the request back to the batch to retry automatically. + $this->requests[] = $request; + $this->addHandle($request); + } + + return false; + } } diff --git a/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlMultiProxy.php b/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlMultiProxy.php index 665f029a79d..c5b80a7f57f 100644 --- a/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlMultiProxy.php +++ b/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/CurlMultiProxy.php @@ -15,13 +15,16 @@ class CurlMultiProxy extends AbstractHasDispatcher implements CurlMultiInterface protected $groups = array(); protected $queued = array(); protected $maxHandles; + protected $selectTimeout; /** - * @param int $maxHandles The maximum number of idle CurlMulti handles to allow to remain open + * @param int $maxHandles The maximum number of idle CurlMulti handles to allow to remain open + * @param float $selectTimeout timeout for curl_multi_select */ - public function __construct($maxHandles = 3) + public function __construct($maxHandles = 3, $selectTimeout = 1.0) { $this->maxHandles = $maxHandles; + $this->selectTimeout = $selectTimeout; // You can get some weird "Too many open files" errors when sending a large amount of requests in parallel. // These two statements autoload classes before a system runs out of file descriptors so that you can get back // valuable error messages if you run out. @@ -122,7 +125,7 @@ class CurlMultiProxy extends AbstractHasDispatcher implements CurlMultiInterface } // All are claimed, so create one - $handle = new CurlMulti(); + $handle = new CurlMulti($this->selectTimeout); $handle->setEventDispatcher($this->getEventDispatcher()); $this->handles[] = $handle; diff --git a/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/RequestMediator.php b/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/RequestMediator.php index 0a70c626bf0..5d1a0cd8724 100644 --- a/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/RequestMediator.php +++ b/apps/files_external/3rdparty/aws-sdk-php/Guzzle/Http/Curl/RequestMediator.php @@ -114,7 +114,12 @@ class RequestMediator )); } - return $this->request->getResponse()->getBody()->write($write); + if ($response = $this->request->getResponse()) { + return $response->getBody()->write($write); + } else { + // Unexpected data received before response headers - abort transfer + return 0; + } } /** @@ -128,18 +133,15 @@ class RequestMediator */ public function readRequestBody($ch, $fd, $length) { - $read = ''; - - if ($this->request->getBody()) { - $read = $this->request->getBody()->read($length); - if ($this->emitIo) { - $this->request->dispatch('curl.callback.read', array( - 'request' => $this->request, - 'read' => $read - )); - } + if (!($body = $this->request->getBody())) { + return ''; + } + + $read = (string) $body->read($length); + if ($this->emitIo) { + $this->request->dispatch('curl.callback.read', array('request' => $this->request, 'read' => $read)); } - return !$read ? '' : $read; + return $read; } } |