/**
  * Creates an instance from a resource.
  * @param string   $filename    File name.
  * @param resource $fileHandler File handler.
  *
  * @throws FileCorruptedException
  *
  * @return FileHeader
  */
 public static function createFromResource($filename, $fileHandler)
 {
     $header = new FileHeader();
     $data = unpack("nmagicNumber/C1compressionMethod/C1flags/LmodificationTime/C1extraFlags/C1os", fread($fileHandler, 10));
     // check magic number and compression method
     if (self::MAGIC_NUMBER !== $data['magicNumber'] || self::COMPRESSION_METHOD_DEFLATE !== $data['compressionMethod']) {
         throw new FileCorruptedException($filename);
     }
     $header->setCompressionMethod($data['compressionMethod'])->setFlags($data['flags'])->setExtraFlags($data['extraFlags'])->setModificationTimeFromUnixEpoch($data['modificationTime'])->setOperatingSystem($data['os']);
     // if FLG.FEXTRA set
     if (($header->getFlags() & self::FLAGS_EXTRA) === self::FLAGS_EXTRA) {
         $extraFieldData = unpack("C2subfield/vlength", fread($fileHandler, 10));
         $header->setExtraSubfields($extraFieldData['subfield1'], $extraFieldData['subfield2'])->setExtraData(fread($fileHandler, $extraFieldData['length']));
     }
     // if FLG.FNAME set
     if (($header->getFlags() & self::FLAGS_NAME) === self::FLAGS_NAME) {
         $header->setOriginalFilename(self::readString($fileHandler));
     }
     // if FLG.FCOMMENT set
     if (($header->getFlags() & self::FLAGS_COMMENT) === self::FLAGS_COMMENT) {
         $header->setComment(self::readString($fileHandler));
     }
     // if FLG.FHCRC set
     if (($header->getFlags() & self::FLAGS_HCRC) === self::FLAGS_HCRC) {
         $crcData = unpack('vcrc', fread($fileHandler, 2));
         $header->setCrc16($crcData['crc']);
     }
     return $header;
 }
 /**
  * Extracts the contents from a GZIP file.
  * @param string $filename GZIP file name.
  * @param string $target   Target path.
  *
  * @throws Exception\IO\Input\FileCorruptedException
  *
  * @return bool
  */
 protected function extractGzipFile($filename, $target)
 {
     $fileHandler = fopen($filename, 'rb');
     $bitReader = new BitReader($fileHandler);
     // read file header
     try {
         $fileHeader = FileHeader::createFromResource($filename, $fileHandler);
     } catch (Exception\IO\Input\FileCorruptedException $e) {
         throw $e;
     }
     // read compressed blocks
     $result = '';
     $isBlockFinal = false;
     while (false === $isBlockFinal) {
         $isBlockFinal = 1 === $bitReader->read(1);
         $compressionType = $bitReader->read(2);
         if (self::COMPRESSION_TYPE_NON_COMPRESSED === $compressionType) {
             // no compression
             $data = unpack("vlength/vlengthOneComplement", fread($fileHandler, 4));
             $result .= fread($fileHandler, $data['length']);
         } else {
             // compression
             if (self::COMPRESSION_TYPE_FIXED_HUFFMAN === $compressionType) {
                 list($literalsTree, $distancesTree) = $this->getFixedHuffmanTrees();
             } elseif (self::COMPRESSION_TYPE_DYNAMIC_HUFFMAN === $compressionType) {
                 list($literalsTree, $distancesTree) = $this->getDynamicHuffmanTrees($bitReader);
             } else {
                 throw new Exception\IO\Input\FileCorruptedException($filename);
             }
             $result .= $this->uncompressCompressedBlock($literalsTree, $distancesTree, $bitReader, $result);
         }
         $literalsTree = null;
         $distancesTree = null;
     }
     // check crc32
     $footer = unpack('Vcrc/Visize', fread($fileHandler, 8));
     if ($footer['crc'] !== crc32($result)) {
         throw new Exception\IO\Input\FileCorruptedException($filename);
     }
     fclose($fileHandler);
     // write file
     $outputFilename = $fileHeader->getOriginalFilename();
     if (empty($outputFilename)) {
         $outputFilename = pathinfo($filename, PATHINFO_FILENAME);
     }
     $location = $target . DIRECTORY_SEPARATOR . $outputFilename;
     file_put_contents($location, $result);
     return true;
 }