closed || !$this->file) { throw new ArchiveIOException('Can not read from a closed archive'); } $outdir = rtrim($outdir, '/'); $extracted = array(); $cdir = $this->readCentralDir(); $pos_entry = $cdir['offset']; // begin of the central file directory for ($i = 0; $i < $cdir['entries']; $i++) { // read file header @fseek($this->fh, $pos_entry); $header = $this->readCentralFileHeader(); $header['index'] = $i; $pos_entry = ftell($this->fh); // position of the next file in central file directory fseek($this->fh, $header['offset']); // seek to beginning of file header $header = $this->readFileHeader($header); $fileinfo = $this->header2fileinfo($header); // apply strip rules $fileinfo->strip($strip); // skip unwanted files if (!strlen($fileinfo->getPath()) || !$fileinfo->match($include, $exclude)) { continue; } $extracted[] = $fileinfo; // create output directory $output = $outdir . '/' . $fileinfo->getPath(); $directory = ($header['folder']) ? $output : dirname($output); // nothing more to do for directories if ($fileinfo->getIsdir()) { continue; } // compressed files are written to temporary .gz file first if ($header['compression'] == 0) { $extractto = $output; $context = stream_context_create([]); } else { $extractto = $output; $context = stream_context_create([ 'gs' => [ 'Content-Encoding' => 'gzip', ] ]); } // open file for writing $fp = fopen($extractto, "wb", false, $context); if (!$fp) { throw new ArchiveIOException('Could not open file for writing: ' . $extractto); } // prepend compression header if ($header['compression'] != 0) { $binary_data = pack( 'va1a1Va1a1', 0x8b1f, chr($header['compression']), chr(0x00), time(), chr(0x00), chr(3) ); fwrite($fp, $binary_data, 10); } // read the file and store it on disk $size = $header['compressed_size']; while ($size != 0) { $read_size = ($size < 2048 ? $size : 2048); $buffer = fread($this->fh, $read_size); $binary_data = pack('a' . $read_size, $buffer); fwrite($fp, $binary_data, $read_size); $size -= $read_size; } // finalize compressed file if ($header['compression'] != 0) { $binary_data = pack('VV', $header['crc'], $header['size']); fwrite($fp, $binary_data, 8); } // close file fclose($fp); touch($output, $fileinfo->getMtime()); //FIXME what about permissions? } $this->close(); return $extracted; } }