1: <?php
2:
3: namespace Guzzle\Http;
4:
5: use Guzzle\Stream\Stream;
6: use Guzzle\Common\Exception\InvalidArgumentException;
7: use Guzzle\Http\Mimetypes;
8:
9: 10: 11:
12: class EntityBody extends Stream implements EntityBodyInterface
13: {
14: 15: 16:
17: protected $contentEncoding = false;
18:
19: 20: 21:
22: protected $rewindFunction;
23:
24: 25: 26: 27: 28: 29: 30: 31: 32:
33: public static function factory($resource = '', $size = null)
34: {
35: if ($resource instanceof EntityBodyInterface) {
36: return $resource;
37: }
38:
39: switch (gettype($resource)) {
40: case 'string':
41: return self::fromString($resource);
42: case 'resource':
43: return new static($resource, $size);
44: case 'object':
45: if (method_exists($resource, '__toString')) {
46: return self::fromString((string) $resource);
47: }
48: break;
49: case 'array':
50: return self::fromString(http_build_query($resource));
51: }
52:
53: throw new InvalidArgumentException('Invalid resource type');
54: }
55:
56: 57: 58:
59: public function setRewindFunction($callable)
60: {
61: if (!is_callable($callable)) {
62: throw new InvalidArgumentException('Must specify a callable');
63: }
64:
65: $this->rewindFunction = $callable;
66:
67: return $this;
68: }
69:
70: 71: 72:
73: public function rewind()
74: {
75: return $this->rewindFunction ? call_user_func($this->rewindFunction, $this) : parent::rewind();
76: }
77:
78: 79: 80: 81: 82: 83: 84:
85: public static function fromString($string)
86: {
87: $stream = fopen('php://temp', 'r+');
88: if ($string !== '') {
89: fwrite($stream, $string);
90: rewind($stream);
91: }
92:
93: return new static($stream);
94: }
95:
96: 97: 98:
99: public function compress($filter = 'zlib.deflate')
100: {
101: $result = $this->handleCompression($filter);
102: $this->contentEncoding = $result ? $filter : false;
103:
104: return $result;
105: }
106:
107: 108: 109:
110: public function uncompress($filter = 'zlib.inflate')
111: {
112: $offsetStart = 0;
113:
114:
115:
116: if ($filter == 'zlib.inflate') {
117:
118: if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
119: return false;
120: }
121:
122: if (stream_get_contents($this->stream, 3, 0) === "\x1f\x8b\x08") {
123: $offsetStart = 10;
124: }
125: }
126:
127: $this->contentEncoding = false;
128:
129: return $this->handleCompression($filter, $offsetStart);
130: }
131:
132: 133: 134:
135: public function getContentLength()
136: {
137: return $this->getSize();
138: }
139:
140: 141: 142:
143: public function getContentType()
144: {
145: return $this->getUri() ? Mimetypes::getInstance()->fromFilename($this->getUri()) : null;
146: }
147:
148: 149: 150:
151: public function getContentMd5($rawOutput = false, $base64Encode = false)
152: {
153: $hash = self::getHash($this, 'md5', $rawOutput);
154:
155: return $hash && $base64Encode ? base64_encode($hash) : $hash;
156: }
157:
158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168:
169: public static function calculateMd5(EntityBodyInterface $body, $rawOutput = false, $base64Encode = false)
170: {
171: return $body->getContentMd5($rawOutput, $base64Encode);
172: }
173:
174: 175: 176:
177: public function setStreamFilterContentEncoding($streamFilterContentEncoding)
178: {
179: $this->contentEncoding = $streamFilterContentEncoding;
180:
181: return $this;
182: }
183:
184: 185: 186:
187: public function getContentEncoding()
188: {
189: return strtr($this->contentEncoding, array(
190: 'zlib.deflate' => 'gzip',
191: 'bzip2.compress' => 'compress'
192: )) ?: false;
193: }
194:
195: 196: 197:
198: protected function handleCompression($filter, $offsetStart = 0)
199: {
200:
201: if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
202: return false;
203: }
204:
205:
206: $handle = fopen('php://temp', 'r+');
207: $filter = @stream_filter_append($handle, $filter, STREAM_FILTER_WRITE);
208: if (!$filter) {
209: return false;
210: }
211:
212:
213: $this->seek($offsetStart);
214: while ($data = fread($this->stream, 8096)) {
215: fwrite($handle, $data);
216: }
217:
218: fclose($this->stream);
219: $this->stream = $handle;
220: stream_filter_remove($filter);
221: $stat = fstat($this->stream);
222: $this->size = $stat['size'];
223: $this->rebuildCache();
224: $this->seek(0);
225:
226:
227: $this->rewindFunction = null;
228:
229: return true;
230: }
231: }
232: