123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- <?php
- namespace Guzzle\Http;
- use Guzzle\Common\Version;
- use Guzzle\Stream\Stream;
- use Guzzle\Common\Exception\InvalidArgumentException;
- use Guzzle\Http\Mimetypes;
- /**
- * Entity body used with an HTTP request or response
- */
- class EntityBody extends Stream implements EntityBodyInterface
- {
- /** @var bool Content-Encoding of the entity body if known */
- protected $contentEncoding = false;
- /** @var callable Method to invoke for rewinding a stream */
- protected $rewindFunction;
- /**
- * Create a new EntityBody based on the input type
- *
- * @param resource|string|EntityBody $resource Entity body data
- * @param int $size Size of the data contained in the resource
- *
- * @return EntityBody
- * @throws InvalidArgumentException if the $resource arg is not a resource or string
- */
- public static function factory($resource = '', $size = null)
- {
- if ($resource instanceof EntityBodyInterface) {
- return $resource;
- }
- switch (gettype($resource)) {
- case 'string':
- return self::fromString($resource);
- case 'resource':
- return new static($resource, $size);
- case 'object':
- if (method_exists($resource, '__toString')) {
- return self::fromString((string) $resource);
- }
- break;
- case 'array':
- return self::fromString(http_build_query($resource));
- }
- throw new InvalidArgumentException('Invalid resource type');
- }
- public function setRewindFunction($callable)
- {
- if (!is_callable($callable)) {
- throw new InvalidArgumentException('Must specify a callable');
- }
- $this->rewindFunction = $callable;
- return $this;
- }
- public function rewind()
- {
- return $this->rewindFunction ? call_user_func($this->rewindFunction, $this) : parent::rewind();
- }
- /**
- * Create a new EntityBody from a string
- *
- * @param string $string String of data
- *
- * @return EntityBody
- */
- public static function fromString($string)
- {
- $stream = fopen('php://temp', 'r+');
- if ($string !== '') {
- fwrite($stream, $string);
- rewind($stream);
- }
- return new static($stream);
- }
- public function compress($filter = 'zlib.deflate')
- {
- $result = $this->handleCompression($filter);
- $this->contentEncoding = $result ? $filter : false;
- return $result;
- }
- public function uncompress($filter = 'zlib.inflate')
- {
- $offsetStart = 0;
- // When inflating gzipped data, the first 10 bytes must be stripped
- // if a gzip header is present
- if ($filter == 'zlib.inflate') {
- // @codeCoverageIgnoreStart
- if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
- return false;
- }
- // @codeCoverageIgnoreEnd
- if (stream_get_contents($this->stream, 3, 0) === "\x1f\x8b\x08") {
- $offsetStart = 10;
- }
- }
- $this->contentEncoding = false;
- return $this->handleCompression($filter, $offsetStart);
- }
- public function getContentLength()
- {
- return $this->getSize();
- }
- public function getContentType()
- {
- return $this->getUri() ? Mimetypes::getInstance()->fromFilename($this->getUri()) : null;
- }
- public function getContentMd5($rawOutput = false, $base64Encode = false)
- {
- if ($hash = self::getHash($this, 'md5', $rawOutput)) {
- return $hash && $base64Encode ? base64_encode($hash) : $hash;
- } else {
- return false;
- }
- }
- /**
- * Calculate the MD5 hash of an entity body
- *
- * @param EntityBodyInterface $body Entity body to calculate the hash for
- * @param bool $rawOutput Whether or not to use raw output
- * @param bool $base64Encode Whether or not to base64 encode raw output (only if raw output is true)
- *
- * @return bool|string Returns an MD5 string on success or FALSE on failure
- * @deprecated This will be deprecated soon
- * @codeCoverageIgnore
- */
- public static function calculateMd5(EntityBodyInterface $body, $rawOutput = false, $base64Encode = false)
- {
- Version::warn(__CLASS__ . ' is deprecated. Use getContentMd5()');
- return $body->getContentMd5($rawOutput, $base64Encode);
- }
- public function setStreamFilterContentEncoding($streamFilterContentEncoding)
- {
- $this->contentEncoding = $streamFilterContentEncoding;
- return $this;
- }
- public function getContentEncoding()
- {
- return strtr($this->contentEncoding, array(
- 'zlib.deflate' => 'gzip',
- 'bzip2.compress' => 'compress'
- )) ?: false;
- }
- protected function handleCompression($filter, $offsetStart = 0)
- {
- // @codeCoverageIgnoreStart
- if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
- return false;
- }
- // @codeCoverageIgnoreEnd
- $handle = fopen('php://temp', 'r+');
- $filter = @stream_filter_append($handle, $filter, STREAM_FILTER_WRITE);
- if (!$filter) {
- return false;
- }
- // Seek to the offset start if possible
- $this->seek($offsetStart);
- while ($data = fread($this->stream, 8096)) {
- fwrite($handle, $data);
- }
- fclose($this->stream);
- $this->stream = $handle;
- stream_filter_remove($filter);
- $stat = fstat($this->stream);
- $this->size = $stat['size'];
- $this->rebuildCache();
- $this->seek(0);
- // Remove any existing rewind function as the underlying stream has been replaced
- $this->rewindFunction = null;
- return true;
- }
- }
|