diff options
Diffstat (limited to 'vendor/sabre/http/lib')
23 files changed, 839 insertions, 1279 deletions
diff --git a/vendor/sabre/http/lib/Auth/AWS.php b/vendor/sabre/http/lib/Auth/AWS.php index 5e176646a..ffda3cf15 100644 --- a/vendor/sabre/http/lib/Auth/AWS.php +++ b/vendor/sabre/http/lib/Auth/AWS.php @@ -1,11 +1,13 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP\Auth; -use Sabre\HTTP\Util; +use Sabre\HTTP; /** - * HTTP AWS Authentication handler + * HTTP AWS Authentication handler. * * Use this class to leverage amazon's AWS authentication header * @@ -13,24 +15,24 @@ use Sabre\HTTP\Util; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class AWS extends AbstractAuth { - +class AWS extends AbstractAuth +{ /** - * The signature supplied by the HTTP client + * The signature supplied by the HTTP client. * * @var string */ private $signature = null; /** - * The accesskey supplied by the HTTP client + * The accesskey supplied by the HTTP client. * * @var string */ private $accessKey = null; /** - * An error code, if any + * An error code, if any. * * This value will be filled with one of the ERR_* constants * @@ -45,47 +47,45 @@ class AWS extends AbstractAuth { const ERR_INVALIDSIGNATURE = 5; /** - * Gathers all information from the headers + * Gathers all information from the headers. * * This method needs to be called prior to anything else. - * - * @return bool */ - function init() { - + public function init(): bool + { $authHeader = $this->request->getHeader('Authorization'); + + if (null === $authHeader) { + $this->errorCode = self::ERR_NOAWSHEADER; + + return false; + } $authHeader = explode(' ', $authHeader); - if ($authHeader[0] != 'AWS' || !isset($authHeader[1])) { + if ('AWS' !== $authHeader[0] || !isset($authHeader[1])) { $this->errorCode = self::ERR_NOAWSHEADER; - return false; + + return false; } list($this->accessKey, $this->signature) = explode(':', $authHeader[1]); return true; - } /** - * Returns the username for the request - * - * @return string + * Returns the username for the request. */ - function getAccessKey() { - + public function getAccessKey(): string + { return $this->accessKey; - } /** - * Validates the signature based on the secretKey - * - * @param string $secretKey - * @return bool + * Validates the signature based on the secretKey. */ - function validate($secretKey) { - + public function validate(string $secretKey): bool + { $contentMD5 = $this->request->getHeader('Content-MD5'); if ($contentMD5) { @@ -93,57 +93,53 @@ class AWS extends AbstractAuth { $body = $this->request->getBody(); $this->request->setBody($body); - if ($contentMD5 != base64_encode(md5($body, true))) { + if ($contentMD5 !== base64_encode(md5((string) $body, true))) { // content-md5 header did not match md5 signature of body $this->errorCode = self::ERR_MD5CHECKSUMWRONG; + return false; } - } - if (!$requestDate = $this->request->getHeader('x-amz-date')) + if (!$requestDate = $this->request->getHeader('x-amz-date')) { $requestDate = $this->request->getHeader('Date'); + } - if (!$this->validateRFC2616Date($requestDate)) + if (!$this->validateRFC2616Date((string) $requestDate)) { return false; + } $amzHeaders = $this->getAmzHeaders(); $signature = base64_encode( $this->hmacsha1($secretKey, - $this->request->getMethod() . "\n" . - $contentMD5 . "\n" . - $this->request->getHeader('Content-type') . "\n" . - $requestDate . "\n" . - $amzHeaders . + $this->request->getMethod()."\n". + $contentMD5."\n". + $this->request->getHeader('Content-type')."\n". + $requestDate."\n". + $amzHeaders. $this->request->getUrl() ) ); - if ($this->signature != $signature) { - + if ($this->signature !== $signature) { $this->errorCode = self::ERR_INVALIDSIGNATURE; - return false; + return false; } return true; - } - /** - * Returns an HTTP 401 header, forcing login + * Returns an HTTP 401 header, forcing login. * * This should be called when username and password are incorrect, or not supplied at all - * - * @return void */ - function requireLogin() { - + public function requireLogin() + { $this->response->addHeader('WWW-Authenticate', 'AWS'); $this->response->setStatus(401); - } /** @@ -154,17 +150,15 @@ class AWS extends AbstractAuth { * * This function also makes sure the Date header is within 15 minutes of the operating * system date, to prevent replay attacks. - * - * @param string $dateHeader - * @return bool */ - protected function validateRFC2616Date($dateHeader) { - - $date = Util::parseHTTPDate($dateHeader); + protected function validateRFC2616Date(string $dateHeader): bool + { + $date = HTTP\parseDate($dateHeader); // Unknown format if (!$date) { $this->errorCode = self::ERR_INVALIDDATEFORMAT; + return false; } @@ -174,47 +168,40 @@ class AWS extends AbstractAuth { // We allow 15 minutes around the current date/time if ($date > $max || $date < $min) { $this->errorCode = self::ERR_REQUESTTIMESKEWED; + return false; } - return $date; - + return true; } /** - * Returns a list of AMZ headers - * - * @return string + * Returns a list of AMZ headers. */ - protected function getAmzHeaders() { - + protected function getAmzHeaders(): string + { $amzHeaders = []; $headers = $this->request->getHeaders(); foreach ($headers as $headerName => $headerValue) { - if (strpos(strtolower($headerName), 'x-amz-') === 0) { - $amzHeaders[strtolower($headerName)] = str_replace(["\r\n"], [' '], $headerValue[0]) . "\n"; + if (0 === strpos(strtolower($headerName), 'x-amz-')) { + $amzHeaders[strtolower($headerName)] = str_replace(["\r\n"], [' '], $headerValue[0])."\n"; } } ksort($amzHeaders); $headerStr = ''; foreach ($amzHeaders as $h => $v) { - $headerStr .= $h . ':' . $v; + $headerStr .= $h.':'.$v; } return $headerStr; - } /** - * Generates an HMAC-SHA1 signature - * - * @param string $key - * @param string $message - * @return string + * Generates an HMAC-SHA1 signature. */ - private function hmacsha1($key, $message) { - + private function hmacsha1(string $key, string $message): string + { if (function_exists('hash_hmac')) { return hash_hmac('sha1', $message, $key, true); } @@ -226,9 +213,8 @@ class AWS extends AbstractAuth { $key = str_pad($key, $blocksize, chr(0x00)); $ipad = str_repeat(chr(0x36), $blocksize); $opad = str_repeat(chr(0x5c), $blocksize); - $hmac = pack('H*', sha1(($key ^ $opad) . pack('H*', sha1(($key ^ $ipad) . $message)))); - return $hmac; + $hmac = pack('H*', sha1(($key ^ $opad).pack('H*', sha1(($key ^ $ipad).$message)))); + return $hmac; } - } diff --git a/vendor/sabre/http/lib/Auth/AbstractAuth.php b/vendor/sabre/http/lib/Auth/AbstractAuth.php index ae45b3ee2..ada6bf0f0 100644 --- a/vendor/sabre/http/lib/Auth/AbstractAuth.php +++ b/vendor/sabre/http/lib/Auth/AbstractAuth.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP\Auth; use Sabre\HTTP\RequestInterface; @@ -14,60 +16,50 @@ use Sabre\HTTP\ResponseInterface; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -abstract class AbstractAuth { - +abstract class AbstractAuth +{ /** - * Authentication realm + * Authentication realm. * * @var string */ protected $realm; /** - * Request object + * Request object. * * @var RequestInterface */ protected $request; /** - * Response object + * Response object. * * @var ResponseInterface */ protected $response; /** - * Creates the object - * - * @param string $realm - * @return void + * Creates the object. */ - function __construct($realm = 'SabreTooth', RequestInterface $request, ResponseInterface $response) { - + public function __construct(string $realm = 'SabreTooth', RequestInterface $request, ResponseInterface $response) + { $this->realm = $realm; $this->request = $request; $this->response = $response; - } /** * This method sends the needed HTTP header and statuscode (401) to force * the user to login. - * - * @return void */ - abstract function requireLogin(); + abstract public function requireLogin(); /** - * Returns the HTTP realm - * - * @return string + * Returns the HTTP realm. */ - function getRealm() { - + public function getRealm(): string + { return $this->realm; - } - } diff --git a/vendor/sabre/http/lib/Auth/Basic.php b/vendor/sabre/http/lib/Auth/Basic.php index c263e3f9b..d04b4a811 100644 --- a/vendor/sabre/http/lib/Auth/Basic.php +++ b/vendor/sabre/http/lib/Auth/Basic.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP\Auth; /** @@ -15,25 +17,25 @@ namespace Sabre\HTTP\Auth; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Basic extends AbstractAuth { - +class Basic extends AbstractAuth +{ /** * This method returns a numeric array with a username and password as the * only elements. * * If no credentials were found, this method returns null. * - * @return null|array + * @return array|null */ - function getCredentials() { - + public function getCredentials() + { $auth = $this->request->getHeader('Authorization'); if (!$auth) { return null; } - if (strtolower(substr($auth, 0, 6)) !== 'basic ') { + if ('basic ' !== strtolower(substr($auth, 0, 6))) { return null; } @@ -44,20 +46,15 @@ class Basic extends AbstractAuth { } return $credentials; - } /** * This method sends the needed HTTP header and statuscode (401) to force * the user to login. - * - * @return void */ - function requireLogin() { - - $this->response->addHeader('WWW-Authenticate', 'Basic realm="' . $this->realm . '", charset="UTF-8"'); + public function requireLogin() + { + $this->response->addHeader('WWW-Authenticate', 'Basic realm="'.$this->realm.'", charset="UTF-8"'); $this->response->setStatus(401); - } - } diff --git a/vendor/sabre/http/lib/Auth/Bearer.php b/vendor/sabre/http/lib/Auth/Bearer.php index eefdf11ee..988bb29d2 100644 --- a/vendor/sabre/http/lib/Auth/Bearer.php +++ b/vendor/sabre/http/lib/Auth/Bearer.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP\Auth; /** @@ -15,42 +17,37 @@ namespace Sabre\HTTP\Auth; * @author François Kooman (fkooman@tuxed.net) * @license http://sabre.io/license/ Modified BSD License */ -class Bearer extends AbstractAuth { - +class Bearer extends AbstractAuth +{ /** * This method returns a string with an access token. * * If no token was found, this method returns null. * - * @return null|string + * @return string|null */ - function getToken() { - + public function getToken() + { $auth = $this->request->getHeader('Authorization'); if (!$auth) { return null; } - if (strtolower(substr($auth, 0, 7)) !== 'bearer ') { + if ('bearer ' !== strtolower(substr($auth, 0, 7))) { return null; } return substr($auth, 7); - } /** * This method sends the needed HTTP header and statuscode (401) to force * authentication. - * - * @return void */ - function requireLogin() { - - $this->response->addHeader('WWW-Authenticate', 'Bearer realm="' . $this->realm . '"'); + public function requireLogin() + { + $this->response->addHeader('WWW-Authenticate', 'Bearer realm="'.$this->realm.'"'); $this->response->setStatus(401); - } - } diff --git a/vendor/sabre/http/lib/Auth/Digest.php b/vendor/sabre/http/lib/Auth/Digest.php index 4b3f0746f..dd35a0b74 100644 --- a/vendor/sabre/http/lib/Auth/Digest.php +++ b/vendor/sabre/http/lib/Auth/Digest.php @@ -1,12 +1,14 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP\Auth; use Sabre\HTTP\RequestInterface; use Sabre\HTTP\ResponseInterface; /** - * HTTP Digest Authentication handler + * HTTP Digest Authentication handler. * * Use this class for easy http digest authentication. * Instructions: @@ -27,10 +29,10 @@ use Sabre\HTTP\ResponseInterface; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Digest extends AbstractAuth { - +class Digest extends AbstractAuth +{ /** - * These constants are used in setQOP(); + * These constants are used in setQOP();. */ const QOP_AUTH = 1; const QOP_AUTHINT = 2; @@ -42,28 +44,24 @@ class Digest extends AbstractAuth { protected $qop = self::QOP_AUTH; /** - * Initializes the object + * Initializes the object. */ - function __construct($realm = 'SabreTooth', RequestInterface $request, ResponseInterface $response) { - + public function __construct(string $realm = 'SabreTooth', RequestInterface $request, ResponseInterface $response) + { $this->nonce = uniqid(); $this->opaque = md5($realm); parent::__construct($realm, $request, $response); - } /** - * Gathers all information from the headers + * Gathers all information from the headers. * * This method needs to be called prior to anything else. - * - * @return void */ - function init() { - + public function init() + { $digest = $this->getDigest(); - $this->digestParts = $this->parseDigest($digest); - + $this->digestParts = $this->parseDigest((string) $digest); } /** @@ -78,115 +76,101 @@ class Digest extends AbstractAuth { * QOP_AUTHINT ensures integrity of the request body, but this is not * supported by most HTTP clients. QOP_AUTHINT also requires the entire * request body to be md5'ed, which can put strains on CPU and memory. - * - * @param int $qop - * @return void */ - function setQOP($qop) { - + public function setQOP(int $qop) + { $this->qop = $qop; - } /** * Validates the user. * * The A1 parameter should be md5($username . ':' . $realm . ':' . $password); - * - * @param string $A1 - * @return bool */ - function validateA1($A1) { - + public function validateA1(string $A1): bool + { $this->A1 = $A1; - return $this->validate(); + return $this->validate(); } /** * Validates authentication through a password. The actual password must be provided here. * It is strongly recommended not store the password in plain-text and use validateA1 instead. - * - * @param string $password - * @return bool */ - function validatePassword($password) { + public function validatePassword(string $password): bool + { + $this->A1 = md5($this->digestParts['username'].':'.$this->realm.':'.$password); - $this->A1 = md5($this->digestParts['username'] . ':' . $this->realm . ':' . $password); return $this->validate(); - } /** - * Returns the username for the request + * Returns the username for the request. + * Returns null if there were none. * - * @return string + * @return string|null */ - function getUsername() { - - return $this->digestParts['username']; - + public function getUsername() + { + return $this->digestParts['username'] ?? null; } /** - * Validates the digest challenge - * - * @return bool + * Validates the digest challenge. */ - protected function validate() { + protected function validate(): bool + { + if (!is_array($this->digestParts)) { + return false; + } - $A2 = $this->request->getMethod() . ':' . $this->digestParts['uri']; + $A2 = $this->request->getMethod().':'.$this->digestParts['uri']; - if ($this->digestParts['qop'] == 'auth-int') { + if ('auth-int' === $this->digestParts['qop']) { // Making sure we support this qop value - if (!($this->qop & self::QOP_AUTHINT)) return false; + if (!($this->qop & self::QOP_AUTHINT)) { + return false; + } // We need to add an md5 of the entire request body to the A2 part of the hash $body = $this->request->getBody($asString = true); $this->request->setBody($body); - $A2 .= ':' . md5($body); - } else { - - // We need to make sure we support this qop value - if (!($this->qop & self::QOP_AUTH)) return false; + $A2 .= ':'.md5($body); + } elseif (!($this->qop & self::QOP_AUTH)) { + return false; } $A2 = md5($A2); $validResponse = md5("{$this->A1}:{$this->digestParts['nonce']}:{$this->digestParts['nc']}:{$this->digestParts['cnonce']}:{$this->digestParts['qop']}:{$A2}"); - return $this->digestParts['response'] == $validResponse; - - + return $this->digestParts['response'] === $validResponse; } /** - * Returns an HTTP 401 header, forcing login + * Returns an HTTP 401 header, forcing login. * * This should be called when username and password are incorrect, or not supplied at all - * - * @return void */ - function requireLogin() { - + public function requireLogin() + { $qop = ''; switch ($this->qop) { - case self::QOP_AUTH : + case self::QOP_AUTH: $qop = 'auth'; break; - case self::QOP_AUTHINT : + case self::QOP_AUTHINT: $qop = 'auth-int'; break; - case self::QOP_AUTH | self::QOP_AUTHINT : + case self::QOP_AUTH | self::QOP_AUTHINT: $qop = 'auth,auth-int'; break; } - $this->response->addHeader('WWW-Authenticate', 'Digest realm="' . $this->realm . '",qop="' . $qop . '",nonce="' . $this->nonce . '",opaque="' . $this->opaque . '"'); + $this->response->addHeader('WWW-Authenticate', 'Digest realm="'.$this->realm.'",qop="'.$qop.'",nonce="'.$this->nonce.'",opaque="'.$this->opaque.'"'); $this->response->setStatus(401); - } - /** * This method returns the full digest string. * @@ -196,23 +180,20 @@ class Digest extends AbstractAuth { * * @return mixed */ - function getDigest() { - + public function getDigest() + { return $this->request->getHeader('Authorization'); - } - /** * Parses the different pieces of the digest string into an array. * * This method returns false if an incomplete digest was supplied * - * @param string $digest - * @return mixed + * @return bool|array */ - protected function parseDigest($digest) { - + protected function parseDigest(string $digest) + { // protect against missing data $needed_parts = ['nonce' => 1, 'nc' => 1, 'cnonce' => 1, 'qop' => 1, 'username' => 1, 'uri' => 1, 'response' => 1]; $data = []; @@ -220,12 +201,10 @@ class Digest extends AbstractAuth { preg_match_all('@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@', $digest, $matches, PREG_SET_ORDER); foreach ($matches as $m) { - $data[$m[1]] = $m[2] ? $m[2] : $m[3]; + $data[$m[1]] = $m[2] ?: $m[3]; unset($needed_parts[$m[1]]); } return $needed_parts ? false : $data; - } - } diff --git a/vendor/sabre/http/lib/Client.php b/vendor/sabre/http/lib/Client.php index 0810c4a25..48862e7da 100644 --- a/vendor/sabre/http/lib/Client.php +++ b/vendor/sabre/http/lib/Client.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; use Sabre\Event\EventEmitter; @@ -41,10 +43,10 @@ use Sabre\Uri; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Client extends EventEmitter { - +class Client extends EventEmitter +{ /** - * List of curl settings + * List of curl settings. * * @var array */ @@ -64,53 +66,61 @@ class Client extends EventEmitter { */ protected $maxRedirects = 5; + protected $headerLinesMap = []; + /** * Initializes the client. - * - * @return void */ - function __construct() { + public function __construct() + { + // See https://github.com/sabre-io/http/pull/115#discussion_r241292068 + // Preserve compatibility for sub-classes that implements their own method `parseCurlResult` + $separatedHeaders = __CLASS__ === get_class($this); $this->curlSettings = [ CURLOPT_RETURNTRANSFER => true, - CURLOPT_HEADER => true, - CURLOPT_NOBODY => false, - CURLOPT_USERAGENT => 'sabre-http/' . Version::VERSION . ' (http://sabre.io/)', + CURLOPT_NOBODY => false, + CURLOPT_USERAGENT => 'sabre-http/'.Version::VERSION.' (http://sabre.io/)', ]; + if ($separatedHeaders) { + $this->curlSettings[CURLOPT_HEADERFUNCTION] = [$this, 'receiveCurlHeader']; + } else { + $this->curlSettings[CURLOPT_HEADER] = true; + } + } + + protected function receiveCurlHeader($curlHandle, $headerLine) + { + $this->headerLinesMap[(int) $curlHandle][] = $headerLine; + return strlen($headerLine); } /** * Sends a request to a HTTP server, and returns a response. - * - * @param RequestInterface $request - * @return ResponseInterface */ - function send(RequestInterface $request) { - + public function send(RequestInterface $request): ResponseInterface + { $this->emit('beforeRequest', [$request]); $retryCount = 0; $redirects = 0; do { - $doRedirect = false; $retry = false; try { - $response = $this->doRequest($request); - $code = (int)$response->getStatus(); + $code = $response->getStatus(); // We are doing in-PHP redirects, because curl's // FOLLOW_LOCATION throws errors when PHP is configured with // open_basedir. // // https://github.com/fruux/sabre-http/issues/12 - if (in_array($code, [301, 302, 307, 308]) && $redirects < $this->maxRedirects) { - + if ($redirects < $this->maxRedirects && in_array($code, [301, 302, 307, 308])) { $oldLocation = $request->getUrl(); // Creating a new instance of the request object. @@ -123,20 +133,15 @@ class Client extends EventEmitter { )); $doRedirect = true; - $redirects++; - + ++$redirects; } // This was a HTTP error if ($code >= 400) { - $this->emit('error', [$request, $response, &$retry, $retryCount]); - $this->emit('error:' . $code, [$request, $response, &$retry, $retryCount]); - + $this->emit('error:'.$code, [$request, $response, &$retry, $retryCount]); } - } catch (ClientException $e) { - $this->emit('exception', [$request, $e, &$retry, $retryCount]); // If retry was still set to false, it means no event handler @@ -145,13 +150,11 @@ class Client extends EventEmitter { if (!$retry) { throw $e; } - } if ($retry) { - $retryCount++; + ++$retryCount; } - } while ($retry || $doRedirect); $this->emit('afterRequest', [$request, $response]); @@ -161,7 +164,6 @@ class Client extends EventEmitter { } return $response; - } /** @@ -172,32 +174,23 @@ class Client extends EventEmitter { * * After calling sendAsync, you must therefore occasionally call the poll() * method, or wait(). - * - * @param RequestInterface $request - * @param callable $success - * @param callable $error - * @return void */ - function sendAsync(RequestInterface $request, callable $success = null, callable $error = null) { - + public function sendAsync(RequestInterface $request, callable $success = null, callable $error = null) + { $this->emit('beforeRequest', [$request]); $this->sendAsyncInternal($request, $success, $error); $this->poll(); - } - /** * This method checks if any http requests have gotten results, and if so, * call the appropriate success or error handlers. * * This method will return true if there are still requests waiting to * return, and false if all the work is done. - * - * @return bool */ - function poll() { - + public function poll(): bool + { // nothing to do? if (!$this->curlMultiMap) { return false; @@ -208,10 +201,10 @@ class Client extends EventEmitter { $this->curlMultiHandle, $stillRunning ); - } while ($r === CURLM_CALL_MULTI_PERFORM); + } while (CURLM_CALL_MULTI_PERFORM === $r); + $messagesInQueue = 0; do { - messageQueue: $status = curl_multi_info_read( @@ -219,26 +212,25 @@ class Client extends EventEmitter { $messagesInQueue ); - if ($status && $status['msg'] === CURLMSG_DONE) { - - $resourceId = intval($status['handle']); + if ($status && CURLMSG_DONE === $status['msg']) { + $resourceId = (int) $status['handle']; list( $request, $successCallback, $errorCallback, - $retryCount, - ) = $this->curlMultiMap[$resourceId]; + $retryCount) = $this->curlMultiMap[$resourceId]; unset($this->curlMultiMap[$resourceId]); - $curlResult = $this->parseCurlResult(curl_multi_getcontent($status['handle']), $status['handle']); - $retry = false; - if ($curlResult['status'] === self::STATUS_CURLERROR) { + $curlHandle = $status['handle']; + $curlResult = $this->parseResponse(curl_multi_getcontent($curlHandle), $curlHandle); + $retry = false; + if (self::STATUS_CURLERROR === $curlResult['status']) { $e = new ClientException($curlResult['curl_errmsg'], $curlResult['curl_errno']); $this->emit('exception', [$request, $e, &$retry, $retryCount]); if ($retry) { - $retryCount++; + ++$retryCount; $this->sendAsyncInternal($request, $successCallback, $errorCallback, $retryCount); goto messageQueue; } @@ -248,18 +240,14 @@ class Client extends EventEmitter { if ($errorCallback) { $errorCallback($curlResult); } - - } elseif ($curlResult['status'] === self::STATUS_HTTPERROR) { - + } elseif (self::STATUS_HTTPERROR === $curlResult['status']) { $this->emit('error', [$request, $curlResult['response'], &$retry, $retryCount]); - $this->emit('error:' . $curlResult['http_code'], [$request, $curlResult['response'], &$retry, $retryCount]); + $this->emit('error:'.$curlResult['http_code'], [$request, $curlResult['response'], &$retry, $retryCount]); if ($retry) { - - $retryCount++; + ++$retryCount; $this->sendAsyncInternal($request, $successCallback, $errorCallback, $retryCount); goto messageQueue; - } $curlResult['request'] = $request; @@ -267,37 +255,29 @@ class Client extends EventEmitter { if ($errorCallback) { $errorCallback($curlResult); } - } else { - $this->emit('afterRequest', [$request, $curlResult['response']]); if ($successCallback) { $successCallback($curlResult['response']); } - } } - } while ($messagesInQueue > 0); return count($this->curlMultiMap) > 0; - } /** * Processes every HTTP request in the queue, and waits till they are all * completed. - * - * @return void */ - function wait() { - + public function wait() + { do { curl_multi_select($this->curlMultiHandle); $stillRunning = $this->poll(); } while ($stillRunning); - } /** @@ -309,14 +289,10 @@ class Client extends EventEmitter { * * This only works for the send() method. Throwing exceptions for * sendAsync() is not supported. - * - * @param bool $throwExceptions - * @return void */ - function setThrowExceptions($throwExceptions) { - + public function setThrowExceptions(bool $throwExceptions) + { $this->throwExceptions = $throwExceptions; - } /** @@ -324,40 +300,34 @@ class Client extends EventEmitter { * * These settings will be included in every HTTP request. * - * @param int $name * @param mixed $value - * @return void */ - function addCurlSetting($name, $value) { - + public function addCurlSetting(int $name, $value) + { $this->curlSettings[$name] = $value; - } /** * This method is responsible for performing a single request. - * - * @param RequestInterface $request - * @return ResponseInterface */ - protected function doRequest(RequestInterface $request) { - + protected function doRequest(RequestInterface $request): ResponseInterface + { $settings = $this->createCurlSettingsArray($request); if (!$this->curlHandle) { $this->curlHandle = curl_init(); + } else { + curl_reset($this->curlHandle); } curl_setopt_array($this->curlHandle, $settings); $response = $this->curlExec($this->curlHandle); - $response = $this->parseCurlResult($response, $this->curlHandle); - - if ($response['status'] === self::STATUS_CURLERROR) { + $response = $this->parseResponse($response, $this->curlHandle); + if (self::STATUS_CURLERROR === $response['status']) { throw new ClientException($response['curl_errmsg'], $response['curl_errno']); } return $response['response']; - } /** @@ -389,28 +359,21 @@ class Client extends EventEmitter { /** * Turns a RequestInterface object into an array with settings that can be - * fed to curl_setopt - * - * @param RequestInterface $request - * @return array + * fed to curl_setopt. */ - protected function createCurlSettingsArray(RequestInterface $request) { - + protected function createCurlSettingsArray(RequestInterface $request): array + { $settings = $this->curlSettings; switch ($request->getMethod()) { - case 'HEAD' : + case 'HEAD': $settings[CURLOPT_NOBODY] = true; $settings[CURLOPT_CUSTOMREQUEST] = 'HEAD'; - $settings[CURLOPT_POSTFIELDS] = ''; - $settings[CURLOPT_PUT] = false; break; - case 'GET' : + case 'GET': $settings[CURLOPT_CUSTOMREQUEST] = 'GET'; - $settings[CURLOPT_POSTFIELDS] = ''; - $settings[CURLOPT_PUT] = false; break; - default : + default: $body = $request->getBody(); if (is_resource($body)) { // This needs to be set to PUT, regardless of the actual @@ -422,20 +385,17 @@ class Client extends EventEmitter { // For security we cast this to a string. If somehow an array could // be passed here, it would be possible for an attacker to use @ to // post local files. - $settings[CURLOPT_POSTFIELDS] = (string)$body; + $settings[CURLOPT_POSTFIELDS] = (string) $body; } $settings[CURLOPT_CUSTOMREQUEST] = $request->getMethod(); break; - } $nHeaders = []; foreach ($request->getHeaders() as $key => $values) { - foreach ($values as $value) { - $nHeaders[] = $key . ': ' . $value; + $nHeaders[] = $key.': '.$value; } - } $settings[CURLOPT_HTTPHEADER] = $nHeaders; $settings[CURLOPT_URL] = $request->getUrl(); @@ -449,13 +409,32 @@ class Client extends EventEmitter { } return $settings; - } const STATUS_SUCCESS = 0; const STATUS_CURLERROR = 1; const STATUS_HTTPERROR = 2; + private function parseResponse(string $response, $curlHandle): array + { + $settings = $this->curlSettings; + $separatedHeaders = isset($settings[CURLOPT_HEADERFUNCTION]) && (bool) $settings[CURLOPT_HEADERFUNCTION]; + + if ($separatedHeaders) { + $resourceId = (int) $curlHandle; + if (isset($this->headerLinesMap[$resourceId])) { + $headers = $this->headerLinesMap[$resourceId]; + } else { + $headers = []; + } + $response = $this->parseCurlResponse($headers, $response, $curlHandle); + } else { + $response = $this->parseCurlResult($response, $curlHandle); + } + + return $response; + } + /** * Parses the result of a curl call in a format that's a bit more * convenient to work with. @@ -471,12 +450,67 @@ class Client extends EventEmitter { * * http_code - HTTP status code, as an int. Only set if Only set if * status is STATUS_SUCCESS, or STATUS_HTTPERROR * - * @param string $response + * @param array $headerLines + * @param string $body * @param resource $curlHandle - * @return Response */ - protected function parseCurlResult($response, $curlHandle) { + protected function parseCurlResponse(array $headerLines, string $body, $curlHandle): array + { + list( + $curlInfo, + $curlErrNo, + $curlErrMsg + ) = $this->curlStuff($curlHandle); + if ($curlErrNo) { + return [ + 'status' => self::STATUS_CURLERROR, + 'curl_errno' => $curlErrNo, + 'curl_errmsg' => $curlErrMsg, + ]; + } + + $response = new Response(); + $response->setStatus($curlInfo['http_code']); + $response->setBody($body); + + foreach ($headerLines as $header) { + $parts = explode(':', $header, 2); + if (2 === count($parts)) { + $response->addHeader(trim($parts[0]), trim($parts[1])); + } + } + + $httpCode = $response->getStatus(); + + return [ + 'status' => $httpCode >= 400 ? self::STATUS_HTTPERROR : self::STATUS_SUCCESS, + 'response' => $response, + 'http_code' => $httpCode, + ]; + } + + /** + * Parses the result of a curl call in a format that's a bit more + * convenient to work with. + * + * The method returns an array with the following elements: + * * status - one of the 3 STATUS constants. + * * curl_errno - A curl error number. Only set if status is + * STATUS_CURLERROR. + * * curl_errmsg - A current error message. Only set if status is + * STATUS_CURLERROR. + * * response - Response object. Only set if status is STATUS_SUCCESS, or + * STATUS_HTTPERROR. + * * http_code - HTTP status code, as an int. Only set if Only set if + * status is STATUS_SUCCESS, or STATUS_HTTPERROR + * + * @deprecated Use parseCurlResponse instead + * + * @param resource $curlHandle + */ + protected function parseCurlResult(string $response, $curlHandle): array + { list( $curlInfo, $curlErrNo, @@ -485,8 +519,8 @@ class Client extends EventEmitter { if ($curlErrNo) { return [ - 'status' => self::STATUS_CURLERROR, - 'curl_errno' => $curlErrNo, + 'status' => self::STATUS_CURLERROR, + 'curl_errno' => $curlErrNo, 'curl_errmsg' => $curlErrMsg, ]; } @@ -495,7 +529,7 @@ class Client extends EventEmitter { // In the case of 204 No Content, strlen($response) == $curlInfo['header_size]. // This will cause substr($response, $curlInfo['header_size']) return FALSE instead of NULL // An exception will be thrown when calling getBodyAsString then - $responseBody = substr($response, $curlInfo['header_size']) ?: null; + $responseBody = substr($response, $curlInfo['header_size']) ?: ''; unset($response); @@ -510,26 +544,7 @@ class Client extends EventEmitter { // Splitting headers $headerBlob = explode("\r\n", $headerBlob); - $response = new Response(); - $response->setStatus($curlInfo['http_code']); - - foreach ($headerBlob as $header) { - $parts = explode(':', $header, 2); - if (count($parts) == 2) { - $response->addHeader(trim($parts[0]), trim($parts[1])); - } - } - - $response->setBody($responseBody); - - $httpCode = intval($response->getStatus()); - - return [ - 'status' => $httpCode >= 400 ? self::STATUS_HTTPERROR : self::STATUS_SUCCESS, - 'response' => $response, - 'http_code' => $httpCode, - ]; - + return $this->parseCurlResponse($headerBlob, $responseBody, $curlHandle); } /** @@ -537,14 +552,9 @@ class Client extends EventEmitter { * * We keep this in a separate method, so we can call it without triggering * the beforeRequest event and don't do the poll(). - * - * @param RequestInterface $request - * @param callable $success - * @param callable $error - * @param int $retryCount */ - protected function sendAsyncInternal(RequestInterface $request, callable $success, callable $error, $retryCount = 0) { - + protected function sendAsyncInternal(RequestInterface $request, callable $success, callable $error, int $retryCount = 0) + { if (!$this->curlMultiHandle) { $this->curlMultiHandle = curl_multi_init(); } @@ -554,29 +564,36 @@ class Client extends EventEmitter { $this->createCurlSettingsArray($request) ); curl_multi_add_handle($this->curlMultiHandle, $curl); - $this->curlMultiMap[intval($curl)] = [ + + $resourceId = (int) $curl; + $this->headerLinesMap[$resourceId] = []; + $this->curlMultiMap[$resourceId] = [ $request, $success, $error, - $retryCount + $retryCount, ]; - } // @codeCoverageIgnoreStart /** - * Calls curl_exec + * Calls curl_exec. * * This method exists so it can easily be overridden and mocked. * * @param resource $curlHandle - * @return string */ - protected function curlExec($curlHandle) { + protected function curlExec($curlHandle): string + { + $this->headerLinesMap[(int) $curlHandle] = []; - return curl_exec($curlHandle); + $result = curl_exec($curlHandle); + if (false === $result) { + $result = ''; + } + return $result; } /** @@ -585,17 +602,15 @@ class Client extends EventEmitter { * This method exists so it can easily be overridden and mocked. * * @param resource $curlHandle - * @return array */ - protected function curlStuff($curlHandle) { - + protected function curlStuff($curlHandle): array + { return [ curl_getinfo($curlHandle), curl_errno($curlHandle), curl_error($curlHandle), ]; - } - // @codeCoverageIgnoreEnd + // @codeCoverageIgnoreEnd } diff --git a/vendor/sabre/http/lib/ClientException.php b/vendor/sabre/http/lib/ClientException.php index 69631f44e..2ca4a28e0 100644 --- a/vendor/sabre/http/lib/ClientException.php +++ b/vendor/sabre/http/lib/ClientException.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -10,6 +12,6 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class ClientException extends \Exception { - +class ClientException extends \Exception +{ } diff --git a/vendor/sabre/http/lib/ClientHttpException.php b/vendor/sabre/http/lib/ClientHttpException.php index 2923ef3b5..116ca1f79 100644 --- a/vendor/sabre/http/lib/ClientHttpException.php +++ b/vendor/sabre/http/lib/ClientHttpException.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -12,47 +14,37 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class ClientHttpException extends \Exception implements HttpException { - +class ClientHttpException extends \Exception implements HttpException +{ /** - * Response object + * Response object. * * @var ResponseInterface */ protected $response; /** - * Constructor - * - * @param ResponseInterface $response + * Constructor. */ - function __construct(ResponseInterface $response) { - + public function __construct(ResponseInterface $response) + { $this->response = $response; parent::__construct($response->getStatusText(), $response->getStatus()); - } /** * The http status code for the error. - * - * @return int */ - function getHttpStatus() { - + public function getHttpStatus(): int + { return $this->response->getStatus(); - } /** * Returns the full response object. - * - * @return ResponseInterface */ - function getResponse() { - + public function getResponse(): ResponseInterface + { return $this->response; - } - } diff --git a/vendor/sabre/http/lib/HttpException.php b/vendor/sabre/http/lib/HttpException.php index 1303dec97..80b3ae665 100644 --- a/vendor/sabre/http/lib/HttpException.php +++ b/vendor/sabre/http/lib/HttpException.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -15,8 +17,8 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -interface HttpException { - +interface HttpException +{ /** * The http status code for the error. * @@ -25,6 +27,5 @@ interface HttpException { * * @return string|null */ - function getHttpStatus(); - + public function getHttpStatus(); } diff --git a/vendor/sabre/http/lib/Message.php b/vendor/sabre/http/lib/Message.php index 45bd18398..fc34f8d7f 100644 --- a/vendor/sabre/http/lib/Message.php +++ b/vendor/sabre/http/lib/Message.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -11,26 +13,26 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -abstract class Message implements MessageInterface { - +abstract class Message implements MessageInterface +{ /** - * Request body + * Request body. * - * This should be a stream resource + * This should be a stream resource, string or a callback writing the body to php://output * - * @var resource + * @var resource|string|callable */ protected $body; /** - * Contains the list of HTTP headers + * Contains the list of HTTP headers. * * @var array */ protected $headers = []; /** - * HTTP message version (1.0 or 1.1) + * HTTP message version (1.0, 1.1 or 2.0). * * @var string */ @@ -44,17 +46,21 @@ abstract class Message implements MessageInterface { * * @return resource */ - function getBodyAsStream() { - + public function getBodyAsStream() + { $body = $this->getBody(); - if (is_string($body) || is_null($body)) { + if (is_callable($this->body)) { + $body = $this->getBodyAsString(); + } + if (is_string($body) || null === $body) { $stream = fopen('php://temp', 'r+'); - fwrite($stream, $body); + fwrite($stream, (string) $body); rewind($stream); + return $stream; } - return $body; + return $body; } /** @@ -62,77 +68,76 @@ abstract class Message implements MessageInterface { * * Note that because the underlying data may be based on a stream, this * method could only work correctly the first time. - * - * @return string */ - function getBodyAsString() { - + public function getBodyAsString(): string + { $body = $this->getBody(); if (is_string($body)) { return $body; } - if (is_null($body)) { + if (null === $body) { return ''; } + if (is_callable($body)) { + ob_start(); + $body(); + + return ob_get_clean(); + } + /** + * @var string|int|null + */ $contentLength = $this->getHeader('Content-Length'); if (is_int($contentLength) || ctype_digit($contentLength)) { - return stream_get_contents($body, $contentLength); - } else { - return stream_get_contents($body); + return stream_get_contents($body, (int) $contentLength); } + + return stream_get_contents($body); } /** * Returns the message body, as it's internal representation. * - * This could be either a string or a stream. + * This could be either a string, a stream or a callback writing the body to php://output. * - * @return resource|string + * @return resource|string|callable */ - function getBody() { - + public function getBody() + { return $this->body; - } /** - * Replaces the body resource with a new stream or string. + * Replaces the body resource with a new stream, string or a callback writing the body to php://output. * - * @param resource|string $body + * @param resource|string|callable $body */ - function setBody($body) { - + public function setBody($body) + { $this->body = $body; - } /** * Returns all the HTTP headers as an array. * * Every header is returned as an array, with one or more values. - * - * @return array */ - function getHeaders() { - + public function getHeaders(): array + { $result = []; foreach ($this->headers as $headerInfo) { $result[$headerInfo[0]] = $headerInfo[1]; } - return $result; + return $result; } /** * Will return true or false, depending on if a HTTP header exists. - * - * @param string $name - * @return bool */ - function hasHeader($name) { - + public function hasHeader(string $name): bool + { return isset($this->headers[strtolower($name)]); - } /** @@ -148,18 +153,17 @@ abstract class Message implements MessageInterface { * `Set-Cookie` cannot be logically combined with a comma. In those cases * you *should* use getHeaderAsArray(). * - * @param string $name * @return string|null */ - function getHeader($name) { - + public function getHeader(string $name) + { $name = strtolower($name); if (isset($this->headers[$name])) { return implode(',', $this->headers[$name][1]); } - return null; + return null; } /** @@ -170,11 +174,10 @@ abstract class Message implements MessageInterface { * * If the header did not exists, this method will return an empty array. * - * @param string $name * @return string[] */ - function getHeaderAsArray($name) { - + public function getHeaderAsArray(string $name): array + { $name = strtolower($name); if (isset($this->headers[$name])) { @@ -182,7 +185,6 @@ abstract class Message implements MessageInterface { } return []; - } /** @@ -192,14 +194,11 @@ abstract class Message implements MessageInterface { * * If the header already existed, it will be overwritten. * - * @param string $name * @param string|string[] $value - * @return void */ - function setHeader($name, $value) { - - $this->headers[strtolower($name)] = [$name, (array)$value]; - + public function setHeader(string $name, $value) + { + $this->headers[strtolower($name)] = [$name, (array) $value]; } /** @@ -209,16 +208,12 @@ abstract class Message implements MessageInterface { * should be specified as either a string or an array. * * Any header that already existed will be overwritten. - * - * @param array $headers - * @return void */ - function setHeaders(array $headers) { - + public function setHeaders(array $headers) + { foreach ($headers as $name => $value) { $this->setHeader($name, $value); } - } /** @@ -228,77 +223,62 @@ abstract class Message implements MessageInterface { * another value. Individual values can be retrieved with * getHeadersAsArray. * - * @param string $name - * @param string $value - * @return void + * @param string|string[] $value */ - function addHeader($name, $value) { - + public function addHeader(string $name, $value) + { $lName = strtolower($name); if (isset($this->headers[$lName])) { $this->headers[$lName][1] = array_merge( $this->headers[$lName][1], - (array)$value + (array) $value ); } else { $this->headers[$lName] = [ $name, - (array)$value + (array) $value, ]; } - } /** * Adds a new set of HTTP headers. * * Any existing headers will not be overwritten. - * - * @param array $headers - * @return void */ - function addHeaders(array $headers) { - + public function addHeaders(array $headers) + { foreach ($headers as $name => $value) { $this->addHeader($name, $value); } - } - /** * Removes a HTTP header. * * The specified header name must be treated as case-insensitive. * This method should return true if the header was successfully deleted, * and false if the header did not exist. - * - * @param string $name - * @return bool */ - function removeHeader($name) { - + public function removeHeader(string $name): bool + { $name = strtolower($name); if (!isset($this->headers[$name])) { return false; } unset($this->headers[$name]); - return true; + return true; } /** * Sets the HTTP version. * - * Should be 1.0 or 1.1. - * - * @param string $version - * @return void + * Should be 1.0, 1.1 or 2.0. */ - function setHttpVersion($version) { - + public function setHttpVersion(string $version) + { $this->httpVersion = $version; - } /** @@ -306,9 +286,8 @@ abstract class Message implements MessageInterface { * * @return string */ - function getHttpVersion() { - + public function getHttpVersion(): string + { return $this->httpVersion; - } } diff --git a/vendor/sabre/http/lib/MessageDecoratorTrait.php b/vendor/sabre/http/lib/MessageDecoratorTrait.php index 1cb32da22..d5504ac78 100644 --- a/vendor/sabre/http/lib/MessageDecoratorTrait.php +++ b/vendor/sabre/http/lib/MessageDecoratorTrait.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -13,8 +15,8 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -trait MessageDecoratorTrait { - +trait MessageDecoratorTrait +{ /** * The inner request object. * @@ -32,10 +34,9 @@ trait MessageDecoratorTrait { * * @return resource */ - function getBodyAsStream() { - + public function getBodyAsStream() + { return $this->inner->getBodyAsStream(); - } /** @@ -43,13 +44,10 @@ trait MessageDecoratorTrait { * * Note that because the underlying data may be based on a stream, this * method could only work correctly the first time. - * - * @return string */ - function getBodyAsString() { - + public function getBodyAsString(): string + { return $this->inner->getBodyAsString(); - } /** @@ -59,47 +57,37 @@ trait MessageDecoratorTrait { * * @return resource|string */ - function getBody() { - + public function getBody() + { return $this->inner->getBody(); - } /** * Updates the body resource with a new stream. * - * @param resource $body - * @return void + * @param resource|string|callable $body */ - function setBody($body) { - + public function setBody($body) + { $this->inner->setBody($body); - } /** * Returns all the HTTP headers as an array. * * Every header is returned as an array, with one or more values. - * - * @return array */ - function getHeaders() { - + public function getHeaders(): array + { return $this->inner->getHeaders(); - } /** * Will return true or false, depending on if a HTTP header exists. - * - * @param string $name - * @return bool */ - function hasHeader($name) { - + public function hasHeader(string $name): bool + { return $this->inner->hasHeader($name); - } /** @@ -115,13 +103,11 @@ trait MessageDecoratorTrait { * `Set-Cookie` cannot be logically combined with a comma. In those cases * you *should* use getHeaderAsArray(). * - * @param string $name * @return string|null */ - function getHeader($name) { - + public function getHeader(string $name) + { return $this->inner->getHeader($name); - } /** @@ -131,14 +117,10 @@ trait MessageDecoratorTrait { * item will appear in the array. * * If the header did not exists, this method will return an empty array. - * - * @param string $name - * @return string[] */ - function getHeaderAsArray($name) { - + public function getHeaderAsArray(string $name): array + { return $this->inner->getHeaderAsArray($name); - } /** @@ -148,14 +130,11 @@ trait MessageDecoratorTrait { * * If the header already existed, it will be overwritten. * - * @param string $name * @param string|string[] $value - * @return void */ - function setHeader($name, $value) { - + public function setHeader(string $name, $value) + { $this->inner->setHeader($name, $value); - } /** @@ -165,14 +144,10 @@ trait MessageDecoratorTrait { * should be specified as either a string or an array. * * Any header that already existed will be overwritten. - * - * @param array $headers - * @return void */ - function setHeaders(array $headers) { - + public function setHeaders(array $headers) + { $this->inner->setHeaders($headers); - } /** @@ -182,31 +157,23 @@ trait MessageDecoratorTrait { * another value. Individual values can be retrieved with * getHeadersAsArray. * - * @param string $name - * @param string $value - * @return void + * @param string|string[] $value */ - function addHeader($name, $value) { - + public function addHeader(string $name, $value) + { $this->inner->addHeader($name, $value); - } /** * Adds a new set of HTTP headers. * * Any existing headers will not be overwritten. - * - * @param array $headers - * @return void */ - function addHeaders(array $headers) { - + public function addHeaders(array $headers) + { $this->inner->addHeaders($headers); - } - /** * Removes a HTTP header. * @@ -214,38 +181,28 @@ trait MessageDecoratorTrait { * This method should return true if the header was successfully deleted, * and false if the header did not exist. * - * @param string $name * @return bool */ - function removeHeader($name) { - + public function removeHeader(string $name): bool + { return $this->inner->removeHeader($name); - } /** * Sets the HTTP version. * - * Should be 1.0 or 1.1. - * - * @param string $version - * @return void + * Should be 1.0, 1.1 or 2.0. */ - function setHttpVersion($version) { - + public function setHttpVersion(string $version) + { $this->inner->setHttpVersion($version); - } /** * Returns the HTTP version. - * - * @return string */ - function getHttpVersion() { - + public function getHttpVersion(): string + { return $this->inner->getHttpVersion(); - } - } diff --git a/vendor/sabre/http/lib/MessageInterface.php b/vendor/sabre/http/lib/MessageInterface.php index df55beb2f..8070845d9 100644 --- a/vendor/sabre/http/lib/MessageInterface.php +++ b/vendor/sabre/http/lib/MessageInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -10,8 +12,8 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -interface MessageInterface { - +interface MessageInterface +{ /** * Returns the body as a readable stream resource. * @@ -20,7 +22,7 @@ interface MessageInterface { * * @return resource */ - function getBodyAsStream(); + public function getBodyAsStream(); /** * Returns the body as a string. @@ -30,41 +32,35 @@ interface MessageInterface { * * @return string */ - function getBodyAsString(); + public function getBodyAsString(): string; /** * Returns the message body, as it's internal representation. * - * This could be either a string or a stream. + * This could be either a string, a stream or a callback writing the body to php://output * - * @return resource|string + * @return resource|string|callable */ - function getBody(); + public function getBody(); /** * Updates the body resource with a new stream. * - * @param resource|string $body - * @return void + * @param resource|string|callable $body */ - function setBody($body); + public function setBody($body); /** * Returns all the HTTP headers as an array. * * Every header is returned as an array, with one or more values. - * - * @return array */ - function getHeaders(); + public function getHeaders(): array; /** * Will return true or false, depending on if a HTTP header exists. - * - * @param string $name - * @return bool */ - function hasHeader($name); + public function hasHeader(string $name): bool; /** * Returns a specific HTTP header, based on it's name. @@ -79,10 +75,9 @@ interface MessageInterface { * `Set-Cookie` cannot be logically combined with a comma. In those cases * you *should* use getHeaderAsArray(). * - * @param string $name * @return string|null */ - function getHeader($name); + public function getHeader(string $name); /** * Returns a HTTP header as an array. @@ -92,10 +87,9 @@ interface MessageInterface { * * If the header did not exists, this method will return an empty array. * - * @param string $name * @return string[] */ - function getHeaderAsArray($name); + public function getHeaderAsArray(string $name): array; /** * Updates a HTTP header. @@ -104,11 +98,9 @@ interface MessageInterface { * * If the header already existed, it will be overwritten. * - * @param string $name * @param string|string[] $value - * @return void */ - function setHeader($name, $value); + public function setHeader(string $name, $value); /** * Sets a new set of HTTP headers. @@ -117,11 +109,8 @@ interface MessageInterface { * should be specified as either a string or an array. * * Any header that already existed will be overwritten. - * - * @param array $headers - * @return void */ - function setHeaders(array $headers); + public function setHeaders(array $headers); /** * Adds a HTTP header. @@ -130,21 +119,16 @@ interface MessageInterface { * another value. Individual values can be retrieved with * getHeadersAsArray. * - * @param string $name - * @param string $value - * @return void + * @param string|string[] $value */ - function addHeader($name, $value); + public function addHeader(string $name, $value); /** * Adds a new set of HTTP headers. * * Any existing headers will not be overwritten. - * - * @param array $headers - * @return void */ - function addHeaders(array $headers); + public function addHeaders(array $headers); /** * Removes a HTTP header. @@ -152,27 +136,18 @@ interface MessageInterface { * The specified header name must be treated as case-insenstive. * This method should return true if the header was successfully deleted, * and false if the header did not exist. - * - * @param string $name - * @return bool */ - function removeHeader($name); + public function removeHeader(string $name): bool; /** * Sets the HTTP version. * - * Should be 1.0 or 1.1. - * - * @param string $version - * @return void + * Should be 1.0, 1.1 or 2.0. */ - function setHttpVersion($version); + public function setHttpVersion(string $version); /** * Returns the HTTP version. - * - * @return string */ - function getHttpVersion(); - + public function getHttpVersion(): string; } diff --git a/vendor/sabre/http/lib/Request.php b/vendor/sabre/http/lib/Request.php index dfa3d5b48..496629a5b 100644 --- a/vendor/sabre/http/lib/Request.php +++ b/vendor/sabre/http/lib/Request.php @@ -1,8 +1,10 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; -use InvalidArgumentException; +use LogicException; use Sabre\Uri; /** @@ -15,132 +17,111 @@ use Sabre\Uri; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Request extends Message implements RequestInterface { - +class Request extends Message implements RequestInterface +{ /** - * HTTP Method + * HTTP Method. * * @var string */ protected $method; /** - * Request Url + * Request Url. * * @var string */ protected $url; /** - * Creates the request object + * Creates the request object. * - * @param string $method - * @param string $url - * @param array $headers - * @param resource $body + * @param resource|callable|string $body */ - function __construct($method = null, $url = null, array $headers = null, $body = null) { - - if (is_array($method)) { - throw new InvalidArgumentException('The first argument for this constructor should be a string or null, not an array. Did you upgrade from sabre/http 1.0 to 2.0?'); - } - if (!is_null($method)) $this->setMethod($method); - if (!is_null($url)) $this->setUrl($url); - if (!is_null($headers)) $this->setHeaders($headers); - if (!is_null($body)) $this->setBody($body); - + public function __construct(string $method, string $url, array $headers = [], $body = null) + { + $this->setMethod($method); + $this->setUrl($url); + $this->setHeaders($headers); + $this->setBody($body); } /** - * Returns the current HTTP method - * - * @return string + * Returns the current HTTP method. */ - function getMethod() { - + public function getMethod(): string + { return $this->method; - } /** - * Sets the HTTP method - * - * @param string $method - * @return void + * Sets the HTTP method. */ - function setMethod($method) { - + public function setMethod(string $method) + { $this->method = $method; - } /** * Returns the request url. - * - * @return string */ - function getUrl() { - + public function getUrl(): string + { return $this->url; - } /** * Sets the request url. - * - * @param string $url - * @return void */ - function setUrl($url) { - + public function setUrl(string $url) + { $this->url = $url; - } /** * Returns the list of query parameters. * * This is equivalent to PHP's $_GET superglobal. - * - * @return array */ - function getQueryParameters() { - + public function getQueryParameters(): array + { $url = $this->getUrl(); - if (($index = strpos($url, '?')) === false) { + if (false === ($index = strpos($url, '?'))) { return []; - } else { - parse_str(substr($url, $index + 1), $queryParams); - return $queryParams; } + parse_str(substr($url, $index + 1), $queryParams); + + return $queryParams; } + protected $absoluteUrl; + /** * Sets the absolute url. - * - * @param string $url - * @return void */ - function setAbsoluteUrl($url) { - + public function setAbsoluteUrl(string $url) + { $this->absoluteUrl = $url; - } /** * Returns the absolute url. - * - * @return string */ - function getAbsoluteUrl() { + public function getAbsoluteUrl(): string + { + if (!$this->absoluteUrl) { + // Guessing we're a http endpoint. + $this->absoluteUrl = 'http://'. + ($this->getHeader('Host') ?? 'localhost'). + $this->getUrl(); + } return $this->absoluteUrl; - } /** - * Base url + * Base url. * * @var string */ @@ -150,25 +131,18 @@ class Request extends Message implements RequestInterface { * Sets a base url. * * This url is used for relative path calculations. - * - * @param string $url - * @return void */ - function setBaseUrl($url) { - + public function setBaseUrl(string $url) + { $this->baseUrl = $url; - } /** * Returns the current base url. - * - * @return string */ - function getBaseUrl() { - + public function getBaseUrl(): string + { return $this->baseUrl; - } /** @@ -185,33 +159,29 @@ class Request extends Message implements RequestInterface { * ISO-8859-1, it will convert it to UTF-8. * * If the path is outside of the base url, a LogicException will be thrown. - * - * @return string */ - function getPath() { - + public function getPath(): string + { // Removing duplicated slashes. $uri = str_replace('//', '/', $this->getUrl()); $uri = Uri\normalize($uri); $baseUri = Uri\normalize($this->getBaseUrl()); - if (strpos($uri, $baseUri) === 0) { - + if (0 === strpos($uri, $baseUri)) { // We're not interested in the query part (everything after the ?). list($uri) = explode('?', $uri); - return trim(URLUtil::decodePath(substr($uri, strlen($baseUri))), '/'); + return trim(decodePath(substr($uri, strlen($baseUri))), '/'); } - // A special case, if the baseUri was accessed without a trailing - // slash, we'll accept it as well. - elseif ($uri . '/' === $baseUri) { + if ($uri.'/' === $baseUri) { return ''; - } + // A special case, if the baseUri was accessed without a trailing + // slash, we'll accept it as well. - throw new \LogicException('Requested uri (' . $this->getUrl() . ') is out of base uri (' . $this->getBaseUrl() . ')'); + throw new \LogicException('Requested uri ('.$this->getUrl().') is out of base uri ('.$this->getBaseUrl().')'); } /** @@ -228,27 +198,20 @@ class Request extends Message implements RequestInterface { * * This would not have been needed, if POST data was accessible as * php://input, but unfortunately we need to special case it. - * - * @param array $postData - * @return void */ - function setPostData(array $postData) { - + public function setPostData(array $postData) + { $this->postData = $postData; - } /** * Returns the POST data. * * This is equivalent to PHP's $_POST superglobal. - * - * @return array */ - function getPostData() { - + public function getPostData(): array + { return $this->postData; - } /** @@ -263,54 +226,42 @@ class Request extends Message implements RequestInterface { * * If the value does not exist in the array, null is returned. * - * @param string $valueName * @return string|null */ - function getRawServerValue($valueName) { - - if (isset($this->rawServerData[$valueName])) { - return $this->rawServerData[$valueName]; - } - + public function getRawServerValue(string $valueName) + { + return $this->rawServerData[$valueName] ?? null; } /** * Sets the _SERVER array. - * - * @param array $data - * @return void */ - function setRawServerData(array $data) { - + public function setRawServerData(array $data) + { $this->rawServerData = $data; - } /** * Serializes the request object as a string. * * This is useful for debugging purposes. - * - * @return string */ - function __toString() { - - $out = $this->getMethod() . ' ' . $this->getUrl() . ' HTTP/' . $this->getHTTPVersion() . "\r\n"; + public function __toString(): string + { + $out = $this->getMethod().' '.$this->getUrl().' HTTP/'.$this->getHttpVersion()."\r\n"; foreach ($this->getHeaders() as $key => $value) { foreach ($value as $v) { - if ($key === 'Authorization') { + if ('Authorization' === $key) { list($v) = explode(' ', $v, 2); $v .= ' REDACTED'; } - $out .= $key . ": " . $v . "\r\n"; + $out .= $key.': '.$v."\r\n"; } } $out .= "\r\n"; $out .= $this->getBodyAsString(); return $out; - } - } diff --git a/vendor/sabre/http/lib/RequestDecorator.php b/vendor/sabre/http/lib/RequestDecorator.php index 7ee3f6fc8..0ad24925f 100644 --- a/vendor/sabre/http/lib/RequestDecorator.php +++ b/vendor/sabre/http/lib/RequestDecorator.php @@ -1,9 +1,11 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** - * Request Decorator + * Request Decorator. * * This helper class allows you to easily create decorators for the Request * object. @@ -12,99 +14,72 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class RequestDecorator implements RequestInterface { - +class RequestDecorator implements RequestInterface +{ use MessageDecoratorTrait; /** * Constructor. - * - * @param RequestInterface $inner */ - function __construct(RequestInterface $inner) { - + public function __construct(RequestInterface $inner) + { $this->inner = $inner; - } /** - * Returns the current HTTP method - * - * @return string + * Returns the current HTTP method. */ - function getMethod() { - + public function getMethod(): string + { return $this->inner->getMethod(); - } /** - * Sets the HTTP method - * - * @param string $method - * @return void + * Sets the HTTP method. */ - function setMethod($method) { - + public function setMethod(string $method) + { $this->inner->setMethod($method); - } /** * Returns the request url. - * - * @return string */ - function getUrl() { - + public function getUrl(): string + { return $this->inner->getUrl(); - } /** * Sets the request url. - * - * @param string $url - * @return void */ - function setUrl($url) { - + public function setUrl(string $url) + { $this->inner->setUrl($url); - } /** * Returns the absolute url. - * - * @return string */ - function getAbsoluteUrl() { - + public function getAbsoluteUrl(): string + { return $this->inner->getAbsoluteUrl(); - } /** * Sets the absolute url. - * - * @param string $url - * @return void */ - function setAbsoluteUrl($url) { - + public function setAbsoluteUrl(string $url) + { $this->inner->setAbsoluteUrl($url); - } /** * Returns the current base url. - * - * @return string */ - function getBaseUrl() { - + public function getBaseUrl(): string + { return $this->inner->getBaseUrl(); - } /** @@ -113,14 +88,10 @@ class RequestDecorator implements RequestInterface { * This url is used for relative path calculations. * * The base url should default to / - * - * @param string $url - * @return void */ - function setBaseUrl($url) { - + public function setBaseUrl(string $url) + { $this->inner->setBaseUrl($url); - } /** @@ -137,39 +108,30 @@ class RequestDecorator implements RequestInterface { * ISO-8859-1, it will convert it to UTF-8. * * If the path is outside of the base url, a LogicException will be thrown. - * - * @return string */ - function getPath() { - + public function getPath(): string + { return $this->inner->getPath(); - } /** * Returns the list of query parameters. * * This is equivalent to PHP's $_GET superglobal. - * - * @return array */ - function getQueryParameters() { - + public function getQueryParameters(): array + { return $this->inner->getQueryParameters(); - } /** * Returns the POST data. * * This is equivalent to PHP's $_POST superglobal. - * - * @return array */ - function getPostData() { - + public function getPostData(): array + { return $this->inner->getPostData(); - } /** @@ -179,53 +141,39 @@ class RequestDecorator implements RequestInterface { * * This would not have been needed, if POST data was accessible as * php://input, but unfortunately we need to special case it. - * - * @param array $postData - * @return void */ - function setPostData(array $postData) { - + public function setPostData(array $postData) + { $this->inner->setPostData($postData); - } - /** * Returns an item from the _SERVER array. * * If the value does not exist in the array, null is returned. * - * @param string $valueName * @return string|null */ - function getRawServerValue($valueName) { - + public function getRawServerValue(string $valueName) + { return $this->inner->getRawServerValue($valueName); - } /** * Sets the _SERVER array. - * - * @param array $data - * @return void */ - function setRawServerData(array $data) { - + public function setRawServerData(array $data) + { $this->inner->setRawServerData($data); - } /** * Serializes the request object as a string. * * This is useful for debugging purposes. - * - * @return string */ - function __toString() { - + public function __toString(): string + { return $this->inner->__toString(); - } } diff --git a/vendor/sabre/http/lib/RequestInterface.php b/vendor/sabre/http/lib/RequestInterface.php index 63d9cbb51..83fa85bdc 100644 --- a/vendor/sabre/http/lib/RequestInterface.php +++ b/vendor/sabre/http/lib/RequestInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -9,59 +11,42 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -interface RequestInterface extends MessageInterface { - +interface RequestInterface extends MessageInterface +{ /** - * Returns the current HTTP method - * - * @return string + * Returns the current HTTP method. */ - function getMethod(); + public function getMethod(): string; /** - * Sets the HTTP method - * - * @param string $method - * @return void + * Sets the HTTP method. */ - function setMethod($method); + public function setMethod(string $method); /** * Returns the request url. - * - * @return string */ - function getUrl(); + public function getUrl(): string; /** * Sets the request url. - * - * @param string $url - * @return void */ - function setUrl($url); + public function setUrl(string $url); /** * Returns the absolute url. - * - * @return string */ - function getAbsoluteUrl(); + public function getAbsoluteUrl(): string; /** * Sets the absolute url. - * - * @param string $url - * @return void */ - function setAbsoluteUrl($url); + public function setAbsoluteUrl(string $url); /** * Returns the current base url. - * - * @return string */ - function getBaseUrl(); + public function getBaseUrl(): string; /** * Sets a base url. @@ -69,11 +54,8 @@ interface RequestInterface extends MessageInterface { * This url is used for relative path calculations. * * The base url should default to / - * - * @param string $url - * @return void */ - function setBaseUrl($url); + public function setBaseUrl(string $url); /** * Returns the relative path. @@ -89,28 +71,22 @@ interface RequestInterface extends MessageInterface { * ISO-8859-1, it will convert it to UTF-8. * * If the path is outside of the base url, a LogicException will be thrown. - * - * @return string */ - function getPath(); + public function getPath(): string; /** * Returns the list of query parameters. * * This is equivalent to PHP's $_GET superglobal. - * - * @return array */ - function getQueryParameters(); + public function getQueryParameters(): array; /** * Returns the POST data. * * This is equivalent to PHP's $_POST superglobal. - * - * @return array */ - function getPostData(); + public function getPostData(): array; /** * Sets the post data. @@ -119,29 +95,20 @@ interface RequestInterface extends MessageInterface { * * This would not have been needed, if POST data was accessible as * php://input, but unfortunately we need to special case it. - * - * @param array $postData - * @return void */ - function setPostData(array $postData); + public function setPostData(array $postData); /** * Returns an item from the _SERVER array. * * If the value does not exist in the array, null is returned. * - * @param string $valueName * @return string|null */ - function getRawServerValue($valueName); + public function getRawServerValue(string $valueName); /** * Sets the _SERVER array. - * - * @param array $data - * @return void */ - function setRawServerData(array $data); - - + public function setRawServerData(array $data); } diff --git a/vendor/sabre/http/lib/Response.php b/vendor/sabre/http/lib/Response.php index 01920d8d9..64dfbc0b2 100644 --- a/vendor/sabre/http/lib/Response.php +++ b/vendor/sabre/http/lib/Response.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -9,14 +11,14 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Response extends Message implements ResponseInterface { - +class Response extends Message implements ResponseInterface +{ /** * This is the list of currently registered HTTP status codes. * * @var array */ - static $statusCodes = [ + public static $statusCodes = [ 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', @@ -81,57 +83,55 @@ class Response extends Message implements ResponseInterface { ]; /** - * HTTP status code + * HTTP status code. * * @var int */ protected $status; /** - * HTTP status text + * HTTP status text. * * @var string */ protected $statusText; /** - * Creates the response object + * Creates the response object. * * @param string|int $status - * @param array $headers - * @param resource $body + * @param array $headers + * @param resource $body */ - function __construct($status = null, array $headers = null, $body = null) { - - if (!is_null($status)) $this->setStatus($status); - if (!is_null($headers)) $this->setHeaders($headers); - if (!is_null($body)) $this->setBody($body); - + public function __construct($status = 500, array $headers = null, $body = null) + { + if (null !== $status) { + $this->setStatus($status); + } + if (null !== $headers) { + $this->setHeaders($headers); + } + if (null !== $body) { + $this->setBody($body); + } } - /** * Returns the current HTTP status code. - * - * @return int */ - function getStatus() { - + public function getStatus(): int + { return $this->status; - } /** * Returns the human-readable status string. * * In the case of a 200, this may for example be 'OK'. - * - * @return string */ - function getStatusText() { - + public function getStatusText(): string + { return $this->statusText; - } /** @@ -144,21 +144,20 @@ class Response extends Message implements ResponseInterface { * added. * * @param string|int $status + * * @throws \InvalidArgumentException - * @return void */ - function setStatus($status) { - + public function setStatus($status) + { if (ctype_digit($status) || is_int($status)) { - $statusCode = $status; - $statusText = isset(self::$statusCodes[$status]) ? self::$statusCodes[$status] : 'Unknown'; - + $statusText = self::$statusCodes[$status] ?? 'Unknown'; } else { list( $statusCode, $statusText ) = explode(' ', $status, 2); + $statusCode = (int) $statusCode; } if ($statusCode < 100 || $statusCode > 999) { throw new \InvalidArgumentException('The HTTP status code must be exactly 3 digits'); @@ -166,28 +165,24 @@ class Response extends Message implements ResponseInterface { $this->status = $statusCode; $this->statusText = $statusText; - } /** * Serializes the response object as a string. * * This is useful for debugging purposes. - * - * @return string */ - function __toString() { - - $str = 'HTTP/' . $this->httpVersion . ' ' . $this->getStatus() . ' ' . $this->getStatusText() . "\r\n"; + public function __toString(): string + { + $str = 'HTTP/'.$this->httpVersion.' '.$this->getStatus().' '.$this->getStatusText()."\r\n"; foreach ($this->getHeaders() as $key => $value) { foreach ($value as $v) { - $str .= $key . ": " . $v . "\r\n"; + $str .= $key.': '.$v."\r\n"; } } $str .= "\r\n"; $str .= $this->getBodyAsString(); - return $str; + return $str; } - } diff --git a/vendor/sabre/http/lib/ResponseDecorator.php b/vendor/sabre/http/lib/ResponseDecorator.php index db3a67507..289dba5cc 100644 --- a/vendor/sabre/http/lib/ResponseDecorator.php +++ b/vendor/sabre/http/lib/ResponseDecorator.php @@ -1,9 +1,11 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** - * Response Decorator + * Response Decorator. * * This helper class allows you to easily create decorators for the Response * object. @@ -12,45 +14,36 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class ResponseDecorator implements ResponseInterface { - +class ResponseDecorator implements ResponseInterface +{ use MessageDecoratorTrait; /** * Constructor. - * - * @param ResponseInterface $inner */ - function __construct(ResponseInterface $inner) { - + public function __construct(ResponseInterface $inner) + { $this->inner = $inner; - } /** * Returns the current HTTP status code. - * - * @return int */ - function getStatus() { - + public function getStatus(): int + { return $this->inner->getStatus(); - } - /** * Returns the human-readable status string. * * In the case of a 200, this may for example be 'OK'. - * - * @return string */ - function getStatusText() { - + public function getStatusText(): string + { return $this->inner->getStatusText(); - } + /** * Sets the HTTP status code. * @@ -61,12 +54,10 @@ class ResponseDecorator implements ResponseInterface { * added. * * @param string|int $status - * @return void */ - function setStatus($status) { - + public function setStatus($status) + { $this->inner->setStatus($status); - } /** @@ -76,9 +67,8 @@ class ResponseDecorator implements ResponseInterface { * * @return string */ - function __toString() { - + public function __toString(): string + { return $this->inner->__toString(); - } } diff --git a/vendor/sabre/http/lib/ResponseInterface.php b/vendor/sabre/http/lib/ResponseInterface.php index 411cdc06c..9bd93f179 100644 --- a/vendor/sabre/http/lib/ResponseInterface.php +++ b/vendor/sabre/http/lib/ResponseInterface.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** @@ -9,23 +11,19 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -interface ResponseInterface extends MessageInterface { - +interface ResponseInterface extends MessageInterface +{ /** * Returns the current HTTP status code. - * - * @return int */ - function getStatus(); + public function getStatus(): int; /** * Returns the human-readable status string. * * In the case of a 200, this may for example be 'OK'. - * - * @return string */ - function getStatusText(); + public function getStatusText(): string; /** * Sets the HTTP status code. @@ -37,9 +35,8 @@ interface ResponseInterface extends MessageInterface { * added. * * @param string|int $status + * * @throws \InvalidArgumentException - * @return void */ - function setStatus($status); - + public function setStatus($status); } diff --git a/vendor/sabre/http/lib/Sapi.php b/vendor/sabre/http/lib/Sapi.php index 054380e73..80254f3f3 100644 --- a/vendor/sabre/http/lib/Sapi.php +++ b/vendor/sabre/http/lib/Sapi.php @@ -1,9 +1,13 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; +use InvalidArgumentException; + /** - * PHP SAPI + * PHP SAPI. * * This object is responsible for: * 1. Constructing a Request object based on the current HTTP request sent to @@ -28,56 +32,85 @@ namespace Sabre\HTTP; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Sapi { - +class Sapi +{ /** * This static method will create a new Request object, based on the * current PHP request. - * - * @return Request */ - static function getRequest() { + public static function getRequest(): Request + { + $serverArr = $_SERVER; + + if ('cli' === PHP_SAPI) { + // If we're running off the CLI, we're going to set some default + // settings. + $serverArr['REQUEST_URI'] = $_SERVER['REQUEST_URI'] ?? '/'; + $serverArr['REQUEST_METHOD'] = $_SERVER['REQUEST_METHOD'] ?? 'CLI'; + } - $r = self::createFromServerArray($_SERVER); + $r = self::createFromServerArray($serverArr); $r->setBody(fopen('php://input', 'r')); $r->setPostData($_POST); - return $r; + return $r; } /** * Sends the HTTP response back to a HTTP client. * * This calls php's header() function and streams the body to php://output. - * - * @param ResponseInterface $response - * @return void */ - static function sendResponse(ResponseInterface $response) { - - header('HTTP/' . $response->getHttpVersion() . ' ' . $response->getStatus() . ' ' . $response->getStatusText()); + public static function sendResponse(ResponseInterface $response) + { + header('HTTP/'.$response->getHttpVersion().' '.$response->getStatus().' '.$response->getStatusText()); foreach ($response->getHeaders() as $key => $value) { - foreach ($value as $k => $v) { - if ($k === 0) { - header($key . ': ' . $v); + if (0 === $k) { + header($key.': '.$v); } else { - header($key . ': ' . $v, false); + header($key.': '.$v, false); } } - } $body = $response->getBody(); - if (is_null($body)) return; + if (null === $body) { + return; + } + + if (is_callable($body)) { + $body(); + + return; + } $contentLength = $response->getHeader('Content-Length'); - if ($contentLength !== null) { + if (null !== $contentLength) { $output = fopen('php://output', 'wb'); - if (is_resource($body) && get_resource_type($body) == 'stream') { - if (PHP_INT_SIZE !== 4){ + if (is_resource($body) && 'stream' == get_resource_type($body)) { + if (PHP_INT_SIZE > 4) { // use the dedicated function on 64 Bit systems - stream_copy_to_stream($body, $output, $contentLength); + // a workaround to make PHP more possible to use mmap based copy, see https://github.com/sabre-io/http/pull/119 + $left = (int) $contentLength; + // copy with 4MiB chunks + $chunk_size = 4 * 1024 * 1024; + stream_set_chunk_size($output, $chunk_size); + // If this is a partial response, flush the beginning bytes until the first position that is a multiple of the page size. + $contentRange = $response->getHeader('Content-Range'); + // Matching "Content-Range: bytes 1234-5678/7890" + if (null !== $contentRange && preg_match('/^bytes\s([0-9]*)-([0-9]*)\//i', $contentRange, $matches) && '' !== $matches[1]) { + // 4kB should be the default page size on most architectures + $pageSize = 4096; + $offset = (int) $matches[1]; + $delta = ($offset % $pageSize) > 0 ? ($pageSize - $offset % $pageSize) : 0; + if ($delta > 0) { + $left -= stream_copy_to_stream($body, $output, min($delta, $left)); + } + } + while ($left > 0) { + $left -= stream_copy_to_stream($body, $output, min($left, $chunk_size)); + } } else { // workaround for 32 Bit systems to avoid stream_copy_to_stream while (!feof($body)) { @@ -85,7 +118,7 @@ class Sapi { } } } else { - fwrite($output, $body, $contentLength); + fwrite($output, $body, (int) $contentLength); } } else { file_put_contents('php://output', $body); @@ -94,18 +127,16 @@ class Sapi { if (is_resource($body)) { fclose($body); } - } /** * This static method will create a new Request object, based on a PHP * $_SERVER array. * - * @param array $serverArray - * @return Request + * REQUEST_URI and REQUEST_METHOD are required. */ - static function createFromServerArray(array $serverArray) { - + public static function createFromServerArray(array $serverArray): Request + { $headers = []; $method = null; $url = null; @@ -115,61 +146,61 @@ class Sapi { $hostName = 'localhost'; foreach ($serverArray as $key => $value) { - switch ($key) { - - case 'SERVER_PROTOCOL' : - if ($value === 'HTTP/1.0') { + case 'SERVER_PROTOCOL': + if ('HTTP/1.0' === $value) { $httpVersion = '1.0'; + } elseif ('HTTP/2.0' === $value) { + $httpVersion = '2.0'; } break; - case 'REQUEST_METHOD' : + case 'REQUEST_METHOD': $method = $value; break; - case 'REQUEST_URI' : + case 'REQUEST_URI': $url = $value; break; // These sometimes show up without a HTTP_ prefix - case 'CONTENT_TYPE' : + case 'CONTENT_TYPE': $headers['Content-Type'] = $value; break; - case 'CONTENT_LENGTH' : + case 'CONTENT_LENGTH': $headers['Content-Length'] = $value; break; // mod_php on apache will put credentials in these variables. // (fast)cgi does not usually do this, however. - case 'PHP_AUTH_USER' : + case 'PHP_AUTH_USER': if (isset($serverArray['PHP_AUTH_PW'])) { - $headers['Authorization'] = 'Basic ' . base64_encode($value . ':' . $serverArray['PHP_AUTH_PW']); + $headers['Authorization'] = 'Basic '.base64_encode($value.':'.$serverArray['PHP_AUTH_PW']); } break; // Similarly, mod_php may also screw around with digest auth. - case 'PHP_AUTH_DIGEST' : - $headers['Authorization'] = 'Digest ' . $value; + case 'PHP_AUTH_DIGEST': + $headers['Authorization'] = 'Digest '.$value; break; // Apache may prefix the HTTP_AUTHORIZATION header with // REDIRECT_, if mod_rewrite was used. - case 'REDIRECT_HTTP_AUTHORIZATION' : + case 'REDIRECT_HTTP_AUTHORIZATION': $headers['Authorization'] = $value; break; - case 'HTTP_HOST' : + case 'HTTP_HOST': $hostName = $value; $headers['Host'] = $value; break; - case 'HTTPS' : - if (!empty($value) && $value !== 'off') { + case 'HTTPS': + if (!empty($value) && 'off' !== $value) { $protocol = 'https'; } break; - default : - if (substr($key, 0, 5) === 'HTTP_') { + default: + if ('HTTP_' === substr($key, 0, 5)) { // It's a HTTP header // Normalizing it to be prettier @@ -182,21 +213,23 @@ class Sapi { // Turning spaces into dashes. $header = str_replace(' ', '-', $header); $headers[$header] = $value; - } break; - - } + } + if (null === $url) { + throw new InvalidArgumentException('The _SERVER array must have a REQUEST_URI key'); } + if (null === $method) { + throw new InvalidArgumentException('The _SERVER array must have a REQUEST_METHOD key'); + } $r = new Request($method, $url, $headers); $r->setHttpVersion($httpVersion); $r->setRawServerData($serverArray); - $r->setAbsoluteUrl($protocol . '://' . $hostName . $url); - return $r; + $r->setAbsoluteUrl($protocol.'://'.$hostName.$url); + return $r; } - } diff --git a/vendor/sabre/http/lib/URLUtil.php b/vendor/sabre/http/lib/URLUtil.php deleted file mode 100644 index 85c0e1150..000000000 --- a/vendor/sabre/http/lib/URLUtil.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -namespace Sabre\HTTP; - -use Sabre\URI; - -/** - * URL utility class - * - * Note: this class is deprecated. All its functionality moved to functions.php - * or sabre\uri. - * - * @deprecated - * @copyright Copyright (C) fruux GmbH (https://fruux.com/) - * @author Evert Pot (http://evertpot.com/) - * @license http://sabre.io/license/ Modified BSD License - */ -class URLUtil { - - /** - * Encodes the path of a url. - * - * slashes (/) are treated as path-separators. - * - * @deprecated use \Sabre\HTTP\encodePath() - * @param string $path - * @return string - */ - static function encodePath($path) { - - return encodePath($path); - - } - - /** - * Encodes a 1 segment of a path - * - * Slashes are considered part of the name, and are encoded as %2f - * - * @deprecated use \Sabre\HTTP\encodePathSegment() - * @param string $pathSegment - * @return string - */ - static function encodePathSegment($pathSegment) { - - return encodePathSegment($pathSegment); - - } - - /** - * Decodes a url-encoded path - * - * @deprecated use \Sabre\HTTP\decodePath - * @param string $path - * @return string - */ - static function decodePath($path) { - - return decodePath($path); - - } - - /** - * Decodes a url-encoded path segment - * - * @deprecated use \Sabre\HTTP\decodePathSegment() - * @param string $path - * @return string - */ - static function decodePathSegment($path) { - - return decodePathSegment($path); - - } - - /** - * Returns the 'dirname' and 'basename' for a path. - * - * @deprecated Use Sabre\Uri\split(). - * @param string $path - * @return array - */ - static function splitPath($path) { - - return Uri\split($path); - - } - - /** - * Resolves relative urls, like a browser would. - * - * @deprecated Use Sabre\Uri\resolve(). - * @param string $basePath - * @param string $newPath - * @return string - */ - static function resolve($basePath, $newPath) { - - return Uri\resolve($basePath, $newPath); - - } - -} diff --git a/vendor/sabre/http/lib/Util.php b/vendor/sabre/http/lib/Util.php deleted file mode 100644 index e3f13a645..000000000 --- a/vendor/sabre/http/lib/Util.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -namespace Sabre\HTTP; - -/** - * HTTP utility methods - * - * @copyright Copyright (C) fruux GmbH (https://fruux.com/) - * @author Evert Pot (http://evertpot.com/) - * @author Paul Voegler - * @deprecated All these functions moved to functions.php - * @license http://sabre.io/license/ Modified BSD License - */ -class Util { - - /** - * Content negotiation - * - * @deprecated Use \Sabre\HTTP\negotiateContentType - * @param string|null $acceptHeaderValue - * @param array $availableOptions - * @return string|null - */ - static function negotiateContentType($acceptHeaderValue, array $availableOptions) { - - return negotiateContentType($acceptHeaderValue, $availableOptions); - - } - - /** - * Deprecated! Use negotiateContentType. - * - * @deprecated Use \Sabre\HTTP\NegotiateContentType - * @param string|null $acceptHeaderValue - * @param array $availableOptions - * @return string|null - */ - static function negotiate($acceptHeaderValue, array $availableOptions) { - - return negotiateContentType($acceptHeaderValue, $availableOptions); - - } - - /** - * Parses a RFC2616-compatible date string - * - * This method returns false if the date is invalid - * - * @deprecated Use parseDate - * @param string $dateHeader - * @return bool|DateTime - */ - static function parseHTTPDate($dateHeader) { - - return parseDate($dateHeader); - - } - - /** - * Transforms a DateTime object to HTTP's most common date format. - * - * We're serializing it as the RFC 1123 date, which, for HTTP must be - * specified as GMT. - * - * @deprecated Use toDate - * @param \DateTime $dateTime - * @return string - */ - static function toHTTPDate(\DateTime $dateTime) { - - return toDate($dateTime); - - } -} diff --git a/vendor/sabre/http/lib/Version.php b/vendor/sabre/http/lib/Version.php index c40532ae8..20a401773 100644 --- a/vendor/sabre/http/lib/Version.php +++ b/vendor/sabre/http/lib/Version.php @@ -1,19 +1,20 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; /** - * This class contains the version number for the HTTP package + * This class contains the version number for the HTTP package. * * @copyright Copyright (C) fruux GmbH (https://fruux.com/) * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Version { - +class Version +{ /** - * Full version number + * Full version number. */ - const VERSION = '4.2.4'; - + const VERSION = '5.0.4'; } diff --git a/vendor/sabre/http/lib/functions.php b/vendor/sabre/http/lib/functions.php index d94119623..197a9e661 100644 --- a/vendor/sabre/http/lib/functions.php +++ b/vendor/sabre/http/lib/functions.php @@ -1,8 +1,11 @@ <?php +declare(strict_types=1); + namespace Sabre\HTTP; use DateTime; +use InvalidArgumentException; /** * A collection of useful helpers for parsing or generating various HTTP @@ -27,61 +30,64 @@ use DateTime; * http://tools.ietf.org/html/rfc7231#section-7.1.1.1 * * @param string $dateString + * * @return bool|DateTime */ -function parseDate($dateString) { - +function parseDate(string $dateString) +{ // Only the format is checked, valid ranges are checked by strtotime below $month = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)'; $weekday = '(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)'; $wkday = '(Mon|Tue|Wed|Thu|Fri|Sat|Sun)'; $time = '([0-1]\d|2[0-3])(\:[0-5]\d){2}'; - $date3 = $month . ' ([12]\d|3[01]| [1-9])'; - $date2 = '(0[1-9]|[12]\d|3[01])\-' . $month . '\-\d{2}'; + $date3 = $month.' ([12]\d|3[01]| [1-9])'; + $date2 = '(0[1-9]|[12]\d|3[01])\-'.$month.'\-\d{2}'; // 4-digit year cannot begin with 0 - unix timestamp begins in 1970 - $date1 = '(0[1-9]|[12]\d|3[01]) ' . $month . ' [1-9]\d{3}'; + $date1 = '(0[1-9]|[12]\d|3[01]) '.$month.' [1-9]\d{3}'; // ANSI C's asctime() format // 4-digit year cannot begin with 0 - unix timestamp begins in 1970 - $asctime_date = $wkday . ' ' . $date3 . ' ' . $time . ' [1-9]\d{3}'; + $asctime_date = $wkday.' '.$date3.' '.$time.' [1-9]\d{3}'; // RFC 850, obsoleted by RFC 1036 - $rfc850_date = $weekday . ', ' . $date2 . ' ' . $time . ' GMT'; + $rfc850_date = $weekday.', '.$date2.' '.$time.' GMT'; // RFC 822, updated by RFC 1123 - $rfc1123_date = $wkday . ', ' . $date1 . ' ' . $time . ' GMT'; + $rfc1123_date = $wkday.', '.$date1.' '.$time.' GMT'; // allowed date formats by RFC 2616 $HTTP_date = "($rfc1123_date|$rfc850_date|$asctime_date)"; // allow for space around the string and strip it $dateString = trim($dateString, ' '); - if (!preg_match('/^' . $HTTP_date . '$/', $dateString)) + if (!preg_match('/^'.$HTTP_date.'$/', $dateString)) { return false; + } // append implicit GMT timezone to ANSI C time format - if (strpos($dateString, ' GMT') === false) + if (false === strpos($dateString, ' GMT')) { $dateString .= ' GMT'; + } try { return new DateTime($dateString, new \DateTimeZone('UTC')); } catch (\Exception $e) { return false; } - } /** - * Transforms a DateTime object to a valid HTTP/1.1 Date header value + * Transforms a DateTime object to a valid HTTP/1.1 Date header value. * * @param DateTime $dateTime + * * @return string */ -function toDate(DateTime $dateTime) { - +function toDate(DateTime $dateTime): string +{ // We need to clone it, as we don't want to affect the existing // DateTime. $dateTime = clone $dateTime; $dateTime->setTimezone(new \DateTimeZone('GMT')); - return $dateTime->format('D, d M Y H:i:s \G\M\T'); + return $dateTime->format('D, d M Y H:i:s \G\M\T'); } /** @@ -101,11 +107,12 @@ function toDate(DateTime $dateTime) { * implying that no accept header was sent. * * @param string|null $acceptHeaderValue - * @param array $availableOptions + * @param array $availableOptions + * * @return string|null */ -function negotiateContentType($acceptHeaderValue, array $availableOptions) { - +function negotiateContentType($acceptHeaderValue, array $availableOptions) +{ if (!$acceptHeaderValue) { // Grabbing the first in the list. return reset($availableOptions); @@ -130,9 +137,10 @@ function negotiateContentType($acceptHeaderValue, array $availableOptions) { $lastChoice = null; foreach ($proposals as $proposal) { - // Ignoring broken values. - if (is_null($proposal)) continue; + if (null === $proposal) { + continue; + } // If the quality is lower we don't have to bother comparing. if ($proposal['quality'] < $lastQuality) { @@ -140,12 +148,11 @@ function negotiateContentType($acceptHeaderValue, array $availableOptions) { } foreach ($options as $optionIndex => $option) { - - if ($proposal['type'] !== '*' && $proposal['type'] !== $option['type']) { + if ('*' !== $proposal['type'] && $proposal['type'] !== $option['type']) { // no match on type. continue; } - if ($proposal['subType'] !== '*' && $proposal['subType'] !== $option['subType']) { + if ('*' !== $proposal['subType'] && $proposal['subType'] !== $option['subType']) { // no match on subtype. continue; } @@ -165,31 +172,25 @@ function negotiateContentType($acceptHeaderValue, array $availableOptions) { // subtype. We need to calculate a score for how specific the // match was. $specificity = - ($proposal['type'] !== '*' ? 20 : 0) + - ($proposal['subType'] !== '*' ? 10 : 0) + + ('*' !== $proposal['type'] ? 20 : 0) + + ('*' !== $proposal['subType'] ? 10 : 0) + count($option['parameters']); - // Does this entry win? if ( ($proposal['quality'] > $lastQuality) || ($proposal['quality'] === $lastQuality && $specificity > $lastSpecificity) || ($proposal['quality'] === $lastQuality && $specificity === $lastSpecificity && $optionIndex < $lastOptionIndex) ) { - $lastQuality = $proposal['quality']; $lastSpecificity = $specificity; $lastOptionIndex = $optionIndex; $lastChoice = $availableOptions[$optionIndex]; - } - } - } return $lastChoice; - } /** @@ -217,10 +218,11 @@ function negotiateContentType($acceptHeaderValue, array $availableOptions) { * uses them. * * @param string|string[] $input + * * @return array */ -function parsePrefer($input) { - +function parsePrefer($input): array +{ $token = '[!#$%&\'*+\-.^_`~A-Za-z0-9]+'; // Work in progress @@ -241,7 +243,6 @@ REGEX; $output = []; foreach (getHeaderValues($input) as $value) { - if (!preg_match($regex, $value, $matches)) { // Ignore continue; @@ -249,22 +250,22 @@ REGEX; // Mapping old values to their new counterparts switch ($matches['name']) { - case 'return-asynch' : + case 'return-asynch': $output['respond-async'] = true; break; - case 'return-representation' : + case 'return-representation': $output['return'] = 'representation'; break; - case 'return-minimal' : + case 'return-minimal': $output['return'] = 'minimal'; break; - case 'strict' : + case 'strict': $output['handling'] = 'strict'; break; - case 'lenient' : + case 'lenient': $output['handling'] = 'lenient'; break; - default : + default: if (isset($matches['value'])) { $value = trim($matches['value'], '"'); } else { @@ -273,11 +274,9 @@ REGEX; $output[strtolower($matches['name'])] = empty($value) ? true : $value; break; } - } return $output; - } /** @@ -296,25 +295,26 @@ REGEX; * * @param string|string[] $values * @param string|string[] $values2 - * @return string[] */ -function getHeaderValues($values, $values2 = null) { - - $values = (array)$values; +function getHeaderValues($values, $values2 = null): array +{ + $values = (array) $values; if ($values2) { - $values = array_merge($values, (array)$values2); + $values = array_merge($values, (array) $values2); } + + $result = array(); foreach ($values as $l1) { foreach (explode(',', $l1) as $l2) { $result[] = trim($l2); } } - return $result; + return $result; } /** - * Parses a mime-type and splits it into: + * Parses a mime-type and splits it into:. * * 1. type * 2. subtype @@ -322,10 +322,11 @@ function getHeaderValues($values, $values2 = null) { * 4. parameters * * @param string $str + * * @return array */ -function parseMimeType($str) { - +function parseMimeType(string $str): array +{ $parameters = []; // If no q= parameter appears, then quality = 1. $quality = 1; @@ -333,17 +334,22 @@ function parseMimeType($str) { $parts = explode(';', $str); // The first part is the mime-type. - $mimeType = array_shift($parts); + $mimeType = trim(array_shift($parts)); + + if ('*' === $mimeType) { + $mimeType = '*/*'; + } - $mimeType = explode('/', trim($mimeType)); - if (count($mimeType) !== 2) { + $mimeType = explode('/', $mimeType); + if (2 !== count($mimeType)) { // Illegal value - return null; + var_dump($mimeType); + die(); + throw new InvalidArgumentException('Not a valid mime-type: '.$str); } list($type, $subType) = $mimeType; foreach ($parts as $part) { - $part = trim($part); if (strpos($part, '=')) { list($partName, $partValue) = @@ -357,89 +363,66 @@ function parseMimeType($str) { // the parameter list. Anything after the q= counts as an // 'accept extension' and could introduce new semantics in // content-negotation. - if ($partName !== 'q') { + if ('q' !== $partName) { $parameters[$partName] = $part; } else { - $quality = (float)$partValue; + $quality = (float) $partValue; break; // Stop parsing parts } - } return [ - 'type' => $type, - 'subType' => $subType, - 'quality' => $quality, + 'type' => $type, + 'subType' => $subType, + 'quality' => $quality, 'parameters' => $parameters, ]; - } /** * Encodes the path of a url. * * slashes (/) are treated as path-separators. - * - * @param string $path - * @return string */ -function encodePath($path) { - - return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\)\/:@])/', function($match) { - - return '%' . sprintf('%02x', ord($match[0])); - +function encodePath(string $path): string +{ + return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\)\/:@])/', function ($match) { + return '%'.sprintf('%02x', ord($match[0])); }, $path); - } /** - * Encodes a 1 segment of a path + * Encodes a 1 segment of a path. * * Slashes are considered part of the name, and are encoded as %2f - * - * @param string $pathSegment - * @return string */ -function encodePathSegment($pathSegment) { - - return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\):@])/', function($match) { - - return '%' . sprintf('%02x', ord($match[0])); - +function encodePathSegment(string $pathSegment): string +{ + return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\):@])/', function ($match) { + return '%'.sprintf('%02x', ord($match[0])); }, $pathSegment); } /** - * Decodes a url-encoded path - * - * @param string $path - * @return string + * Decodes a url-encoded path. */ -function decodePath($path) { - +function decodePath(string $path): string +{ return decodePathSegment($path); - } /** - * Decodes a url-encoded path segment - * - * @param string $path - * @return string + * Decodes a url-encoded path segment. */ -function decodePathSegment($path) { - +function decodePathSegment(string $path): string +{ $path = rawurldecode($path); $encoding = mb_detect_encoding($path, ['UTF-8', 'ISO-8859-1']); switch ($encoding) { - - case 'ISO-8859-1' : + case 'ISO-8859-1': $path = utf8_encode($path); - } return $path; - } |