Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
namespace Guzzle\Http;
4
 
5
use Guzzle\Common\Version;
6
use Guzzle\Stream\Stream;
7
use Guzzle\Common\Exception\InvalidArgumentException;
8
use Guzzle\Http\Mimetypes;
9
 
10
/**
11
 * Entity body used with an HTTP request or response
12
 */
13
class EntityBody extends Stream implements EntityBodyInterface
14
{
15
    /** @var bool Content-Encoding of the entity body if known */
16
    protected $contentEncoding = false;
17
 
18
    /** @var callable Method to invoke for rewinding a stream */
19
    protected $rewindFunction;
20
 
21
    /**
22
     * Create a new EntityBody based on the input type
23
     *
24
     * @param resource|string|EntityBody $resource Entity body data
25
     * @param int                        $size     Size of the data contained in the resource
26
     *
27
     * @return EntityBody
28
     * @throws InvalidArgumentException if the $resource arg is not a resource or string
29
     */
30
    public static function factory($resource = '', $size = null)
31
    {
32
        if ($resource instanceof EntityBodyInterface) {
33
            return $resource;
34
        }
35
 
36
        switch (gettype($resource)) {
37
            case 'string':
38
                return self::fromString($resource);
39
            case 'resource':
40
                return new static($resource, $size);
41
            case 'object':
42
                if (method_exists($resource, '__toString')) {
43
                    return self::fromString((string) $resource);
44
                }
45
                break;
46
            case 'array':
47
                return self::fromString(http_build_query($resource));
48
        }
49
 
50
        throw new InvalidArgumentException('Invalid resource type');
51
    }
52
 
53
    public function setRewindFunction($callable)
54
    {
55
        if (!is_callable($callable)) {
56
            throw new InvalidArgumentException('Must specify a callable');
57
        }
58
 
59
        $this->rewindFunction = $callable;
60
 
61
        return $this;
62
    }
63
 
64
    public function rewind()
65
    {
66
        return $this->rewindFunction ? call_user_func($this->rewindFunction, $this) : parent::rewind();
67
    }
68
 
69
    /**
70
     * Create a new EntityBody from a string
71
     *
72
     * @param string $string String of data
73
     *
74
     * @return EntityBody
75
     */
76
    public static function fromString($string)
77
    {
78
        $stream = fopen('php://temp', 'r+');
79
        if ($string !== '') {
80
            fwrite($stream, $string);
81
            rewind($stream);
82
        }
83
 
84
        return new static($stream);
85
    }
86
 
87
    public function compress($filter = 'zlib.deflate')
88
    {
89
        $result = $this->handleCompression($filter);
90
        $this->contentEncoding = $result ? $filter : false;
91
 
92
        return $result;
93
    }
94
 
95
    public function uncompress($filter = 'zlib.inflate')
96
    {
97
        $offsetStart = 0;
98
 
99
        // When inflating gzipped data, the first 10 bytes must be stripped
100
        // if a gzip header is present
101
        if ($filter == 'zlib.inflate') {
102
            // @codeCoverageIgnoreStart
103
            if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
104
                return false;
105
            }
106
            // @codeCoverageIgnoreEnd
107
            if (stream_get_contents($this->stream, 3, 0) === "\x1f\x8b\x08") {
108
                $offsetStart = 10;
109
            }
110
        }
111
 
112
        $this->contentEncoding = false;
113
 
114
        return $this->handleCompression($filter, $offsetStart);
115
    }
116
 
117
    public function getContentLength()
118
    {
119
        return $this->getSize();
120
    }
121
 
122
    public function getContentType()
123
    {
124
        return $this->getUri() ? Mimetypes::getInstance()->fromFilename($this->getUri()) : null;
125
    }
126
 
127
    public function getContentMd5($rawOutput = false, $base64Encode = false)
128
    {
129
        if ($hash = self::getHash($this, 'md5', $rawOutput)) {
130
            return $hash && $base64Encode ? base64_encode($hash) : $hash;
131
        } else {
132
            return false;
133
        }
134
    }
135
 
136
    /**
137
     * Calculate the MD5 hash of an entity body
138
     *
139
     * @param EntityBodyInterface $body         Entity body to calculate the hash for
140
     * @param bool                $rawOutput    Whether or not to use raw output
141
     * @param bool                $base64Encode Whether or not to base64 encode raw output (only if raw output is true)
142
     *
143
     * @return bool|string Returns an MD5 string on success or FALSE on failure
144
     * @deprecated This will be deprecated soon
145
     * @codeCoverageIgnore
146
     */
147
    public static function calculateMd5(EntityBodyInterface $body, $rawOutput = false, $base64Encode = false)
148
    {
149
        Version::warn(__CLASS__ . ' is deprecated. Use getContentMd5()');
150
        return $body->getContentMd5($rawOutput, $base64Encode);
151
    }
152
 
153
    public function setStreamFilterContentEncoding($streamFilterContentEncoding)
154
    {
155
        $this->contentEncoding = $streamFilterContentEncoding;
156
 
157
        return $this;
158
    }
159
 
160
    public function getContentEncoding()
161
    {
162
        return strtr($this->contentEncoding, array(
163
            'zlib.deflate' => 'gzip',
164
            'bzip2.compress' => 'compress'
165
        )) ?: false;
166
    }
167
 
168
    protected function handleCompression($filter, $offsetStart = 0)
169
    {
170
        // @codeCoverageIgnoreStart
171
        if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
172
            return false;
173
        }
174
        // @codeCoverageIgnoreEnd
175
 
176
        $handle = fopen('php://temp', 'r+');
177
        $filter = @stream_filter_append($handle, $filter, STREAM_FILTER_WRITE);
178
        if (!$filter) {
179
            return false;
180
        }
181
 
182
        // Seek to the offset start if possible
183
        $this->seek($offsetStart);
184
        while ($data = fread($this->stream, 8096)) {
185
            fwrite($handle, $data);
186
        }
187
 
188
        fclose($this->stream);
189
        $this->stream = $handle;
190
        stream_filter_remove($filter);
191
        $stat = fstat($this->stream);
192
        $this->size = $stat['size'];
193
        $this->rebuildCache();
194
        $this->seek(0);
195
 
196
        // Remove any existing rewind function as the underlying stream has been replaced
197
        $this->rewindFunction = null;
198
 
199
        return true;
200
    }
201
}