This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace iqb; |
||
4 | |||
5 | use const iqb\stream\SUBSTREAM_SCHEME; |
||
6 | use morgue\zip\CentralDirectoryHeader; |
||
7 | use morgue\zip\EndOfCentralDirectory; |
||
8 | use morgue\zip\LocalFileHeader; |
||
9 | use const morgue\zip\ZIP_COMPRESSION_METHOD_BZIP2; |
||
10 | use const morgue\zip\ZIP_COMPRESSION_METHOD_DEFLATE; |
||
11 | use const morgue\zip\ZIP_COMPRESSION_METHOD_DEFLATE64; |
||
12 | use const morgue\zip\ZIP_COMPRESSION_METHOD_IMPLODE; |
||
13 | use const morgue\zip\ZIP_COMPRESSION_METHOD_LZ77; |
||
14 | use const morgue\zip\ZIP_COMPRESSION_METHOD_LZMA; |
||
15 | use const morgue\zip\ZIP_COMPRESSION_METHOD_PKWARE_IMPLODE; |
||
16 | use const morgue\zip\ZIP_COMPRESSION_METHOD_PPMD; |
||
17 | use const morgue\zip\ZIP_COMPRESSION_METHOD_REDUCE_1; |
||
18 | use const morgue\zip\ZIP_COMPRESSION_METHOD_REDUCE_2; |
||
19 | use const morgue\zip\ZIP_COMPRESSION_METHOD_REDUCE_3; |
||
20 | use const morgue\zip\ZIP_COMPRESSION_METHOD_REDUCE_4; |
||
21 | use const morgue\zip\ZIP_COMPRESSION_METHOD_SHRINK; |
||
22 | use const morgue\zip\ZIP_COMPRESSION_METHOD_STORE; |
||
23 | use const morgue\zip\ZIP_COMPRESSION_METHOD_TERSE; |
||
24 | use const morgue\zip\ZIP_COMPRESSION_METHOD_TOKENIZE; |
||
25 | use const morgue\zip\ZIP_COMPRESSION_METHOD_WAVPACK; |
||
26 | |||
27 | /** |
||
28 | * |
||
29 | * @property-read int $status Status of the Zip Archive |
||
30 | * @property-read int statusSys System status of the Zip Archive |
||
31 | * @property-read int numFiles Number of files in the archive |
||
32 | * @property-read string $comment Comment for the archive |
||
33 | * @property-read string $filename File name in the file system |
||
34 | * |
||
35 | * @link http://php.net/manual/en/class.ziparchive.php |
||
36 | * @link http://php.net/manual/en/zip.constants.php |
||
37 | */ |
||
38 | class ZipArchive implements \Countable |
||
39 | { |
||
40 | // Flags for open |
||
41 | |||
42 | /** |
||
43 | * Create the archive if it does not exist |
||
44 | */ |
||
45 | const CREATE = 1; |
||
46 | |||
47 | /** |
||
48 | * Error if archive already exists |
||
49 | */ |
||
50 | const EXCL = 2; |
||
51 | |||
52 | /** |
||
53 | * Perform additional consistency checks on the archive, and error if they fail |
||
54 | */ |
||
55 | const CHECKCONS = 4; |
||
56 | |||
57 | /** |
||
58 | * Always start a new archive, this mode will overwrite the file if it already exists |
||
59 | */ |
||
60 | const OVERWRITE = 8; |
||
61 | |||
62 | // Generic flags |
||
63 | |||
64 | /** |
||
65 | * Ignore case on name lookup |
||
66 | */ |
||
67 | const FL_NOCASE = 1; |
||
68 | |||
69 | /** |
||
70 | * Ignore directory component |
||
71 | */ |
||
72 | const FL_NODIR = 2; |
||
73 | |||
74 | /** |
||
75 | * Read compressed data |
||
76 | */ |
||
77 | const FL_COMPRESSED = 4; |
||
78 | |||
79 | /** |
||
80 | * Use original data, ignoring changes. |
||
81 | */ |
||
82 | const FL_UNCHANGED = 8; |
||
83 | |||
84 | // Encoding flags |
||
85 | |||
86 | /** |
||
87 | * Guess string encoding (is default) |
||
88 | */ |
||
89 | const FL_ENC_GUESS = 0; |
||
90 | |||
91 | /** |
||
92 | * Get unmodified string |
||
93 | */ |
||
94 | const FL_ENC_RAW = 64; |
||
95 | |||
96 | /** |
||
97 | * Follow specification strictly |
||
98 | */ |
||
99 | const FL_ENC_STRICT = 128; |
||
100 | |||
101 | /** |
||
102 | * String is UTF-8 encoded |
||
103 | */ |
||
104 | const FL_ENC_UTF_8 = 2048; |
||
105 | |||
106 | /** |
||
107 | * String is CP437 encoded |
||
108 | */ |
||
109 | const FL_ENC_CP437 = 4096; |
||
110 | |||
111 | // Compression methods |
||
112 | |||
113 | /** |
||
114 | * Better of store or deflate |
||
115 | */ |
||
116 | const CM_DEFAULT = -1; |
||
117 | |||
118 | const CM_STORE = ZIP_COMPRESSION_METHOD_STORE; |
||
119 | const CM_SHRINK = ZIP_COMPRESSION_METHOD_SHRINK; |
||
120 | const CM_REDUCE_1 = ZIP_COMPRESSION_METHOD_REDUCE_1; |
||
121 | const CM_REDUCE_2 = ZIP_COMPRESSION_METHOD_REDUCE_2; |
||
122 | const CM_REDUCE_3 = ZIP_COMPRESSION_METHOD_REDUCE_3; |
||
123 | const CM_REDUCE_4 = ZIP_COMPRESSION_METHOD_REDUCE_4; |
||
124 | const CM_IMPLODE = ZIP_COMPRESSION_METHOD_IMPLODE; |
||
125 | const CM_TOKENIZE = ZIP_COMPRESSION_METHOD_TOKENIZE; |
||
126 | const CM_DEFLATE = ZIP_COMPRESSION_METHOD_DEFLATE; |
||
127 | const CM_DEFLATE64 = ZIP_COMPRESSION_METHOD_DEFLATE64; |
||
128 | const CM_PKWARE_IMPLODE = ZIP_COMPRESSION_METHOD_PKWARE_IMPLODE; |
||
129 | const CM_BZIP2 = ZIP_COMPRESSION_METHOD_BZIP2; |
||
130 | const CM_LZMA = ZIP_COMPRESSION_METHOD_LZMA; |
||
131 | const CM_TERSE = ZIP_COMPRESSION_METHOD_TERSE; |
||
132 | const CM_LZ77 = ZIP_COMPRESSION_METHOD_LZ77; |
||
133 | const CM_WAVPACK = ZIP_COMPRESSION_METHOD_WAVPACK; |
||
134 | const CM_PPMD = ZIP_COMPRESSION_METHOD_PPMD; |
||
135 | |||
136 | // Error constants |
||
137 | |||
138 | /** |
||
139 | * No error |
||
140 | */ |
||
141 | const ER_OK = 0; |
||
142 | |||
143 | /** |
||
144 | * Multi-disk zip archives not supported |
||
145 | */ |
||
146 | const ER_MULTIDISK = 1; |
||
147 | |||
148 | /** |
||
149 | * Renaming temporary file failed |
||
150 | */ |
||
151 | const ER_RENAME = 2; |
||
152 | |||
153 | /** |
||
154 | * Closing zip archive failed |
||
155 | */ |
||
156 | const ER_CLOSE = 3; |
||
157 | |||
158 | /** |
||
159 | * Seek error |
||
160 | */ |
||
161 | const ER_SEEK = 4; |
||
162 | |||
163 | /** |
||
164 | * Read error |
||
165 | */ |
||
166 | const ER_READ = 5; |
||
167 | |||
168 | /** |
||
169 | * Write error |
||
170 | */ |
||
171 | const ER_WRITE = 6; |
||
172 | |||
173 | /** |
||
174 | * CRC error |
||
175 | */ |
||
176 | const ER_CRC = 7; |
||
177 | |||
178 | /** |
||
179 | * Containing zip archive was closed |
||
180 | */ |
||
181 | const ER_ZIPCLOSED = 8; |
||
182 | |||
183 | /** |
||
184 | * No such file |
||
185 | */ |
||
186 | const ER_NOENT = 9; |
||
187 | |||
188 | /** |
||
189 | * File already exists |
||
190 | */ |
||
191 | const ER_EXISTS = 10; |
||
192 | |||
193 | /** |
||
194 | * Can't open file |
||
195 | */ |
||
196 | const ER_OPEN = 11; |
||
197 | |||
198 | /** |
||
199 | * Failure to create temporary file |
||
200 | */ |
||
201 | const ER_TMPOPEN = 12; |
||
202 | |||
203 | /** |
||
204 | * Zlib error |
||
205 | */ |
||
206 | const ER_ZLIB = 13; |
||
207 | |||
208 | /** |
||
209 | * Memory allocation failure |
||
210 | */ |
||
211 | const ER_MEMORY = 14; |
||
212 | |||
213 | /** |
||
214 | * Entry has been changed |
||
215 | */ |
||
216 | const ER_CHANGED = 15; |
||
217 | |||
218 | /** |
||
219 | * Compression method not supported |
||
220 | */ |
||
221 | const ER_COMPNOTSUPP = 16; |
||
222 | |||
223 | /** |
||
224 | * Premature EOF |
||
225 | */ |
||
226 | const ER_EOF = 17; |
||
227 | |||
228 | /** |
||
229 | * Invalid argument |
||
230 | */ |
||
231 | const ER_INVAL = 18; |
||
232 | |||
233 | /** |
||
234 | * Not a zip archive |
||
235 | */ |
||
236 | const ER_NOZIP = 19; |
||
237 | |||
238 | /** |
||
239 | * Internal error |
||
240 | */ |
||
241 | const ER_INTERNAL = 20; |
||
242 | |||
243 | /** |
||
244 | * Zip archive inconsistent |
||
245 | */ |
||
246 | const ER_INCONS = 21; |
||
247 | |||
248 | /** |
||
249 | * Can't remove file |
||
250 | */ |
||
251 | const ER_REMOVE = 22; |
||
252 | |||
253 | /** |
||
254 | * Entry has been deleted |
||
255 | */ |
||
256 | const ER_DELETED = 23; |
||
257 | |||
258 | // Encryption |
||
259 | |||
260 | /** |
||
261 | * No encryption |
||
262 | */ |
||
263 | const EM_NONE = 0; |
||
264 | |||
265 | /** |
||
266 | * AES 128 encryption |
||
267 | */ |
||
268 | const EM_AES_128 = 257; |
||
269 | |||
270 | /** |
||
271 | * AES 192 encryption |
||
272 | */ |
||
273 | const EM_AES_192 = 258; |
||
274 | |||
275 | /** |
||
276 | * AES 256 encryption |
||
277 | */ |
||
278 | const EM_AES_256 = 259; |
||
279 | |||
280 | // Operating system constants for external attributes |
||
281 | |||
282 | /** |
||
283 | * MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) |
||
284 | */ |
||
285 | const OPSYS_DOS = 0; |
||
286 | |||
287 | /** |
||
288 | * Amiga |
||
289 | */ |
||
290 | const OPSYS_AMIGA = 1; |
||
291 | |||
292 | /** |
||
293 | * OpenVMS |
||
294 | */ |
||
295 | const OPSYS_OPENVMS = 2; |
||
296 | |||
297 | /** |
||
298 | * UNIX |
||
299 | */ |
||
300 | const OPSYS_UNIX = 3; |
||
301 | |||
302 | /** |
||
303 | * VM/CMS |
||
304 | */ |
||
305 | const OPSYS_VM_CMS = 4; |
||
306 | |||
307 | /** |
||
308 | * Atari ST |
||
309 | */ |
||
310 | const OPSYS_ATARI_ST = 5; |
||
311 | |||
312 | /** |
||
313 | * OS/2 H.P.F.S. |
||
314 | */ |
||
315 | const OPSYS_OS_2 = 6; |
||
316 | |||
317 | /** |
||
318 | * Macintosh |
||
319 | */ |
||
320 | const OPSYS_MACINTOSH = 7; |
||
321 | |||
322 | /** |
||
323 | * Z-System |
||
324 | */ |
||
325 | const OPSYS_Z_SYSTEM = 8; |
||
326 | |||
327 | /** |
||
328 | * CP/M |
||
329 | */ |
||
330 | const OPSYS_CPM = 9; |
||
331 | const OPSYS_Z_CPM = self::OPSYS_CPM; |
||
332 | |||
333 | /** |
||
334 | * Windows NTFS |
||
335 | */ |
||
336 | const OPSYS_WINDOWS_NTFS = 10; |
||
337 | |||
338 | /** |
||
339 | * MVS (OS/390 - Z/OS) |
||
340 | */ |
||
341 | const OPSYS_MVS = 11; |
||
342 | |||
343 | /** |
||
344 | * VSE |
||
345 | */ |
||
346 | const OPSYS_VSE = 12; |
||
347 | |||
348 | /** |
||
349 | * Acorn Risc |
||
350 | */ |
||
351 | const OPSYS_ACORN_RISC = 13; |
||
352 | |||
353 | /** |
||
354 | * VFAT |
||
355 | */ |
||
356 | const OPSYS_VFAT = 14; |
||
357 | |||
358 | /** |
||
359 | * alternate MVS |
||
360 | */ |
||
361 | const OPSYS_ALTERNATE_MVS = 15; |
||
362 | |||
363 | /** |
||
364 | * BeOS |
||
365 | */ |
||
366 | const OPSYS_BEOS = 16; |
||
367 | |||
368 | /** |
||
369 | * Tandem |
||
370 | */ |
||
371 | const OPSYS_TANDEM = 17; |
||
372 | |||
373 | /** |
||
374 | * OS/400 |
||
375 | */ |
||
376 | const OPSYS_OS_400 = 18; |
||
377 | |||
378 | /** |
||
379 | * OS X (Darwin) |
||
380 | */ |
||
381 | const OPSYS_OS_X = 19; |
||
382 | |||
383 | const OPSYS_DEFAULT = self::OPSYS_UNIX; |
||
384 | |||
385 | /** |
||
386 | * @var bool |
||
387 | */ |
||
388 | private $bzip2Support = false; |
||
389 | |||
390 | /** |
||
391 | * @var bool |
||
392 | */ |
||
393 | private $deflateSupport = false; |
||
394 | |||
395 | /** |
||
396 | * Status of the Zip Archive |
||
397 | * @var int |
||
398 | */ |
||
399 | private $status = 0; |
||
400 | |||
401 | /** |
||
402 | * System status of the Zip Archive |
||
403 | * @var int |
||
404 | */ |
||
405 | private $statusSys = 0; |
||
406 | |||
407 | /** |
||
408 | * File name in the file system |
||
409 | * @var string |
||
410 | */ |
||
411 | private $filename; |
||
412 | |||
413 | /** |
||
414 | * @var resource |
||
415 | */ |
||
416 | private $handle; |
||
417 | |||
418 | /** |
||
419 | * @var CentralDirectoryHeader[] |
||
420 | */ |
||
421 | private $originalCentralDirectory = []; |
||
422 | |||
423 | /** |
||
424 | * @var EndOfCentralDirectory |
||
425 | */ |
||
426 | private $originalEndOfCentralDirectory; |
||
427 | |||
428 | /** |
||
429 | * @var CentralDirectoryHeader[] |
||
430 | */ |
||
431 | private $modifiedCentralDirectory = []; |
||
432 | |||
433 | /** |
||
434 | * @var EndOfCentralDirectory |
||
435 | */ |
||
436 | private $modifiedEndOfCentralDirectory; |
||
437 | |||
438 | |||
439 | 2048 | public function __construct() |
|
440 | { |
||
441 | 2048 | $this->deflateSupport(true); |
|
442 | 2048 | $this->bzip2Support(true); |
|
443 | 2048 | } |
|
444 | |||
445 | |||
446 | /** |
||
447 | * Enable or disable deflate compression support. |
||
448 | * Can be called without parameter to check status. |
||
449 | * |
||
450 | * @param bool $enableSupport Enable or disable deflate compression support |
||
451 | * @return bool The deflate compression support status valid from now on |
||
452 | */ |
||
453 | 2048 | public function deflateSupport(bool $enableSupport = null) |
|
454 | { |
||
455 | 2048 | if ($enableSupport !== null) { |
|
456 | 2048 | $this->deflateSupport = ($enableSupport && \in_array('zlib.*', \stream_get_filters())); |
|
457 | } |
||
458 | |||
459 | 2048 | return $this->deflateSupport; |
|
460 | } |
||
461 | |||
462 | |||
463 | /** |
||
464 | * Enable or disable BZip2 compression support. |
||
465 | * Can be called without parameter to check status. |
||
466 | * |
||
467 | * @param bool $enableSupport Enable or disable BZip2 compression support |
||
468 | * @return bool The BZip2 support status valid from now on |
||
469 | */ |
||
470 | 2048 | public function bzip2Support(bool $enableSupport = null) |
|
471 | { |
||
472 | 2048 | if ($enableSupport !== null) { |
|
473 | 2048 | $this->bzip2Support = ($enableSupport && \in_array('bzip2.*', \stream_get_filters())); |
|
474 | } |
||
475 | |||
476 | 2048 | return $this->bzip2Support; |
|
477 | } |
||
478 | |||
479 | |||
480 | /** |
||
481 | * Emulate read-only access to class variables |
||
482 | */ |
||
483 | 2045 | public function __get(string $name) |
|
484 | { |
||
485 | 2045 | if ($name === 'status') { |
|
486 | 2044 | return $this->status; |
|
487 | 2045 | } elseif ($name === 'statusSys') { |
|
488 | 2044 | return $this->statusSys; |
|
489 | 2045 | } elseif ($name === 'filename') { |
|
490 | 2043 | return $this->filename; |
|
491 | 2045 | } elseif ($name === 'numFiles') { |
|
492 | 2044 | return $this->count(); |
|
493 | 2045 | } elseif ($name === 'comment') { |
|
494 | 2045 | return $this->getArchiveComment(); |
|
495 | } |
||
496 | } |
||
497 | |||
498 | |||
499 | /** |
||
500 | * Emulate writes that vanish into the air for class variables |
||
501 | */ |
||
502 | 2048 | public function __set(string $name, $value) |
|
503 | { |
||
504 | 2048 | } |
|
505 | |||
506 | |||
507 | /** |
||
508 | * @implements \Countable |
||
509 | * @return int |
||
510 | */ |
||
511 | 2044 | public function count() |
|
512 | { |
||
513 | 2044 | return \count($this->modifiedCentralDirectory); |
|
514 | } |
||
515 | |||
516 | |||
517 | 2048 | public function open(string $filename) |
|
518 | { |
||
519 | 2048 | $this->filename = \realpath($filename); |
|
520 | 2048 | $this->handle = \fopen($this->filename, 'r+'); |
|
521 | |||
522 | // Find end of central directory |
||
523 | 2048 | $this->originalEndOfCentralDirectory = $this->modifiedEndOfCentralDirectory = $this->findEndOfCentralDirectory(); |
|
524 | |||
525 | // Read central directory |
||
526 | 2048 | if (\fseek($this->handle, $this->originalEndOfCentralDirectory->getOffsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber()) === -1) { |
|
527 | throw new \RuntimeException("Unable to read Central Directory"); |
||
528 | } |
||
529 | |||
530 | 2048 | $centralDirectoryData = \fread($this->handle, $this->originalEndOfCentralDirectory->getSizeOfTheCentralDirectory()); |
|
531 | 2048 | $offset = 0; |
|
532 | |||
533 | 2048 | for ($i=0; $i<$this->originalEndOfCentralDirectory->getTotalNumberOfEntriesInTheCentralDirectory(); $i++) { |
|
534 | 2048 | $centralDirectoryEntry = CentralDirectoryHeader::parse($centralDirectoryData, $offset); |
|
535 | 2048 | $offset += CentralDirectoryHeader::MIN_LENGTH; |
|
536 | |||
537 | 2048 | if ($centralDirectoryEntry->getVariableLength() > 0) { |
|
538 | 2048 | $offset += $centralDirectoryEntry->parseAdditionalData($centralDirectoryData, $offset); |
|
539 | } |
||
540 | |||
541 | 2048 | $this->originalCentralDirectory[] = $centralDirectoryEntry; |
|
542 | } |
||
543 | |||
544 | 2048 | $this->modifiedCentralDirectory = $this->originalCentralDirectory; |
|
545 | 2048 | $this->numFiles = \count($this->originalCentralDirectory); |
|
546 | 2048 | } |
|
547 | |||
548 | |||
549 | /** |
||
550 | * @return EndOfCentralDirectory|null |
||
551 | */ |
||
552 | 2048 | private function findEndOfCentralDirectory() |
|
553 | { |
||
554 | 2048 | $signature = \pack('N', EndOfCentralDirectory::SIGNATURE); |
|
555 | |||
556 | 2048 | for ($offset = EndOfCentralDirectory::MIN_LENGTH; $offset <= EndOfCentralDirectory::MAX_LENGTH; $offset++) { |
|
557 | 2048 | if (\fseek($this->handle, -$offset, \SEEK_END) === -1) { |
|
558 | throw new \RuntimeException("Can not find EndOfDirectoryDirectory record"); |
||
559 | } |
||
560 | |||
561 | 2048 | $chunk = \fread($this->handle, EndOfCentralDirectory::MIN_LENGTH); |
|
562 | 2048 | if (\substr($chunk, 0, \strlen($signature)) !== $signature) { |
|
563 | 2042 | continue; |
|
564 | } |
||
565 | |||
566 | 2048 | $endOfCentralDirectory = EndOfCentralDirectory::parse($chunk); |
|
567 | 2048 | if ($endOfCentralDirectory->getVariableLength() > 0) { |
|
568 | 2042 | $additionalData = \fread($this->handle, $endOfCentralDirectory->getVariableLength()); |
|
569 | 2042 | $endOfCentralDirectory->parseAdditionalData($additionalData); |
|
570 | } |
||
571 | |||
572 | 2048 | return $endOfCentralDirectory; |
|
573 | } |
||
574 | |||
575 | return null; |
||
576 | } |
||
577 | |||
578 | |||
579 | /** |
||
580 | * Returns the Zip archive comment |
||
581 | * |
||
582 | * @param int $flags ZipArchive::FL_UNCHANGED or 0 |
||
583 | * @return string|bool |
||
584 | * |
||
585 | * @link http://php.net/manual/en/ziparchive.getarchivecomment.php |
||
586 | */ |
||
587 | 2045 | final public function getArchiveComment(int $flags = null) |
|
588 | { |
||
589 | 2045 | $validFlags = (is_null($flags) ? 0 : $flags & self::FL_UNCHANGED); |
|
590 | |||
591 | 2045 | if ($validFlags & self::FL_UNCHANGED) { |
|
592 | 1 | return $this->originalEndOfCentralDirectory->getZipFileComment(); |
|
593 | } |
||
594 | |||
595 | else { |
||
596 | 2045 | return $this->modifiedEndOfCentralDirectory->getZipFileComment(); |
|
597 | } |
||
598 | } |
||
599 | |||
600 | |||
601 | /** |
||
602 | * Returns the comment of an entry using the entry index. |
||
603 | * |
||
604 | * @param int $index Index of the entry |
||
605 | * @param int $flags ZipArchive::FL_UNCHANGED or 0 |
||
606 | * @return string|false |
||
607 | * |
||
608 | * @link http://php.net/manual/en/ziparchive.getcommentindex.php |
||
609 | */ |
||
610 | 73 | final public function getCommentIndex(int $index, int $flags = null) |
|
611 | { |
||
612 | 73 | $validFlags = (is_null($flags) ? 0 : $flags & self::FL_UNCHANGED); |
|
613 | 73 | $directory = ($validFlags & self::FL_UNCHANGED ? $this->originalCentralDirectory : $this->modifiedCentralDirectory); |
|
614 | |||
615 | 73 | if (isset($directory[$index])) { |
|
616 | 72 | $this->status = self::ER_OK; |
|
617 | 72 | return $directory[$index]->getFileComment(); |
|
618 | } else { |
||
619 | 1 | $this->status = self::ER_INVAL; |
|
620 | 1 | return false; |
|
621 | } |
||
622 | } |
||
623 | |||
624 | |||
625 | /** |
||
626 | * Returns the comment of an entry using the entry name |
||
627 | * |
||
628 | * @param string $name Name of the entry |
||
629 | * @param int $flags Any combination of ZipArchive::FL_UNCHANGED |
||
630 | * @return string|false |
||
631 | * |
||
632 | * @link http://php.net/manual/en/ziparchive.getcommentname.php |
||
633 | */ |
||
634 | 211 | final public function getCommentName(string $name, int $flags = null) |
|
635 | { |
||
636 | 211 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_UNCHANGED)); |
|
637 | |||
638 | 211 | if (($index = $this->locateName($name, $validFlags)) !== false) { |
|
639 | // Hack to align behaviour with \ZipArchive |
||
640 | 56 | if ($flags & self::FL_NODIR) { |
|
641 | 32 | $this->status = self::ER_NOENT; |
|
642 | } |
||
643 | 56 | return $this->getCommentIndex($index, $validFlags); |
|
644 | } else { |
||
645 | 155 | return false; |
|
646 | } |
||
647 | } |
||
648 | |||
649 | |||
650 | /** |
||
651 | * Retrieve the external attributes of an entry defined by its index |
||
652 | * |
||
653 | * @param int $index Index of the entry. |
||
654 | * @param int $opsys On success, receive the operating system code defined by one of the ZipArchive::OPSYS_ constants. |
||
655 | * @param int $attr On success, receive the external attributes. Value depends on operating system. |
||
656 | * @param int $flags ZipArchive::FL_UNCHANGED or 0 |
||
657 | * @return bool |
||
658 | * |
||
659 | * @link http://php.net/manual/en/ziparchive.getexternalattributesindex.php |
||
660 | */ |
||
661 | 54 | final public function getExternalAttributesIndex(int $index, &$opsys, &$attr, int $flags = null) |
|
662 | { |
||
663 | 54 | $validFlags = (is_null($flags) ? 0 : $flags & self::FL_UNCHANGED); |
|
664 | 54 | $directory = ($validFlags & self::FL_UNCHANGED ? $this->originalCentralDirectory : $this->modifiedCentralDirectory); |
|
665 | |||
666 | 54 | if (!isset($directory[$index])) { |
|
667 | return false; |
||
668 | } |
||
669 | |||
670 | 54 | $opsys = $directory[$index]->getEncodingHost(); |
|
671 | 54 | $attr = $directory[$index]->getExternalFileAttributes(); |
|
672 | |||
673 | 54 | return true; |
|
674 | } |
||
675 | |||
676 | |||
677 | /** |
||
678 | * Retrieve the external attributes of an entry defined by its name |
||
679 | * |
||
680 | * @param string $name Name of the entry. |
||
681 | * @param int $opsys On success, receive the operating system code defined by one of the ZipArchive::OPSYS_ constants. |
||
682 | * @param int $attr On success, receive the external attributes. Value depends on operating system. |
||
683 | * @param int $flags ZipArchive::FL_UNCHANGED or 0 |
||
684 | * @return bool |
||
685 | * |
||
686 | * @link http://php.net/manual/en/ziparchive.getexternalattributesname.php |
||
687 | */ |
||
688 | 168 | final public function getExternalAttributesName(string $name, &$opsys, &$attr, int $flags = null) |
|
689 | { |
||
690 | 168 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_UNCHANGED)); |
|
691 | |||
692 | 168 | if (($index = $this->locateName($name, $validFlags)) !== false) { |
|
693 | 42 | return $this->getExternalAttributesIndex($index, $opsys, $attr, $flags); |
|
694 | } else { |
||
695 | 126 | return false; |
|
696 | } |
||
697 | } |
||
698 | |||
699 | |||
700 | /** |
||
701 | * Returns the entry contents using its index |
||
702 | * |
||
703 | * @param int $index Index of the entry |
||
704 | * @param int $length The length to be read from the entry. If 0, then the entire entry is read. |
||
705 | * @param int $flags Any combination of ZipArchive::FL_COMPRESSED|ZipArchive::FL_UNCHANGED |
||
706 | * @return string|false |
||
707 | * |
||
708 | * @link http://php.net/manual/en/ziparchive.getfromindex.php |
||
709 | */ |
||
710 | 486 | final public function getFromIndex(int $index, int $length = null, int $flags = null) |
|
711 | { |
||
712 | 486 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_COMPRESSED|self::FL_UNCHANGED)); |
|
713 | |||
714 | 486 | if (($stream = $this->getStreamIndex($index, $validFlags)) === false) { |
|
715 | 1 | return false; |
|
716 | } |
||
717 | |||
718 | 485 | $length = (is_null($length) ? 0 : $length); |
|
719 | 485 | $string = ''; |
|
720 | do { |
||
721 | 485 | $chunkSize = ($length ? $length - \strlen($string) : 8192); |
|
722 | 485 | if (($chunk = \fread($stream, $chunkSize)) !== false) { |
|
723 | 485 | $string .= $chunk; |
|
724 | } else { |
||
725 | break; |
||
726 | } |
||
727 | 485 | } while (!\feof($stream) && ($length === 0 || \strlen($string) < $length)); |
|
728 | |||
729 | 485 | return $string; |
|
730 | } |
||
731 | |||
732 | |||
733 | /** |
||
734 | * Returns the entry contents using its name |
||
735 | * |
||
736 | * @param string $name Name of the entry |
||
737 | * @param int $length The length to be read from the entry. If 0, then the entire entry is read. |
||
738 | * @param int $flags Any combination of ZipArchive::FL_COMPRESSED|ZipArchive::FL_NOCASE|ZipArchive::FL_UNCHANGED |
||
739 | * @return bool |
||
740 | * |
||
741 | * @link http://php.net/manual/en/ziparchive.getfromname.php |
||
742 | */ |
||
743 | 1320 | View Code Duplication | final public function getFromName(string $name, int $length = null, int $flags = null) |
0 ignored issues
–
show
|
|||
744 | { |
||
745 | 1320 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_COMPRESSED|self::FL_NOCASE|self::FL_NODIR|self::FL_UNCHANGED)); |
|
746 | |||
747 | 1320 | if (($index = $this->locateName($name, $validFlags)) === false) { |
|
748 | 960 | return false; |
|
749 | } |
||
750 | |||
751 | 360 | return $this->getFromIndex($index, $length, $validFlags); |
|
752 | } |
||
753 | |||
754 | |||
755 | /** |
||
756 | * @return string |
||
757 | */ |
||
758 | 2031 | final public function getStatusString() |
|
759 | { |
||
760 | 2031 | switch ($this->status) { |
|
761 | 2031 | case self::ER_OK: |
|
762 | 662 | return "No error"; |
|
763 | |||
764 | 1369 | case self::ER_NOENT: |
|
765 | 1367 | return "No such file"; |
|
766 | |||
767 | 2 | case self::ER_COMPNOTSUPP: |
|
768 | 1 | return "Compression method not supported"; |
|
769 | |||
770 | 1 | case self::ER_INVAL: |
|
771 | 1 | return "Invalid argument"; |
|
772 | |||
773 | default: |
||
774 | return ""; |
||
775 | } |
||
776 | } |
||
777 | |||
778 | |||
779 | /** |
||
780 | * Get a file handler to the entry defined by its name (read only) |
||
781 | * |
||
782 | * @param string $name The name of the entry to use. |
||
783 | * @return resource|false |
||
784 | * |
||
785 | * @link http://php.net/manual/en/ziparchive.getstream.php |
||
786 | */ |
||
787 | 6 | final public function getStream(string $name) |
|
788 | { |
||
789 | 6 | return $this->getStreamName($name); |
|
790 | } |
||
791 | |||
792 | |||
793 | /** |
||
794 | * Get a file handle to the entry defined by its index (read only) |
||
795 | * |
||
796 | * @param int $index Index of the entry |
||
797 | * @param int $flags Any combination of ZipArchive::FL_COMPRESSED|ZipArchive::FL_UNCHANGED |
||
798 | * @return resource|false |
||
799 | */ |
||
800 | 486 | final public function getStreamIndex(int $index, int $flags = null) |
|
801 | { |
||
802 | 486 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_COMPRESSED|self::FL_UNCHANGED)); |
|
803 | 486 | $directory = ($validFlags & self::FL_UNCHANGED ? $this->originalCentralDirectory : $this->modifiedCentralDirectory); |
|
804 | |||
805 | 486 | $this->status = self::ER_OK; |
|
806 | |||
807 | 486 | if (!isset($directory[$index])) { |
|
808 | return false; |
||
809 | } |
||
810 | 486 | $entry = $directory[$index]; |
|
811 | |||
812 | 486 | if ($entry->getCompressedSize() === 0) { |
|
813 | 165 | return \fopen('php://memory', 'r'); |
|
814 | } |
||
815 | |||
816 | 321 | \fseek($this->handle, $entry->getRelativeOffsetOfLocalHeader()); |
|
817 | 321 | $localHeader = LocalFileHeader::parse(\fread($this->handle, LocalFileHeader::MIN_LENGTH)); |
|
818 | 321 | if ($localHeader->getVariableLength() > 0) { |
|
819 | 321 | $localHeader->parseAdditionalData(\fread($this->handle, $localHeader->getVariableLength())); |
|
820 | } |
||
821 | |||
822 | 321 | $offset = \ftell($this->handle); |
|
823 | 321 | $length = $entry->getCompressedSize(); |
|
824 | |||
825 | 321 | if (($handle = \fopen(SUBSTREAM_SCHEME . '://' . $offset . ':' . $length . '/' . (int)$this->handle, 'r')) === false) { |
|
826 | return false; |
||
827 | } |
||
828 | |||
829 | 321 | if (($entry->getCompressionMethod() === self::CM_STORE) || ($validFlags & self::FL_COMPRESSED)) { |
|
830 | 137 | return $handle; |
|
831 | } |
||
832 | |||
833 | 184 | elseif ($this->deflateSupport && ($entry->getCompressionMethod() === self::CM_DEFLATE)) { |
|
834 | 182 | \stream_filter_append($handle, 'zlib.inflate', \STREAM_FILTER_READ); |
|
835 | 182 | return $handle; |
|
836 | } |
||
837 | |||
838 | 2 | elseif ($this->bzip2Support && ($entry->getCompressionMethod() === self::CM_BZIP2)) { |
|
839 | 1 | \stream_filter_append($handle, 'bzip2.decompress', \STREAM_FILTER_READ); |
|
840 | 1 | return $handle; |
|
841 | } |
||
842 | |||
843 | else { |
||
844 | 1 | $this->status = self::ER_COMPNOTSUPP; |
|
845 | 1 | return false; |
|
846 | } |
||
847 | } |
||
848 | |||
849 | |||
850 | /** |
||
851 | * Get a file handler to the entry defined by its name (read only) |
||
852 | * |
||
853 | * @param string $name The name of the entry to use. |
||
854 | * @param int|null $flags Any combination of ZipArchive::FL_COMPRESSED|ZipArchive::FL_NOCASE|ZipArchive::FL_NODIR|ZipArchive::FL_UNCHANGED |
||
855 | * @return resource|false |
||
856 | */ |
||
857 | 6 | View Code Duplication | public function getStreamName(string $name, int $flags = null) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
858 | { |
||
859 | 6 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_COMPRESSED|self::FL_NOCASE|self::FL_NODIR|self::FL_UNCHANGED)); |
|
860 | |||
861 | 6 | if (($index = $this->locateName($name, $validFlags)) === false) { |
|
862 | 6 | return false; |
|
863 | } |
||
864 | |||
865 | return $this->getStreamIndex($index, $validFlags); |
||
866 | } |
||
867 | |||
868 | |||
869 | /** |
||
870 | * Returns the index of the entry in the archive |
||
871 | * |
||
872 | * @param string $name The name of the entry to look up |
||
873 | * @param int $flags Any combination of ZipArchive::FL_NOCASE|ZipArchive::FL_NODIR |
||
874 | * @return int|false |
||
875 | * |
||
876 | * @link http://php.net/manual/en/ziparchive.locatename.php |
||
877 | */ |
||
878 | 1879 | final public function locateName(string $name, int $flags = 0) |
|
879 | { |
||
880 | 1879 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_NOCASE|self::FL_NODIR)); |
|
881 | 1879 | $this->status = self::ER_OK; |
|
882 | |||
883 | 1879 | $ignoreCase = (($validFlags & self::FL_NOCASE) !== 0); |
|
884 | 1879 | $ignoreDir = (($validFlags & self::FL_NODIR) !== 0); |
|
885 | |||
886 | 1879 | $name = ($ignoreCase ? \strtolower($name) : $name); |
|
887 | |||
888 | 1879 | foreach ($this->originalCentralDirectory as $possibleIndex => $possibleEntry) { |
|
889 | 1879 | if ($ignoreDir && $possibleEntry->isDirectory()) { |
|
890 | 822 | continue; |
|
891 | } |
||
892 | |||
893 | 1879 | $entryName = $possibleEntry->getFileName(); |
|
894 | 1879 | $entryName = ($ignoreCase ? \strtolower($entryName) : $entryName); |
|
895 | 1879 | $entryName = ($ignoreDir ? \basename($entryName) : $entryName); |
|
896 | |||
897 | 1879 | if ($name === $entryName) { |
|
898 | 1879 | return $possibleIndex; |
|
899 | } |
||
900 | } |
||
901 | |||
902 | 1379 | $this->status = self::ER_NOENT; |
|
903 | 1379 | return false; |
|
904 | } |
||
905 | |||
906 | |||
907 | /** |
||
908 | * Get the details of an entry defined by its index |
||
909 | * |
||
910 | * @param int $index Index of the entry |
||
911 | * @param int $flags ZipArchive::FL_UNCHANGED or 0 |
||
912 | * @return array|false |
||
913 | * |
||
914 | * @link http://php.net/manual/en/ziparchive.statindex.php |
||
915 | */ |
||
916 | 54 | final public function statIndex(int $index, int $flags = null) |
|
917 | { |
||
918 | 54 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_UNCHANGED)); |
|
0 ignored issues
–
show
$validFlags is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
919 | |||
920 | 54 | if (!isset($this->originalCentralDirectory[$index])) { |
|
921 | return false; |
||
922 | } |
||
923 | |||
924 | /* @var $entry CentralDirectoryHeader */ |
||
925 | 54 | $entry = $this->originalCentralDirectory[$index]; |
|
926 | |||
927 | return [ |
||
928 | 54 | 'name' => $entry->getFileName(), |
|
929 | 54 | 'index' => $index, |
|
930 | 54 | 'crc' => $entry->getCrc32(), |
|
931 | 54 | 'size' => $entry->getUncompressedSize(), |
|
932 | 54 | 'mtime' => $entry->getLastModification()->getTimestamp(), |
|
933 | 54 | 'comp_size' => $entry->getCompressedSize(), |
|
934 | 54 | 'comp_method' => $entry->getCompressionMethod(), |
|
935 | 54 | 'encryption_method' => 0, |
|
936 | ]; |
||
937 | } |
||
938 | |||
939 | |||
940 | /** |
||
941 | * Get the details of an entry defined by its name |
||
942 | * |
||
943 | * @param string $name Name of the entry |
||
944 | * @param int $flags Any combination of ZipArchive::FL_NOCASE|ZipArchive::FL_NODIR|ZipArchive::FL_UNCHANGED |
||
945 | * @return array|false |
||
946 | * |
||
947 | * @link http://php.net/manual/en/ziparchive.statname.php |
||
948 | */ |
||
949 | 168 | final public function statName(string $name, int $flags = 0) |
|
950 | { |
||
951 | 168 | $validFlags = (is_null($flags) ? 0 : $flags & (self::FL_NOCASE|self::FL_NODIR|self::FL_UNCHANGED)); |
|
952 | |||
953 | 168 | if (($index = $this->locateName($name, $validFlags)) !== false) { |
|
954 | 42 | return $this->statIndex($index, $validFlags); |
|
955 | } |
||
956 | |||
957 | 126 | return false; |
|
958 | } |
||
959 | } |
||
960 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.