Projet

Général

Profil

Paste
Télécharger (8,37 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / libraries / simplepie / library / SimplePie / gzdecode.php @ 41cc1b08

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-2012, 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.1
37
 * @copyright 2004-2012 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
 */
44

    
45

    
46
/**
47
 * Decode 'gzip' encoded HTTP data
48
 *
49
 * @package SimplePie
50
 * @subpackage HTTP
51
 * @link http://www.gzip.org/format.txt
52
 */
53
class SimplePie_gzdecode
54
{
55
        /**
56
         * Compressed data
57
         *
58
         * @access private
59
         * @var string
60
         * @see gzdecode::$data
61
         */
62
        var $compressed_data;
63

    
64
        /**
65
         * Size of compressed data
66
         *
67
         * @access private
68
         * @var int
69
         */
70
        var $compressed_size;
71

    
72
        /**
73
         * Minimum size of a valid gzip string
74
         *
75
         * @access private
76
         * @var int
77
         */
78
        var $min_compressed_size = 18;
79

    
80
        /**
81
         * Current position of pointer
82
         *
83
         * @access private
84
         * @var int
85
         */
86
        var $position = 0;
87

    
88
        /**
89
         * Flags (FLG)
90
         *
91
         * @access private
92
         * @var int
93
         */
94
        var $flags;
95

    
96
        /**
97
         * Uncompressed data
98
         *
99
         * @access public
100
         * @see gzdecode::$compressed_data
101
         * @var string
102
         */
103
        var $data;
104

    
105
        /**
106
         * Modified time
107
         *
108
         * @access public
109
         * @var int
110
         */
111
        var $MTIME;
112

    
113
        /**
114
         * Extra Flags
115
         *
116
         * @access public
117
         * @var int
118
         */
119
        var $XFL;
120

    
121
        /**
122
         * Operating System
123
         *
124
         * @access public
125
         * @var int
126
         */
127
        var $OS;
128

    
129
        /**
130
         * Subfield ID 1
131
         *
132
         * @access public
133
         * @see gzdecode::$extra_field
134
         * @see gzdecode::$SI2
135
         * @var string
136
         */
137
        var $SI1;
138

    
139
        /**
140
         * Subfield ID 2
141
         *
142
         * @access public
143
         * @see gzdecode::$extra_field
144
         * @see gzdecode::$SI1
145
         * @var string
146
         */
147
        var $SI2;
148

    
149
        /**
150
         * Extra field content
151
         *
152
         * @access public
153
         * @see gzdecode::$SI1
154
         * @see gzdecode::$SI2
155
         * @var string
156
         */
157
        var $extra_field;
158

    
159
        /**
160
         * Original filename
161
         *
162
         * @access public
163
         * @var string
164
         */
165
        var $filename;
166

    
167
        /**
168
         * Human readable comment
169
         *
170
         * @access public
171
         * @var string
172
         */
173
        var $comment;
174

    
175
        /**
176
         * Don't allow anything to be set
177
         *
178
         * @param string $name
179
         * @param mixed $value
180
         */
181
        public function __set($name, $value)
182
        {
183
                trigger_error("Cannot write property $name", E_USER_ERROR);
184
        }
185

    
186
        /**
187
         * Set the compressed string and related properties
188
         *
189
         * @param string $data
190
         */
191
        public function __construct($data)
192
        {
193
                $this->compressed_data = $data;
194
                $this->compressed_size = strlen($data);
195
        }
196

    
197
        /**
198
         * Decode the GZIP stream
199
         *
200
         * @return bool Successfulness
201
         */
202
        public function parse()
203
        {
204
                if ($this->compressed_size >= $this->min_compressed_size)
205
                {
206
                        // Check ID1, ID2, and CM
207
                        if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
208
                        {
209
                                return false;
210
                        }
211

    
212
                        // Get the FLG (FLaGs)
213
                        $this->flags = ord($this->compressed_data[3]);
214

    
215
                        // FLG bits above (1 << 4) are reserved
216
                        if ($this->flags > 0x1F)
217
                        {
218
                                return false;
219
                        }
220

    
221
                        // Advance the pointer after the above
222
                        $this->position += 4;
223

    
224
                        // MTIME
225
                        $mtime = substr($this->compressed_data, $this->position, 4);
226
                        // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
227
                        if (current(unpack('S', "\x00\x01")) === 1)
228
                        {
229
                                $mtime = strrev($mtime);
230
                        }
231
                        $this->MTIME = current(unpack('l', $mtime));
232
                        $this->position += 4;
233

    
234
                        // Get the XFL (eXtra FLags)
235
                        $this->XFL = ord($this->compressed_data[$this->position++]);
236

    
237
                        // Get the OS (Operating System)
238
                        $this->OS = ord($this->compressed_data[$this->position++]);
239

    
240
                        // Parse the FEXTRA
241
                        if ($this->flags & 4)
242
                        {
243
                                // Read subfield IDs
244
                                $this->SI1 = $this->compressed_data[$this->position++];
245
                                $this->SI2 = $this->compressed_data[$this->position++];
246

    
247
                                // SI2 set to zero is reserved for future use
248
                                if ($this->SI2 === "\x00")
249
                                {
250
                                        return false;
251
                                }
252

    
253
                                // Get the length of the extra field
254
                                $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
255
                                $this->position += 2;
256

    
257
                                // Check the length of the string is still valid
258
                                $this->min_compressed_size += $len + 4;
259
                                if ($this->compressed_size >= $this->min_compressed_size)
260
                                {
261
                                        // Set the extra field to the given data
262
                                        $this->extra_field = substr($this->compressed_data, $this->position, $len);
263
                                        $this->position += $len;
264
                                }
265
                                else
266
                                {
267
                                        return false;
268
                                }
269
                        }
270

    
271
                        // Parse the FNAME
272
                        if ($this->flags & 8)
273
                        {
274
                                // Get the length of the filename
275
                                $len = strcspn($this->compressed_data, "\x00", $this->position);
276

    
277
                                // Check the length of the string is still valid
278
                                $this->min_compressed_size += $len + 1;
279
                                if ($this->compressed_size >= $this->min_compressed_size)
280
                                {
281
                                        // Set the original filename to the given string
282
                                        $this->filename = substr($this->compressed_data, $this->position, $len);
283
                                        $this->position += $len + 1;
284
                                }
285
                                else
286
                                {
287
                                        return false;
288
                                }
289
                        }
290

    
291
                        // Parse the FCOMMENT
292
                        if ($this->flags & 16)
293
                        {
294
                                // Get the length of the comment
295
                                $len = strcspn($this->compressed_data, "\x00", $this->position);
296

    
297
                                // Check the length of the string is still valid
298
                                $this->min_compressed_size += $len + 1;
299
                                if ($this->compressed_size >= $this->min_compressed_size)
300
                                {
301
                                        // Set the original comment to the given string
302
                                        $this->comment = substr($this->compressed_data, $this->position, $len);
303
                                        $this->position += $len + 1;
304
                                }
305
                                else
306
                                {
307
                                        return false;
308
                                }
309
                        }
310

    
311
                        // Parse the FHCRC
312
                        if ($this->flags & 2)
313
                        {
314
                                // Check the length of the string is still valid
315
                                $this->min_compressed_size += $len + 2;
316
                                if ($this->compressed_size >= $this->min_compressed_size)
317
                                {
318
                                        // Read the CRC
319
                                        $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
320

    
321
                                        // Check the CRC matches
322
                                        if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
323
                                        {
324
                                                $this->position += 2;
325
                                        }
326
                                        else
327
                                        {
328
                                                return false;
329
                                        }
330
                                }
331
                                else
332
                                {
333
                                        return false;
334
                                }
335
                        }
336

    
337
                        // Decompress the actual data
338
                        if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
339
                        {
340
                                return false;
341
                        }
342
                        else
343
                        {
344
                                $this->position = $this->compressed_size - 8;
345
                        }
346

    
347
                        // Check CRC of data
348
                        $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
349
                        $this->position += 4;
350
                        /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
351
                        {
352
                                return false;
353
                        }*/
354

    
355
                        // Check ISIZE of data
356
                        $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
357
                        $this->position += 4;
358
                        if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
359
                        {
360
                                return false;
361
                        }
362

    
363
                        // Wow, against all odds, we've actually got a valid gzip string
364
                        return true;
365
                }
366
                else
367
                {
368
                        return false;
369
                }
370
        }
371
}