diff options
Diffstat (limited to 'vendor/guzzle/guzzle/src/Guzzle/Stream')
5 files changed, 845 insertions, 0 deletions
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Stream/PhpStreamRequestFactory.php b/vendor/guzzle/guzzle/src/Guzzle/Stream/PhpStreamRequestFactory.php new file mode 100644 index 0000000..d115fd8 --- /dev/null +++ b/vendor/guzzle/guzzle/src/Guzzle/Stream/PhpStreamRequestFactory.php @@ -0,0 +1,284 @@ +<?php + +namespace Guzzle\Stream; + +use Guzzle\Common\Exception\InvalidArgumentException; +use Guzzle\Common\Exception\RuntimeException; +use Guzzle\Http\Message\EntityEnclosingRequestInterface; +use Guzzle\Http\Message\RequestInterface; +use Guzzle\Http\Url; + +/** + * Factory used to create fopen streams using PHP's http and https stream wrappers + * + * Note: PHP's http stream wrapper only supports streaming downloads. It does not support streaming uploads. + */ +class PhpStreamRequestFactory implements StreamRequestFactoryInterface +{ + /** @var resource Stream context options */ + protected $context; + + /** @var array Stream context */ + protected $contextOptions; + + /** @var Url Stream URL */ + protected $url; + + /** @var array Last response headers received by the HTTP request */ + protected $lastResponseHeaders; + + /** + * {@inheritdoc} + * + * The $params array can contain the following custom keys specific to the PhpStreamRequestFactory: + * - stream_class: The name of a class to create instead of a Guzzle\Stream\Stream object + */ + public function fromRequest(RequestInterface $request, $context = array(), array $params = array()) + { + if (is_resource($context)) { + $this->contextOptions = stream_context_get_options($context); + $this->context = $context; + } elseif (is_array($context) || !$context) { + $this->contextOptions = $context; + $this->createContext($params); + } elseif ($context) { + throw new InvalidArgumentException('$context must be an array or resource'); + } + + // Dispatch the before send event + $request->dispatch('request.before_send', array( + 'request' => $request, + 'context' => $this->context, + 'context_options' => $this->contextOptions + )); + + $this->setUrl($request); + $this->addDefaultContextOptions($request); + $this->addSslOptions($request); + $this->addBodyOptions($request); + $this->addProxyOptions($request); + + // Create the file handle but silence errors + return $this->createStream($params) + ->setCustomData('request', $request) + ->setCustomData('response_headers', $this->getLastResponseHeaders()); + } + + /** + * Set an option on the context and the internal options array + * + * @param string $wrapper Stream wrapper name of http + * @param string $name Context name + * @param mixed $value Context value + * @param bool $overwrite Set to true to overwrite an existing value + */ + protected function setContextValue($wrapper, $name, $value, $overwrite = false) + { + if (!isset($this->contextOptions[$wrapper])) { + $this->contextOptions[$wrapper] = array($name => $value); + } elseif (!$overwrite && isset($this->contextOptions[$wrapper][$name])) { + return; + } + $this->contextOptions[$wrapper][$name] = $value; + stream_context_set_option($this->context, $wrapper, $name, $value); + } + + /** + * Create a stream context + * + * @param array $params Parameter array + */ + protected function createContext(array $params) + { + $options = $this->contextOptions; + $this->context = $this->createResource(function () use ($params, $options) { + return stream_context_create($options, $params); + }); + } + + /** + * Get the last response headers received by the HTTP request + * + * @return array + */ + public function getLastResponseHeaders() + { + return $this->lastResponseHeaders; + } + + /** + * Adds the default context options to the stream context options + * + * @param RequestInterface $request Request + */ + protected function addDefaultContextOptions(RequestInterface $request) + { + $this->setContextValue('http', 'method', $request->getMethod()); + $headers = $request->getHeaderLines(); + + // "Connection: close" is required to get streams to work in HTTP 1.1 + if (!$request->hasHeader('Connection')) { + $headers[] = 'Connection: close'; + } + + $this->setContextValue('http', 'header', $headers); + $this->setContextValue('http', 'protocol_version', $request->getProtocolVersion()); + $this->setContextValue('http', 'ignore_errors', true); + } + + /** + * Set the URL to use with the factory + * + * @param RequestInterface $request Request that owns the URL + */ + protected function setUrl(RequestInterface $request) + { + $this->url = $request->getUrl(true); + + // Check for basic Auth username + if ($request->getUsername()) { + $this->url->setUsername($request->getUsername()); + } + + // Check for basic Auth password + if ($request->getPassword()) { + $this->url->setPassword($request->getPassword()); + } + } + + /** + * Add SSL options to the stream context + * + * @param RequestInterface $request Request + */ + protected function addSslOptions(RequestInterface $request) + { + if ($request->getCurlOptions()->get(CURLOPT_SSL_VERIFYPEER)) { + $this->setContextValue('ssl', 'verify_peer', true, true); + if ($cafile = $request->getCurlOptions()->get(CURLOPT_CAINFO)) { + $this->setContextValue('ssl', 'cafile', $cafile, true); + } + } else { + $this->setContextValue('ssl', 'verify_peer', false, true); + } + } + + /** + * Add body (content) specific options to the context options + * + * @param RequestInterface $request + */ + protected function addBodyOptions(RequestInterface $request) + { + // Add the content for the request if needed + if (!($request instanceof EntityEnclosingRequestInterface)) { + return; + } + + if (count($request->getPostFields())) { + $this->setContextValue('http', 'content', (string) $request->getPostFields(), true); + } elseif ($request->getBody()) { + $this->setContextValue('http', 'content', (string) $request->getBody(), true); + } + + // Always ensure a content-length header is sent + if (isset($this->contextOptions['http']['content'])) { + $headers = isset($this->contextOptions['http']['header']) ? $this->contextOptions['http']['header'] : array(); + $headers[] = 'Content-Length: ' . strlen($this->contextOptions['http']['content']); + $this->setContextValue('http', 'header', $headers, true); + } + } + + /** + * Add proxy parameters to the context if needed + * + * @param RequestInterface $request Request + */ + protected function addProxyOptions(RequestInterface $request) + { + if ($proxy = $request->getCurlOptions()->get(CURLOPT_PROXY)) { + $this->setContextValue('http', 'proxy', $proxy); + } + } + + /** + * Create the stream for the request with the context options + * + * @param array $params Parameters of the stream + * + * @return StreamInterface + */ + protected function createStream(array $params) + { + $http_response_header = null; + $url = $this->url; + $context = $this->context; + $fp = $this->createResource(function () use ($context, $url, &$http_response_header) { + return fopen((string) $url, 'r', false, $context); + }); + + // Determine the class to instantiate + $className = isset($params['stream_class']) ? $params['stream_class'] : __NAMESPACE__ . '\\Stream'; + + /** @var $stream StreamInterface */ + $stream = new $className($fp); + + // Track the response headers of the request + if (isset($http_response_header)) { + $this->lastResponseHeaders = $http_response_header; + $this->processResponseHeaders($stream); + } + + return $stream; + } + + /** + * Process response headers + * + * @param StreamInterface $stream + */ + protected function processResponseHeaders(StreamInterface $stream) + { + // Set the size on the stream if it was returned in the response + foreach ($this->lastResponseHeaders as $header) { + if ((stripos($header, 'Content-Length:')) === 0) { + $stream->setSize(trim(substr($header, 15))); + } + } + } + + /** + * Create a resource and check to ensure it was created successfully + * + * @param callable $callback Closure to invoke that must return a valid resource + * + * @return resource + * @throws RuntimeException on error + */ + protected function createResource($callback) + { + $errors = null; + set_error_handler(function ($_, $msg, $file, $line) use (&$errors) { + $errors[] = array( + 'message' => $msg, + 'file' => $file, + 'line' => $line + ); + return true; + }); + $resource = call_user_func($callback); + restore_error_handler(); + + if (!$resource) { + $message = 'Error creating resource. '; + foreach ($errors as $err) { + foreach ($err as $key => $value) { + $message .= "[$key] $value" . PHP_EOL; + } + } + throw new RuntimeException(trim($message)); + } + + return $resource; + } +} diff --git a/vendor/guzzle/guzzle/src/Guzzle/Stream/Stream.php b/vendor/guzzle/guzzle/src/Guzzle/Stream/Stream.php new file mode 100644 index 0000000..12bed26 --- /dev/null +++ b/vendor/guzzle/guzzle/src/Guzzle/Stream/Stream.php @@ -0,0 +1,289 @@ +<?php + +namespace Guzzle\Stream; + +use Guzzle\Common\Exception\InvalidArgumentException; + +/** + * PHP stream implementation + */ +class Stream implements StreamInterface +{ + const STREAM_TYPE = 'stream_type'; + const WRAPPER_TYPE = 'wrapper_type'; + const IS_LOCAL = 'is_local'; + const IS_READABLE = 'is_readable'; + const IS_WRITABLE = 'is_writable'; + const SEEKABLE = 'seekable'; + + /** @var resource Stream resource */ + protected $stream; + + /** @var int Size of the stream contents in bytes */ + protected $size; + + /** @var array Stream cached data */ + protected $cache = array(); + + /** @var array Custom stream data */ + protected $customData = array(); + + /** @var array Hash table of readable and writeable stream types for fast lookups */ + protected static $readWriteHash = array( + 'read' => array( + 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, + 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, 'c+b' => true, + 'rt' => true, 'w+t' => true, 'r+t' => true, 'x+t' => true, 'c+t' => true, 'a+' => true + ), + 'write' => array( + 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, 'c+' => true, + 'wb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, 'c+b' => true, + 'w+t' => true, 'r+t' => true, 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true + ) + ); + + /** + * @param resource $stream Stream resource to wrap + * @param int $size Size of the stream in bytes. Only pass if the size cannot be obtained from the stream. + * + * @throws InvalidArgumentException if the stream is not a stream resource + */ + public function __construct($stream, $size = null) + { + $this->setStream($stream, $size); + } + + /** + * Closes the stream when the helper is destructed + */ + public function __destruct() + { + $this->close(); + } + + public function __toString() + { + if (!$this->isReadable() || (!$this->isSeekable() && $this->isConsumed())) { + return ''; + } + + $originalPos = $this->ftell(); + $body = stream_get_contents($this->stream, -1, 0); + $this->seek($originalPos); + + return $body; + } + + public function close() + { + if (is_resource($this->stream)) { + fclose($this->stream); + } + $this->cache[self::IS_READABLE] = false; + $this->cache[self::IS_WRITABLE] = false; + } + + /** + * Calculate a hash of a Stream + * + * @param StreamInterface $stream Stream to calculate the hash for + * @param string $algo Hash algorithm (e.g. md5, crc32, etc) + * @param bool $rawOutput Whether or not to use raw output + * + * @return bool|string Returns false on failure or a hash string on success + */ + public static function getHash(StreamInterface $stream, $algo, $rawOutput = false) + { + $pos = $stream->ftell(); + if (!$stream->seek(0)) { + return false; + } + + $ctx = hash_init($algo); + while (!$stream->feof()) { + hash_update($ctx, $stream->read(8192)); + } + + $out = hash_final($ctx, (bool) $rawOutput); + $stream->seek($pos); + + return $out; + } + + public function getMetaData($key = null) + { + $meta = stream_get_meta_data($this->stream); + + return !$key ? $meta : (array_key_exists($key, $meta) ? $meta[$key] : null); + } + + public function getStream() + { + return $this->stream; + } + + public function setStream($stream, $size = null) + { + if (!is_resource($stream)) { + throw new InvalidArgumentException('Stream must be a resource'); + } + + $this->size = $size; + $this->stream = $stream; + $this->rebuildCache(); + + return $this; + } + + public function detachStream() + { + $this->stream = null; + + return $this; + } + + public function getWrapper() + { + return $this->cache[self::WRAPPER_TYPE]; + } + + public function getWrapperData() + { + return $this->getMetaData('wrapper_data') ?: array(); + } + + public function getStreamType() + { + return $this->cache[self::STREAM_TYPE]; + } + + public function getUri() + { + return $this->cache['uri']; + } + + public function getSize() + { + if ($this->size !== null) { + return $this->size; + } + + // If the stream is a file based stream and local, then use fstat + clearstatcache(true, $this->cache['uri']); + $stats = fstat($this->stream); + if (isset($stats['size'])) { + $this->size = $stats['size']; + return $this->size; + } elseif ($this->cache[self::IS_READABLE] && $this->cache[self::SEEKABLE]) { + // Only get the size based on the content if the the stream is readable and seekable + $pos = $this->ftell(); + $this->size = strlen((string) $this); + $this->seek($pos); + return $this->size; + } + + return false; + } + + public function isReadable() + { + return $this->cache[self::IS_READABLE]; + } + + public function isRepeatable() + { + return $this->cache[self::IS_READABLE] && $this->cache[self::SEEKABLE]; + } + + public function isWritable() + { + return $this->cache[self::IS_WRITABLE]; + } + + public function isConsumed() + { + return feof($this->stream); + } + + public function feof() + { + return $this->isConsumed(); + } + + public function isLocal() + { + return $this->cache[self::IS_LOCAL]; + } + + public function isSeekable() + { + return $this->cache[self::SEEKABLE]; + } + + public function setSize($size) + { + $this->size = $size; + + return $this; + } + + public function seek($offset, $whence = SEEK_SET) + { + return $this->cache[self::SEEKABLE] ? fseek($this->stream, $offset, $whence) === 0 : false; + } + + public function read($length) + { + return fread($this->stream, $length); + } + + public function write($string) + { + // We can't know the size after writing anything + $this->size = null; + + return fwrite($this->stream, $string); + } + + public function ftell() + { + return ftell($this->stream); + } + + public function rewind() + { + return $this->seek(0); + } + + public function readLine($maxLength = null) + { + if (!$this->cache[self::IS_READABLE]) { + return false; + } else { + return $maxLength ? fgets($this->getStream(), $maxLength) : fgets($this->getStream()); + } + } + + public function setCustomData($key, $value) + { + $this->customData[$key] = $value; + + return $this; + } + + public function getCustomData($key) + { + return isset($this->customData[$key]) ? $this->customData[$key] : null; + } + + /** + * Reprocess stream metadata + */ + protected function rebuildCache() + { + $this->cache = stream_get_meta_data($this->stream); + $this->cache[self::IS_LOCAL] = stream_is_local($this->stream); + $this->cache[self::IS_READABLE] = isset(self::$readWriteHash['read'][$this->cache['mode']]); + $this->cache[self::IS_WRITABLE] = isset(self::$readWriteHash['write'][$this->cache['mode']]); + } +} diff --git a/vendor/guzzle/guzzle/src/Guzzle/Stream/StreamInterface.php b/vendor/guzzle/guzzle/src/Guzzle/Stream/StreamInterface.php new file mode 100644 index 0000000..6d7dc37 --- /dev/null +++ b/vendor/guzzle/guzzle/src/Guzzle/Stream/StreamInterface.php @@ -0,0 +1,218 @@ +<?php + +namespace Guzzle\Stream; + +/** + * OO interface to PHP streams + */ +interface StreamInterface +{ + /** + * Convert the stream to a string if the stream is readable and the stream is seekable. + * + * @return string + */ + public function __toString(); + + /** + * Close the underlying stream + */ + public function close(); + + /** + * Get stream metadata + * + * @param string $key Specific metadata to retrieve + * + * @return array|mixed|null + */ + public function getMetaData($key = null); + + /** + * Get the stream resource + * + * @return resource + */ + public function getStream(); + + /** + * Set the stream that is wrapped by the object + * + * @param resource $stream Stream resource to wrap + * @param int $size Size of the stream in bytes. Only pass if the size cannot be obtained from the stream. + * + * @return self + */ + public function setStream($stream, $size = null); + + /** + * Detach the current stream resource + * + * @return self + */ + public function detachStream(); + + /** + * Get the stream wrapper type + * + * @return string + */ + public function getWrapper(); + + /** + * Wrapper specific data attached to this stream. + * + * @return array + */ + public function getWrapperData(); + + /** + * Get a label describing the underlying implementation of the stream + * + * @return string + */ + public function getStreamType(); + + /** + * Get the URI/filename associated with this stream + * + * @return string + */ + public function getUri(); + + /** + * Get the size of the stream if able + * + * @return int|bool + */ + public function getSize(); + + /** + * Check if the stream is readable + * + * @return bool + */ + public function isReadable(); + + /** + * Check if the stream is repeatable + * + * @return bool + */ + public function isRepeatable(); + + /** + * Check if the stream is writable + * + * @return bool + */ + public function isWritable(); + + /** + * Check if the stream has been consumed + * + * @return bool + */ + public function isConsumed(); + + /** + * Alias of isConsumed + * + * @return bool + */ + public function feof(); + + /** + * Check if the stream is a local stream vs a remote stream + * + * @return bool + */ + public function isLocal(); + + /** + * Check if the string is repeatable + * + * @return bool + */ + public function isSeekable(); + + /** + * Specify the size of the stream in bytes + * + * @param int $size Size of the stream contents in bytes + * + * @return self + */ + public function setSize($size); + + /** + * Seek to a position in the stream + * + * @param int $offset Stream offset + * @param int $whence Where the offset is applied + * + * @return bool Returns TRUE on success or FALSE on failure + * @link http://www.php.net/manual/en/function.fseek.php + */ + public function seek($offset, $whence = SEEK_SET); + + /** + * Read data from the stream + * + * @param int $length Up to length number of bytes read. + * + * @return string|bool Returns the data read from the stream or FALSE on failure or EOF + */ + public function read($length); + + /** + * Write data to the stream + * + * @param string $string The string that is to be written. + * + * @return int|bool Returns the number of bytes written to the stream on success or FALSE on failure. + */ + public function write($string); + + /** + * Returns the current position of the file read/write pointer + * + * @return int|bool Returns the position of the file pointer or false on error + */ + public function ftell(); + + /** + * Rewind to the beginning of the stream + * + * @return bool Returns true on success or false on failure + */ + public function rewind(); + + /** + * Read a line from the stream up to the maximum allowed buffer length + * + * @param int $maxLength Maximum buffer length + * + * @return string|bool + */ + public function readLine($maxLength = null); + + /** + * Set custom data on the stream + * + * @param string $key Key to set + * @param mixed $value Value to set + * + * @return self + */ + public function setCustomData($key, $value); + + /** + * Get custom data from the stream + * + * @param string $key Key to retrieve + * + * @return null|mixed + */ + public function getCustomData($key); +} diff --git a/vendor/guzzle/guzzle/src/Guzzle/Stream/StreamRequestFactoryInterface.php b/vendor/guzzle/guzzle/src/Guzzle/Stream/StreamRequestFactoryInterface.php new file mode 100644 index 0000000..d00e622 --- /dev/null +++ b/vendor/guzzle/guzzle/src/Guzzle/Stream/StreamRequestFactoryInterface.php @@ -0,0 +1,24 @@ +<?php + +namespace Guzzle\Stream; + +use Guzzle\Http\Message\RequestInterface; + +/** + * Interface used for creating streams from requests + */ +interface StreamRequestFactoryInterface +{ + /** + * Create a stream based on a request object + * + * @param RequestInterface $request Base the stream on a request + * @param array|resource $context A stream_context_options resource or array of parameters used to create a + * stream context. + * @param array $params Optional array of parameters specific to the factory + * + * @return StreamInterface Returns a stream object + * @throws \Guzzle\Common\Exception\RuntimeException if the stream cannot be opened or an error occurs + */ + public function fromRequest(RequestInterface $request, $context = array(), array $params = array()); +} diff --git a/vendor/guzzle/guzzle/src/Guzzle/Stream/composer.json b/vendor/guzzle/guzzle/src/Guzzle/Stream/composer.json new file mode 100644 index 0000000..9c19d2b --- /dev/null +++ b/vendor/guzzle/guzzle/src/Guzzle/Stream/composer.json @@ -0,0 +1,30 @@ +{ + "name": "guzzle/stream", + "description": "Guzzle stream wrapper component", + "homepage": "http://guzzlephp.org/", + "keywords": ["stream", "component", "guzzle"], + "license": "MIT", + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "require": { + "php": ">=5.3.2", + "guzzle/common": "self.version" + }, + "suggest": { + "guzzle/http": "To convert Guzzle request objects to PHP streams" + }, + "autoload": { + "psr-0": { "Guzzle\\Stream": "" } + }, + "target-dir": "Guzzle/Stream", + "extra": { + "branch-alias": { + "dev-master": "3.7-dev" + } + } +} |