Total Complexity | 98 |
Total Lines | 855 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 1 |
Complex classes like ZipWriter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ZipWriter, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | class ZipWriter |
||
28 | { |
||
29 | /** @var int Chunk read size */ |
||
30 | const CHUNK_SIZE = 8192; |
||
31 | |||
32 | /** @var ZipContainer */ |
||
33 | protected $zipContainer; |
||
34 | |||
35 | /** |
||
36 | * ZipWriter constructor. |
||
37 | * |
||
38 | * @param ZipContainer $container |
||
39 | */ |
||
40 | public function __construct(ZipContainer $container) |
||
43 | } |
||
44 | |||
45 | /** |
||
46 | * @param resource $outStream |
||
47 | * |
||
48 | * @throws ZipException |
||
49 | */ |
||
50 | public function write($outStream) |
||
51 | { |
||
52 | if (!\is_resource($outStream)) { |
||
53 | throw new \InvalidArgumentException('$outStream must be resource'); |
||
54 | } |
||
55 | $this->beforeWrite(); |
||
56 | $this->writeLocalBlock($outStream); |
||
57 | $cdOffset = ftell($outStream); |
||
58 | $this->writeCentralDirectoryBlock($outStream); |
||
59 | $cdSize = ftell($outStream) - $cdOffset; |
||
60 | $this->writeEndOfCentralDirectoryBlock($outStream, $cdOffset, $cdSize); |
||
61 | } |
||
62 | |||
63 | protected function beforeWrite() |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * @param resource $outStream |
||
69 | * |
||
70 | * @throws ZipException |
||
71 | */ |
||
72 | protected function writeLocalBlock($outStream) |
||
82 | } |
||
83 | } |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * @param resource $outStream |
||
88 | * @param ZipEntry $entry |
||
89 | * |
||
90 | * @throws ZipException |
||
91 | */ |
||
92 | protected function writeLocalHeader($outStream, ZipEntry $entry) |
||
93 | { |
||
94 | // todo in 4.0 version move zipalign functional to ApkWriter class |
||
95 | if ($this->zipContainer->isZipAlign()) { |
||
96 | $this->zipAlign($outStream, $entry); |
||
97 | } |
||
98 | |||
99 | $relativeOffset = ftell($outStream); |
||
100 | $entry->setLocalHeaderOffset($relativeOffset); |
||
101 | |||
102 | if ($entry->isEncrypted() && $entry->getEncryptionMethod() === ZipEncryptionMethod::PKWARE) { |
||
103 | $entry->enableDataDescriptor(true); |
||
104 | } |
||
105 | |||
106 | $dd = $entry->isDataDescriptorRequired() || |
||
107 | $entry->isDataDescriptorEnabled(); |
||
108 | |||
109 | $compressedSize = $entry->getCompressedSize(); |
||
110 | $uncompressedSize = $entry->getUncompressedSize(); |
||
111 | |||
112 | $entry->getLocalExtraFields()->remove(Zip64ExtraField::HEADER_ID); |
||
113 | |||
114 | if ($compressedSize > ZipConstants::ZIP64_MAGIC || $uncompressedSize > ZipConstants::ZIP64_MAGIC) { |
||
115 | $entry->getLocalExtraFields()->add( |
||
116 | new Zip64ExtraField($uncompressedSize, $compressedSize) |
||
117 | ); |
||
118 | |||
119 | $compressedSize = ZipConstants::ZIP64_MAGIC; |
||
120 | $uncompressedSize = ZipConstants::ZIP64_MAGIC; |
||
121 | } |
||
122 | |||
123 | $compressionMethod = $entry->getCompressionMethod(); |
||
124 | $crc = $entry->getCrc(); |
||
125 | |||
126 | if ($entry->isEncrypted() && ZipEncryptionMethod::isWinZipAesMethod($entry->getEncryptionMethod())) { |
||
127 | /** @var WinZipAesExtraField|null $winZipAesExtra */ |
||
128 | $winZipAesExtra = $entry->getLocalExtraField(WinZipAesExtraField::HEADER_ID); |
||
129 | |||
130 | if ($winZipAesExtra === null) { |
||
131 | $winZipAesExtra = WinZipAesExtraField::create($entry); |
||
132 | } |
||
133 | |||
134 | if ($winZipAesExtra->isV2()) { |
||
135 | $crc = 0; |
||
136 | } |
||
137 | $compressionMethod = ZipCompressionMethod::WINZIP_AES; |
||
138 | } |
||
139 | |||
140 | $extra = $this->getExtraFieldsContents($entry, true); |
||
141 | $name = $entry->getName(); |
||
142 | $dosCharset = $entry->getCharset(); |
||
143 | |||
144 | if ($dosCharset !== null && !$entry->isUtf8Flag()) { |
||
145 | $name = DosCodePage::fromUTF8($name, $dosCharset); |
||
146 | } |
||
147 | |||
148 | $nameLength = \strlen($name); |
||
149 | $extraLength = \strlen($extra); |
||
150 | |||
151 | $size = $nameLength + $extraLength; |
||
152 | |||
153 | if ($size > 0xffff) { |
||
154 | throw new ZipException( |
||
155 | sprintf( |
||
156 | '%s (the total size of %s bytes for the name, extra fields and comment exceeds the maximum size of %d bytes)', |
||
157 | $entry->getName(), |
||
158 | $size, |
||
159 | 0xffff |
||
160 | ) |
||
161 | ); |
||
162 | } |
||
163 | |||
164 | $extractedBy = ($entry->getExtractedOS() << 8) | $entry->getExtractVersion(); |
||
165 | |||
166 | fwrite( |
||
167 | $outStream, |
||
168 | pack( |
||
169 | 'VvvvVVVVvv', |
||
170 | // local file header signature 4 bytes (0x04034b50) |
||
171 | ZipConstants::LOCAL_FILE_HEADER, |
||
172 | // version needed to extract 2 bytes |
||
173 | $extractedBy, |
||
174 | // general purpose bit flag 2 bytes |
||
175 | $entry->getGeneralPurposeBitFlags(), |
||
176 | // compression method 2 bytes |
||
177 | $compressionMethod, |
||
178 | // last mod file time 2 bytes |
||
179 | // last mod file date 2 bytes |
||
180 | $entry->getDosTime(), |
||
181 | // crc-32 4 bytes |
||
182 | $dd ? 0 : $crc, |
||
183 | // compressed size 4 bytes |
||
184 | $dd ? 0 : $compressedSize, |
||
185 | // uncompressed size 4 bytes |
||
186 | $dd ? 0 : $uncompressedSize, |
||
187 | // file name length 2 bytes |
||
188 | $nameLength, |
||
189 | // extra field length 2 bytes |
||
190 | $extraLength |
||
191 | ) |
||
192 | ); |
||
193 | |||
194 | if ($nameLength > 0) { |
||
195 | fwrite($outStream, $name); |
||
196 | } |
||
197 | |||
198 | if ($extraLength > 0) { |
||
199 | fwrite($outStream, $extra); |
||
200 | } |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * @param resource $outStream |
||
205 | * @param ZipEntry $entry |
||
206 | * |
||
207 | * @throws ZipException |
||
208 | */ |
||
209 | private function zipAlign($outStream, ZipEntry $entry) |
||
210 | { |
||
211 | if (!$entry->isDirectory() && $entry->getCompressionMethod() === ZipCompressionMethod::STORED) { |
||
212 | $entry->removeExtraField(ApkAlignmentExtraField::HEADER_ID); |
||
213 | |||
214 | $extra = $this->getExtraFieldsContents($entry, true); |
||
215 | $extraLength = \strlen($extra); |
||
216 | $name = $entry->getName(); |
||
217 | |||
218 | $dosCharset = $entry->getCharset(); |
||
219 | |||
220 | if ($dosCharset !== null && !$entry->isUtf8Flag()) { |
||
221 | $name = DosCodePage::fromUTF8($name, $dosCharset); |
||
222 | } |
||
223 | $nameLength = \strlen($name); |
||
224 | |||
225 | $multiple = ApkAlignmentExtraField::ALIGNMENT_BYTES; |
||
226 | |||
227 | if (StringUtil::endsWith($name, '.so')) { |
||
228 | $multiple = ApkAlignmentExtraField::COMMON_PAGE_ALIGNMENT_BYTES; |
||
229 | } |
||
230 | |||
231 | $offset = ftell($outStream); |
||
232 | |||
233 | $dataMinStartOffset = |
||
234 | $offset + |
||
235 | ZipConstants::LFH_FILENAME_POS + |
||
236 | $extraLength + |
||
237 | $nameLength; |
||
238 | |||
239 | $padding = |
||
240 | ($multiple - ($dataMinStartOffset % $multiple)) |
||
241 | % $multiple; |
||
242 | |||
243 | if ($padding > 0) { |
||
244 | $dataMinStartOffset += ApkAlignmentExtraField::MIN_SIZE; |
||
245 | $padding = |
||
246 | ($multiple - ($dataMinStartOffset % $multiple)) |
||
247 | % $multiple; |
||
248 | |||
249 | $entry->getLocalExtraFields()->add( |
||
250 | new ApkAlignmentExtraField($multiple, $padding) |
||
251 | ); |
||
252 | } |
||
253 | } |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * Merges the local file data fields of the given ZipExtraFields. |
||
258 | * |
||
259 | * @param ZipEntry $entry |
||
260 | * @param bool $local |
||
261 | * |
||
262 | * @throws ZipException |
||
263 | * |
||
264 | * @return string |
||
265 | */ |
||
266 | protected function getExtraFieldsContents(ZipEntry $entry, $local) |
||
267 | { |
||
268 | $local = (bool) $local; |
||
269 | $collection = $local ? |
||
270 | $entry->getLocalExtraFields() : |
||
271 | $entry->getCdExtraFields(); |
||
272 | $extraData = ''; |
||
273 | |||
274 | foreach ($collection as $extraField) { |
||
275 | if ($local) { |
||
276 | $data = $extraField->packLocalFileData(); |
||
277 | } else { |
||
278 | $data = $extraField->packCentralDirData(); |
||
279 | } |
||
280 | $extraData .= pack( |
||
281 | 'vv', |
||
282 | $extraField->getHeaderId(), |
||
283 | \strlen($data) |
||
284 | ); |
||
285 | $extraData .= $data; |
||
286 | } |
||
287 | |||
288 | $size = \strlen($extraData); |
||
289 | |||
290 | if ($size > 0xffff) { |
||
291 | throw new ZipException( |
||
292 | sprintf( |
||
293 | 'Size extra out of range: %d. Extra data: %s', |
||
294 | $size, |
||
295 | $extraData |
||
296 | ) |
||
297 | ); |
||
298 | } |
||
299 | |||
300 | return $extraData; |
||
301 | } |
||
302 | |||
303 | /** |
||
304 | * @param resource $outStream |
||
305 | * @param ZipEntry $entry |
||
306 | * |
||
307 | * @throws ZipException |
||
308 | */ |
||
309 | protected function writeData($outStream, ZipEntry $entry) |
||
310 | { |
||
311 | $zipData = $entry->getData(); |
||
312 | |||
313 | if ($zipData === null) { |
||
314 | if ($entry->isDirectory()) { |
||
315 | return; |
||
316 | } |
||
317 | |||
318 | throw new ZipException(sprintf('No zip data for entry "%s"', $entry->getName())); |
||
319 | } |
||
320 | |||
321 | // data write variants: |
||
322 | // -------------------- |
||
323 | // * data of source zip file -> copy compressed data |
||
324 | // * store - simple write |
||
325 | // * store and encryption - apply encryption filter and simple write |
||
326 | // * deflate or bzip2 - apply compression filter and simple write |
||
327 | // * (deflate or bzip2) and encryption - create temp stream and apply |
||
328 | // compression filter to it, then apply encryption filter to root |
||
329 | // stream and write temp stream data. |
||
330 | // (PHP cannot apply the filter for encryption after the compression |
||
331 | // filter, so a temporary stream is created for the compressed data) |
||
332 | |||
333 | if ($zipData instanceof ZipSourceFileData && !$zipData->hasRecompressData($entry)) { |
||
334 | // data of source zip file -> copy compressed data |
||
335 | $zipData->copyCompressedDataToStream($outStream); |
||
336 | |||
337 | return; |
||
338 | } |
||
339 | |||
340 | $entryStream = $zipData->getDataAsStream(); |
||
341 | |||
342 | if (stream_get_meta_data($entryStream)['seekable']) { |
||
343 | rewind($entryStream); |
||
344 | } |
||
345 | |||
346 | $uncompressedSize = $entry->getUncompressedSize(); |
||
347 | |||
348 | $posBeforeWrite = ftell($outStream); |
||
349 | $compressionMethod = $entry->getCompressionMethod(); |
||
350 | |||
351 | if ($entry->isEncrypted()) { |
||
352 | if ($compressionMethod === ZipCompressionMethod::STORED) { |
||
353 | $contextFilter = $this->appendEncryptionFilter($outStream, $entry, $uncompressedSize); |
||
|
|||
354 | $checksum = $this->writeAndCountChecksum($entryStream, $outStream, $uncompressedSize); |
||
355 | } else { |
||
356 | $compressStream = fopen('php://temp', 'w+b'); |
||
357 | $contextFilter = $this->appendCompressionFilter($compressStream, $entry); |
||
358 | $checksum = $this->writeAndCountChecksum($entryStream, $compressStream, $uncompressedSize); |
||
359 | |||
360 | if ($contextFilter !== null) { |
||
361 | stream_filter_remove($contextFilter); |
||
362 | $contextFilter = null; |
||
363 | } |
||
364 | |||
365 | rewind($compressStream); |
||
366 | |||
367 | $compressedSize = fstat($compressStream)['size']; |
||
368 | $contextFilter = $this->appendEncryptionFilter($outStream, $entry, $compressedSize); |
||
369 | |||
370 | stream_copy_to_stream($compressStream, $outStream); |
||
371 | } |
||
372 | } else { |
||
373 | $contextFilter = $this->appendCompressionFilter($outStream, $entry); |
||
374 | $checksum = $this->writeAndCountChecksum($entryStream, $outStream, $uncompressedSize); |
||
375 | } |
||
376 | |||
377 | if ($contextFilter !== null) { |
||
378 | stream_filter_remove($contextFilter); |
||
379 | $contextFilter = null; |
||
380 | } |
||
381 | |||
382 | // my hack {@see https://bugs.php.net/bug.php?id=49874} |
||
383 | fseek($outStream, 0, \SEEK_END); |
||
384 | $compressedSize = ftell($outStream) - $posBeforeWrite; |
||
385 | |||
386 | $entry->setCompressedSize($compressedSize); |
||
387 | $entry->setCrc($checksum); |
||
388 | |||
389 | if (!$entry->isDataDescriptorEnabled()) { |
||
390 | if ($uncompressedSize > ZipConstants::ZIP64_MAGIC || $compressedSize > ZipConstants::ZIP64_MAGIC) { |
||
391 | /** @var Zip64ExtraField|null $zip64ExtraLocal */ |
||
392 | $zip64ExtraLocal = $entry->getLocalExtraField(Zip64ExtraField::HEADER_ID); |
||
393 | |||
394 | // if there is a zip64 extra record, then update it; |
||
395 | // if not, write data to data descriptor |
||
396 | if ($zip64ExtraLocal !== null) { |
||
397 | $zip64ExtraLocal->setCompressedSize($compressedSize); |
||
398 | $zip64ExtraLocal->setUncompressedSize($uncompressedSize); |
||
399 | |||
400 | $posExtra = $entry->getLocalHeaderOffset() + ZipConstants::LFH_FILENAME_POS + \strlen($entry->getName()); |
||
401 | fseek($outStream, $posExtra); |
||
402 | fwrite($outStream, $this->getExtraFieldsContents($entry, true)); |
||
403 | } else { |
||
404 | $posGPBF = $entry->getLocalHeaderOffset() + 6; |
||
405 | $entry->enableDataDescriptor(true); |
||
406 | fseek($outStream, $posGPBF); |
||
407 | fwrite( |
||
408 | $outStream, |
||
409 | pack( |
||
410 | 'v', |
||
411 | // general purpose bit flag 2 bytes |
||
412 | $entry->getGeneralPurposeBitFlags() |
||
413 | ) |
||
414 | ); |
||
415 | } |
||
416 | |||
417 | $compressedSize = ZipConstants::ZIP64_MAGIC; |
||
418 | $uncompressedSize = ZipConstants::ZIP64_MAGIC; |
||
419 | } |
||
420 | |||
421 | $posChecksum = $entry->getLocalHeaderOffset() + 14; |
||
422 | |||
423 | /** @var WinZipAesExtraField|null $winZipAesExtra */ |
||
424 | $winZipAesExtra = $entry->getLocalExtraField(WinZipAesExtraField::HEADER_ID); |
||
425 | |||
426 | if ($winZipAesExtra !== null && $winZipAesExtra->isV2()) { |
||
427 | $checksum = 0; |
||
428 | } |
||
429 | |||
430 | fseek($outStream, $posChecksum); |
||
431 | fwrite( |
||
432 | $outStream, |
||
433 | pack( |
||
434 | 'VVV', |
||
435 | // crc-32 4 bytes |
||
436 | $checksum, |
||
437 | // compressed size 4 bytes |
||
438 | $compressedSize, |
||
439 | // uncompressed size 4 bytes |
||
440 | $uncompressedSize |
||
441 | ) |
||
442 | ); |
||
443 | fseek($outStream, 0, \SEEK_END); |
||
444 | } |
||
445 | } |
||
446 | |||
447 | /** |
||
448 | * @param resource $inStream |
||
449 | * @param resource $outStream |
||
450 | * @param int $size |
||
451 | * |
||
452 | * @return int |
||
453 | */ |
||
454 | private function writeAndCountChecksum($inStream, $outStream, $size) |
||
455 | { |
||
456 | $contextHash = hash_init('crc32b'); |
||
457 | $offset = 0; |
||
458 | |||
459 | while ($offset < $size) { |
||
460 | $read = min(self::CHUNK_SIZE, $size - $offset); |
||
461 | $buffer = fread($inStream, $read); |
||
462 | fwrite($outStream, $buffer); |
||
463 | hash_update($contextHash, $buffer); |
||
464 | $offset += $read; |
||
465 | } |
||
466 | |||
467 | return (int) hexdec(hash_final($contextHash)); |
||
468 | } |
||
469 | |||
470 | /** |
||
471 | * @param resource $outStream |
||
472 | * @param ZipEntry $entry |
||
473 | * |
||
474 | * @throws ZipUnsupportMethodException |
||
475 | * |
||
476 | * @return resource|null |
||
477 | */ |
||
478 | protected function appendCompressionFilter($outStream, ZipEntry $entry) |
||
520 | } |
||
521 | |||
522 | /** |
||
523 | * @param resource $outStream |
||
524 | * @param ZipEntry $entry |
||
525 | * @param int $size |
||
526 | * |
||
527 | * @return resource|null |
||
528 | */ |
||
529 | protected function appendEncryptionFilter($outStream, ZipEntry $entry, $size) |
||
530 | { |
||
531 | $encContextFilter = null; |
||
532 | |||
533 | if ($entry->isEncrypted()) { |
||
534 | if ($entry->getEncryptionMethod() === ZipEncryptionMethod::PKWARE) { |
||
535 | PKEncryptionStreamFilter::register(); |
||
536 | $cipherFilterName = PKEncryptionStreamFilter::FILTER_NAME; |
||
537 | } else { |
||
538 | WinZipAesEncryptionStreamFilter::register(); |
||
539 | $cipherFilterName = WinZipAesEncryptionStreamFilter::FILTER_NAME; |
||
540 | } |
||
541 | $encContextFilter = stream_filter_append( |
||
542 | $outStream, |
||
543 | $cipherFilterName, |
||
544 | \STREAM_FILTER_WRITE, |
||
545 | [ |
||
546 | 'entry' => $entry, |
||
547 | 'size' => $size, |
||
548 | ] |
||
549 | ); |
||
550 | |||
551 | if (!$encContextFilter) { |
||
552 | throw new \RuntimeException('Not apply filter ' . $cipherFilterName); |
||
553 | } |
||
554 | } |
||
555 | |||
556 | return $encContextFilter; |
||
557 | } |
||
558 | |||
559 | /** |
||
560 | * @param resource $outStream |
||
561 | * @param ZipEntry $entry |
||
562 | */ |
||
563 | protected function writeDataDescriptor($outStream, ZipEntry $entry) |
||
564 | { |
||
565 | $crc = $entry->getCrc(); |
||
566 | |||
567 | /** @var WinZipAesExtraField|null $winZipAesExtra */ |
||
568 | $winZipAesExtra = $entry->getLocalExtraField(WinZipAesExtraField::HEADER_ID); |
||
569 | |||
570 | if ($winZipAesExtra !== null && $winZipAesExtra->isV2()) { |
||
571 | $crc = 0; |
||
572 | } |
||
573 | |||
574 | fwrite( |
||
575 | $outStream, |
||
576 | pack( |
||
577 | 'VV', |
||
578 | // data descriptor signature 4 bytes (0x08074b50) |
||
579 | ZipConstants::DATA_DESCRIPTOR, |
||
580 | // crc-32 4 bytes |
||
581 | $crc |
||
582 | ) |
||
583 | ); |
||
584 | |||
585 | if ( |
||
586 | $entry->isZip64ExtensionsRequired() || |
||
587 | $entry->getLocalExtraFields()->has(Zip64ExtraField::HEADER_ID) |
||
588 | ) { |
||
589 | $dd = |
||
590 | // compressed size 8 bytes |
||
591 | PackUtil::packLongLE($entry->getCompressedSize()) . |
||
592 | // uncompressed size 8 bytes |
||
593 | PackUtil::packLongLE($entry->getUncompressedSize()); |
||
594 | } else { |
||
595 | $dd = pack( |
||
596 | 'VV', |
||
597 | // compressed size 4 bytes |
||
598 | $entry->getCompressedSize(), |
||
599 | // uncompressed size 4 bytes |
||
600 | $entry->getUncompressedSize() |
||
601 | ); |
||
602 | } |
||
603 | |||
604 | fwrite($outStream, $dd); |
||
605 | } |
||
606 | |||
607 | /** |
||
608 | * @param resource $outStream |
||
609 | * |
||
610 | * @throws ZipException |
||
611 | */ |
||
612 | protected function writeCentralDirectoryBlock($outStream) |
||
613 | { |
||
614 | foreach ($this->zipContainer->getEntries() as $outputEntry) { |
||
615 | $this->writeCentralDirectoryHeader($outStream, $outputEntry); |
||
616 | } |
||
617 | } |
||
618 | |||
619 | /** |
||
620 | * Writes a Central File Header record. |
||
621 | * |
||
622 | * @param resource $outStream |
||
623 | * @param ZipEntry $entry |
||
624 | * |
||
625 | * @throws ZipException |
||
626 | */ |
||
627 | protected function writeCentralDirectoryHeader($outStream, ZipEntry $entry) |
||
628 | { |
||
629 | $compressedSize = $entry->getCompressedSize(); |
||
630 | $uncompressedSize = $entry->getUncompressedSize(); |
||
631 | $localHeaderOffset = $entry->getLocalHeaderOffset(); |
||
632 | |||
633 | $entry->getCdExtraFields()->remove(Zip64ExtraField::HEADER_ID); |
||
634 | |||
635 | if ( |
||
636 | $localHeaderOffset > ZipConstants::ZIP64_MAGIC || |
||
637 | $compressedSize > ZipConstants::ZIP64_MAGIC || |
||
638 | $uncompressedSize > ZipConstants::ZIP64_MAGIC |
||
639 | ) { |
||
640 | $zip64ExtraField = new Zip64ExtraField(); |
||
641 | |||
642 | if ($uncompressedSize >= ZipConstants::ZIP64_MAGIC) { |
||
643 | $zip64ExtraField->setUncompressedSize($uncompressedSize); |
||
644 | $uncompressedSize = ZipConstants::ZIP64_MAGIC; |
||
645 | } |
||
646 | |||
647 | if ($compressedSize >= ZipConstants::ZIP64_MAGIC) { |
||
648 | $zip64ExtraField->setCompressedSize($compressedSize); |
||
649 | $compressedSize = ZipConstants::ZIP64_MAGIC; |
||
650 | } |
||
651 | |||
652 | if ($localHeaderOffset >= ZipConstants::ZIP64_MAGIC) { |
||
653 | $zip64ExtraField->setLocalHeaderOffset($localHeaderOffset); |
||
654 | $localHeaderOffset = ZipConstants::ZIP64_MAGIC; |
||
655 | } |
||
656 | |||
657 | $entry->getCdExtraFields()->add($zip64ExtraField); |
||
658 | } |
||
659 | |||
660 | $extra = $this->getExtraFieldsContents($entry, false); |
||
661 | $extraLength = \strlen($extra); |
||
662 | |||
663 | $name = $entry->getName(); |
||
664 | $comment = $entry->getComment(); |
||
665 | |||
666 | $dosCharset = $entry->getCharset(); |
||
667 | |||
668 | if ($dosCharset !== null && !$entry->isUtf8Flag()) { |
||
669 | $name = DosCodePage::fromUTF8($name, $dosCharset); |
||
670 | |||
671 | if ($comment) { |
||
672 | $comment = DosCodePage::fromUTF8($comment, $dosCharset); |
||
673 | } |
||
674 | } |
||
675 | |||
676 | $commentLength = \strlen($comment); |
||
677 | |||
678 | $compressionMethod = $entry->getCompressionMethod(); |
||
679 | $crc = $entry->getCrc(); |
||
680 | |||
681 | /** @var WinZipAesExtraField|null $winZipAesExtra */ |
||
682 | $winZipAesExtra = $entry->getLocalExtraField(WinZipAesExtraField::HEADER_ID); |
||
683 | |||
684 | if ($winZipAesExtra !== null) { |
||
685 | if ($winZipAesExtra->isV2()) { |
||
686 | $crc = 0; |
||
687 | } |
||
688 | $compressionMethod = ZipCompressionMethod::WINZIP_AES; |
||
689 | } |
||
690 | |||
691 | fwrite( |
||
692 | $outStream, |
||
693 | pack( |
||
694 | 'VvvvvVVVVvvvvvVV', |
||
695 | // central file header signature 4 bytes (0x02014b50) |
||
696 | ZipConstants::CENTRAL_FILE_HEADER, |
||
697 | // version made by 2 bytes |
||
698 | ($entry->getCreatedOS() << 8) | $entry->getSoftwareVersion(), |
||
699 | // version needed to extract 2 bytes |
||
700 | ($entry->getExtractedOS() << 8) | $entry->getExtractVersion(), |
||
701 | // general purpose bit flag 2 bytes |
||
702 | $entry->getGeneralPurposeBitFlags(), |
||
703 | // compression method 2 bytes |
||
704 | $compressionMethod, |
||
705 | // last mod file datetime 4 bytes |
||
706 | $entry->getDosTime(), |
||
707 | // crc-32 4 bytes |
||
708 | $crc, |
||
709 | // compressed size 4 bytes |
||
710 | $compressedSize, |
||
711 | // uncompressed size 4 bytes |
||
712 | $uncompressedSize, |
||
713 | // file name length 2 bytes |
||
714 | \strlen($name), |
||
715 | // extra field length 2 bytes |
||
716 | $extraLength, |
||
717 | // file comment length 2 bytes |
||
718 | $commentLength, |
||
719 | // disk number start 2 bytes |
||
720 | 0, |
||
721 | // internal file attributes 2 bytes |
||
722 | $entry->getInternalAttributes(), |
||
723 | // external file attributes 4 bytes |
||
724 | $entry->getExternalAttributes(), |
||
725 | // relative offset of local header 4 bytes |
||
726 | $localHeaderOffset |
||
727 | ) |
||
728 | ); |
||
729 | |||
730 | // file name (variable size) |
||
731 | fwrite($outStream, $name); |
||
732 | |||
733 | if ($extraLength > 0) { |
||
734 | // extra field (variable size) |
||
735 | fwrite($outStream, $extra); |
||
736 | } |
||
737 | |||
738 | if ($commentLength > 0) { |
||
739 | // file comment (variable size) |
||
740 | fwrite($outStream, $comment); |
||
741 | } |
||
742 | } |
||
743 | |||
744 | /** |
||
745 | * @param resource $outStream |
||
746 | * @param int $centralDirectoryOffset |
||
747 | * @param int $centralDirectorySize |
||
748 | */ |
||
749 | protected function writeEndOfCentralDirectoryBlock( |
||
882 | } |
||
883 | } |
||
884 | } |
||
885 |
This check looks for function or method calls that always return null and whose return value is assigned to a variable.
The method
getObject()
can return nothing but null, so it makes no sense to assign that value to a variable.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.