public function parseHeader($handle) { $pk = fread($handle, 4); if ($pk == AbstractZipHeader::ZIP_LOCAL_FILE_HEADER) { /* * local file header signature 4 bytes (0x04034b50) * version needed to extract 2 bytes * general purpose bit flag 2 bytes * compression method 2 bytes * last mod file time + file date 4 bytes * crc-32 4 bytes * compressed size 4 bytes * uncompressed size 4 bytes * file name length 2 bytes * extra field length 2 bytes * --------------------------------------- * 30 bytes */ $this->offset = (int) ftell($handle) - 4; $this->versionNeeded = fread($handle, 2); $arr = unpack("v2wa", fread($handle, 4)); $this->gpFlags = $arr['wa1']; $this->gzType = $arr['wa2']; $this->dosTime = fread($handle, 4); $arr = unpack("V3dwa/v2wa", fread($handle, 16)); $this->fileCRC32 = $arr['dwa1']; $this->gzLength = $arr['dwa2']; $this->dataLength = $arr['dwa3']; $filePathLength = $arr['wa1']; $localExtraFieldLength = $arr['wa2']; $this->path = fread($handle, $filePathLength); $this->dataOffset = 30 + $filePathLength + $localExtraFieldLength; if ($localExtraFieldLength > 0) { $eoef = ftell($handle) + $localExtraFieldLength; while (ftell($handle) < $eoef) { $ef = AbstractExtraField::decodeField($handle); /* @var $ef AbstractExtraField */ $this->extraFieldsArray[$ef->header] = $ef; } } $hasDataDescriptor = $this->gpFlags & 4 == 4; if ($hasDataDescriptor) { $pkHeader = AbstractZipHeader::seekPKHeader($handle); if ($pkHeader !== self::ZIP_LOCAL_DATA_DESCRIPTOR) { fseek($handle, -12, SEEK_CUR); } $arr = unpack("Vdwa", fread($handle, 12)); $this->fileCRC32 = $arr['dwa1']; $this->gzLength = $arr['dwa2']; $this->dataLength = $arr['dwa3']; } else { fseek($handle, $this->gzLength, SEEK_CUR); } $this->isDirectory = !$hasDataDescriptor && $this->dataLength == 0 && $this->fileCRC32 == 0; } else { if ($pk == AbstractZipHeader::ZIP_CENTRAL_FILE_HEADER) { /* * * central file header signature 4 bytes (0x02014b50) * version made by 2 bytes * version needed to extract 2 bytes * general purpose bit flag 2 bytes * compression method 2 bytes * last mod file time 2 bytes * last mod file date 2 bytes * crc-32 4 bytes * compressed size 4 bytes * uncompressed size 4 bytes * file name length 2 bytes * extra field length 2 bytes * file comment length 2 bytes * disk number start 2 bytes * internal file attributes 2 bytes * external file attributes 4 bytes * relative offset of local header 4 bytes * ---------------------------------------- * 46 bytes * * file name (variable size) * extra field (variable size) * file comment (variable size) */ // $this->offset = (int)ftell($handle) - 4; $this->versionMadeBy = fread($handle, 2); $this->versionNeeded = fread($handle, 2); $arr = unpack("v2wa", fread($handle, 4)); $this->gpFlags = $arr['wa1']; $this->gzType = $arr['wa2']; $this->dosTime = fread($handle, 4); $arr = unpack("V3dwa/v3wa", fread($handle, 18)); // $this->fileCRC32 = $arr['dwa1']; // $this->gzLength = $arr['dwa2']; // $this->dataLength = $arr['dwa3']; $filePathLength = $arr['wa1']; $centralExtraFieldLength = $arr['wa2']; $fileCommentLength = $arr['wa3']; $this->discNumberStart = fread($handle, 2); $this->internalFileAttributes = fread($handle, 2); $this->externalFileAttributes = fread($handle, 4); // $arr = unpack("V", fread($handle, 4)); // $this->relativeOffsetOfLocalHeader = $arr[1]; // $this->path = fread($handle, $filePathLength); fseek($handle, 4 + $filePathLength, SEEK_CUR); if ($centralExtraFieldLength > 0) { $eoef = ftell($handle) + $centralExtraFieldLength; while (ftell($handle) < $eoef) { $ef = AbstractExtraField::decodeField($handle, false); /* @var $ef AbstractExtraField */ $ef2 = $this->extraFieldsArray[$ef->header]; if (isset($ef2)) { $ef2->centralData = $ef->centralData; } else { $this->extraFieldsArray[$ef->header] = $ef; } } } if ($fileCommentLength > 0) { $this->comment = fread($handle, $fileCommentLength); } } else { fseek($handle, -4, SEEK_CUR); } } }
private function processStream($handle, $subPath = '') { $pkHeader = null; do { $curPos = ftell($handle); $pkHeader = AbstractZipHeader::seekPKHeader($handle); if ($pkHeader === false || feof($handle)) { break; } $pkPos = ftell($handle); if ($curPos < $pkPos) { $this->_throwException(new HeaderPositionError(array('expected' => $curPos, 'actual' => $pkPos))); } if ($pkHeader === AbstractZipHeader::ZIP_CENTRAL_FILE_HEADER) { $fileEntry = $this->FILES[$this->CDRindex++]; /* @var $fileEntry ZipFileEntry */ $fileEntry->parseHeader($handle); } else { if ($pkHeader === AbstractZipHeader::ZIP_LOCAL_FILE_HEADER) { $fileEntry = new ZipFileEntry($handle); $this->FILES[$this->LFHindex++] = $fileEntry; $fileEntry->prependPath($subPath); $lf = $fileEntry->getLocalHeader(); $lfLen = ZipUtils::bin_strlen($lf); $this->zipWrite($lf); fseek($handle, $fileEntry->offset + $fileEntry->dataOffset, SEEK_SET); if (!$fileEntry->isDirectory) { $len = $fileEntry->gzLength; while ($len >= $this->streamChunkSize) { $data = fread($handle, $this->streamChunkSize); $this->zipWrite($data); $len -= $this->streamChunkSize; } $data = fread($handle, $len); $this->zipWrite($data); } $fileEntry->offset = $this->entryOffset; $this->entryOffset += $lfLen + $fileEntry->gzLength; } else { if ($pkHeader === AbstractZipHeader::ZIP_END_OF_CENTRAL_DIRECTORY) { fread($handle, 4); $this->eocd = new EndOfCentralDirectory($handle); } } } } while (!feof($handle)); }