Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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