]> git.immae.eu Git - github/wallabag/wallabag.git/blob - inc/3rdparty/simplepie/SimplePie/gzdecode.php
Merge pull request #181 from inthepoche/dev
[github/wallabag/wallabag.git] / inc / 3rdparty / simplepie / SimplePie / gzdecode.php
1 <?php
2 /**
3 * SimplePie
4 *
5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
7 *
8 * Copyright (c) 2004-2009, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
13 *
14 * * Redistributions of source code must retain the above copyright notice, this list of
15 * conditions and the following disclaimer.
16 *
17 * * Redistributions in binary form must reproduce the above copyright notice, this list
18 * of conditions and the following disclaimer in the documentation and/or other materials
19 * provided with the distribution.
20 *
21 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
22 * to endorse or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * @package SimplePie
36 * @version 1.3-dev
37 * @copyright 2004-2010 Ryan Parman, Geoffrey Sneddon, Ryan McCue
38 * @author Ryan Parman
39 * @author Geoffrey Sneddon
40 * @author Ryan McCue
41 * @link http://simplepie.org/ SimplePie
42 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @todo phpDoc comments
44 */
45
46
47 /**
48 * gzdecode
49 *
50 * @package SimplePie
51 */
52 class SimplePie_gzdecode
53 {
54 /**
55 * Compressed data
56 *
57 * @access private
58 * @see gzdecode::$data
59 */
60 var $compressed_data;
61
62 /**
63 * Size of compressed data
64 *
65 * @access private
66 */
67 var $compressed_size;
68
69 /**
70 * Minimum size of a valid gzip string
71 *
72 * @access private
73 */
74 var $min_compressed_size = 18;
75
76 /**
77 * Current position of pointer
78 *
79 * @access private
80 */
81 var $position = 0;
82
83 /**
84 * Flags (FLG)
85 *
86 * @access private
87 */
88 var $flags;
89
90 /**
91 * Uncompressed data
92 *
93 * @access public
94 * @see gzdecode::$compressed_data
95 */
96 var $data;
97
98 /**
99 * Modified time
100 *
101 * @access public
102 */
103 var $MTIME;
104
105 /**
106 * Extra Flags
107 *
108 * @access public
109 */
110 var $XFL;
111
112 /**
113 * Operating System
114 *
115 * @access public
116 */
117 var $OS;
118
119 /**
120 * Subfield ID 1
121 *
122 * @access public
123 * @see gzdecode::$extra_field
124 * @see gzdecode::$SI2
125 */
126 var $SI1;
127
128 /**
129 * Subfield ID 2
130 *
131 * @access public
132 * @see gzdecode::$extra_field
133 * @see gzdecode::$SI1
134 */
135 var $SI2;
136
137 /**
138 * Extra field content
139 *
140 * @access public
141 * @see gzdecode::$SI1
142 * @see gzdecode::$SI2
143 */
144 var $extra_field;
145
146 /**
147 * Original filename
148 *
149 * @access public
150 */
151 var $filename;
152
153 /**
154 * Human readable comment
155 *
156 * @access public
157 */
158 var $comment;
159
160 /**
161 * Don't allow anything to be set
162 *
163 * @access public
164 */
165 public function __set($name, $value)
166 {
167 trigger_error("Cannot write property $name", E_USER_ERROR);
168 }
169
170 /**
171 * Set the compressed string and related properties
172 *
173 * @access public
174 */
175 public function __construct($data)
176 {
177 $this->compressed_data = $data;
178 $this->compressed_size = strlen($data);
179 }
180
181 /**
182 * Decode the GZIP stream
183 *
184 * @access public
185 */
186 public function parse()
187 {
188 if ($this->compressed_size >= $this->min_compressed_size)
189 {
190 // Check ID1, ID2, and CM
191 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
192 {
193 return false;
194 }
195
196 // Get the FLG (FLaGs)
197 $this->flags = ord($this->compressed_data[3]);
198
199 // FLG bits above (1 << 4) are reserved
200 if ($this->flags > 0x1F)
201 {
202 return false;
203 }
204
205 // Advance the pointer after the above
206 $this->position += 4;
207
208 // MTIME
209 $mtime = substr($this->compressed_data, $this->position, 4);
210 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
211 if (current(unpack('S', "\x00\x01")) === 1)
212 {
213 $mtime = strrev($mtime);
214 }
215 $this->MTIME = current(unpack('l', $mtime));
216 $this->position += 4;
217
218 // Get the XFL (eXtra FLags)
219 $this->XFL = ord($this->compressed_data[$this->position++]);
220
221 // Get the OS (Operating System)
222 $this->OS = ord($this->compressed_data[$this->position++]);
223
224 // Parse the FEXTRA
225 if ($this->flags & 4)
226 {
227 // Read subfield IDs
228 $this->SI1 = $this->compressed_data[$this->position++];
229 $this->SI2 = $this->compressed_data[$this->position++];
230
231 // SI2 set to zero is reserved for future use
232 if ($this->SI2 === "\x00")
233 {
234 return false;
235 }
236
237 // Get the length of the extra field
238 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
239 $this->position += 2;
240
241 // Check the length of the string is still valid
242 $this->min_compressed_size += $len + 4;
243 if ($this->compressed_size >= $this->min_compressed_size)
244 {
245 // Set the extra field to the given data
246 $this->extra_field = substr($this->compressed_data, $this->position, $len);
247 $this->position += $len;
248 }
249 else
250 {
251 return false;
252 }
253 }
254
255 // Parse the FNAME
256 if ($this->flags & 8)
257 {
258 // Get the length of the filename
259 $len = strcspn($this->compressed_data, "\x00", $this->position);
260
261 // Check the length of the string is still valid
262 $this->min_compressed_size += $len + 1;
263 if ($this->compressed_size >= $this->min_compressed_size)
264 {
265 // Set the original filename to the given string
266 $this->filename = substr($this->compressed_data, $this->position, $len);
267 $this->position += $len + 1;
268 }
269 else
270 {
271 return false;
272 }
273 }
274
275 // Parse the FCOMMENT
276 if ($this->flags & 16)
277 {
278 // Get the length of the comment
279 $len = strcspn($this->compressed_data, "\x00", $this->position);
280
281 // Check the length of the string is still valid
282 $this->min_compressed_size += $len + 1;
283 if ($this->compressed_size >= $this->min_compressed_size)
284 {
285 // Set the original comment to the given string
286 $this->comment = substr($this->compressed_data, $this->position, $len);
287 $this->position += $len + 1;
288 }
289 else
290 {
291 return false;
292 }
293 }
294
295 // Parse the FHCRC
296 if ($this->flags & 2)
297 {
298 // Check the length of the string is still valid
299 $this->min_compressed_size += $len + 2;
300 if ($this->compressed_size >= $this->min_compressed_size)
301 {
302 // Read the CRC
303 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
304
305 // Check the CRC matches
306 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
307 {
308 $this->position += 2;
309 }
310 else
311 {
312 return false;
313 }
314 }
315 else
316 {
317 return false;
318 }
319 }
320
321 // Decompress the actual data
322 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
323 {
324 return false;
325 }
326 else
327 {
328 $this->position = $this->compressed_size - 8;
329 }
330
331 // Check CRC of data
332 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
333 $this->position += 4;
334 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
335 {
336 return false;
337 }*/
338
339 // Check ISIZE of data
340 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
341 $this->position += 4;
342 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
343 {
344 return false;
345 }
346
347 // Wow, against all odds, we've actually got a valid gzip string
348 return true;
349 }
350 else
351 {
352 return false;
353 }
354 }
355 }