Read zip file without zip extension / ZipArchive

  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13502
  • Loc: Florida

Post 3+ Months Ago

I put together this quick and dirty code for retrieving the filenames and content positions of compressed files in a zip file with PHP. I was having a tough time finding something in PHP to read zip files that didn't depend on functions such as zip_open or the ZipArchive class. This code is far from full-featured, but it works for simple zip files like you might create by selecting a group of files on your desktop and selecting "send to -> compressed (zipped) folder" from the right-click menu.

Basically a zip file is a series of 30 byte headers of which the first 4 bytes are a signature (0x04034b50) followed by variable length filename and extra info sections, which are in turn followed by variable length sections of compressed content.

The function quickly scans the passed file and returns an array of arrays. Each array includes the filename, offset of the files compressed content in the file, and the size of the compressed content.

The function takes a single argument, the filename of the zip file.

PHP Code: [ Select ]
<?php
 
function zip_list($filename)
{
   $size    = filesize($filename);
   $position   = 0;
   $signature  = 0x04034b50;
   $files      = array();
 
   $fh         = fopen($filename, 'r');
 
   while($position < $size)
   {
      fseek($fh, $position);
      $h = fread($fh, 30); // fixed length section of header.
 
      if(array_shift(unpack('V', substr($h, 0, 4))) != $signature)
      {
         break;
      }
 
      $name_len   = array_shift(unpack('v', $h[26].$h[27]));
      $xtra_len   = array_shift(unpack('v', $h[28].$h[29]));
      $comp_size  = array_shift(unpack('V', $h[18].$h[19].$h[20].$h[21]));
 
      $filename   = implode(array_map('chr', unpack("C{$name_len}", fread($fh, $name_len))));
      $files[] = array(
         'filename'  => $filename,
         'offset' => ftell($fh) + $xtra_len,
         'length' => $comp_size
      );
 
      $position   = ftell($fh) + $xtra_len + $comp_size;
   }
 
   fclose($fh);
 
   return $files;
}
 
?>
  1. <?php
  2.  
  3. function zip_list($filename)
  4. {
  5.    $size    = filesize($filename);
  6.    $position   = 0;
  7.    $signature  = 0x04034b50;
  8.    $files      = array();
  9.  
  10.    $fh         = fopen($filename, 'r');
  11.  
  12.    while($position < $size)
  13.    {
  14.       fseek($fh, $position);
  15.       $h = fread($fh, 30); // fixed length section of header.
  16.  
  17.       if(array_shift(unpack('V', substr($h, 0, 4))) != $signature)
  18.       {
  19.          break;
  20.       }
  21.  
  22.       $name_len   = array_shift(unpack('v', $h[26].$h[27]));
  23.       $xtra_len   = array_shift(unpack('v', $h[28].$h[29]));
  24.       $comp_size  = array_shift(unpack('V', $h[18].$h[19].$h[20].$h[21]));
  25.  
  26.       $filename   = implode(array_map('chr', unpack("C{$name_len}", fread($fh, $name_len))));
  27.       $files[] = array(
  28.          'filename'  => $filename,
  29.          'offset' => ftell($fh) + $xtra_len,
  30.          'length' => $comp_size
  31.       );
  32.  
  33.       $position   = ftell($fh) + $xtra_len + $comp_size;
  34.    }
  35.  
  36.    fclose($fh);
  37.  
  38.    return $files;
  39. }
  40.  
  41. ?>


With that you can use file_get_contents and gzinflate to retrieve the compressed sections for each file and decompress them.

PHP Code: [ Select ]
<?php
 
$zip = zip_list('file.zip');
 
for($i = 0, $toi = count($zip); $i < $toi; $i++)
{
    $compressed_str = file_get_contents('file.zip', null, null, $zip[$i]['offset'], $zip[$i]['length']);
    $decompressed_str = gzinflate($compressed_str);
    file_put_contents($zip[$i]['filename'], $decompressed_str);
}
 
?>
  1. <?php
  2.  
  3. $zip = zip_list('file.zip');
  4.  
  5. for($i = 0, $toi = count($zip); $i < $toi; $i++)
  6. {
  7.     $compressed_str = file_get_contents('file.zip', null, null, $zip[$i]['offset'], $zip[$i]['length']);
  8.     $decompressed_str = gzinflate($compressed_str);
  9.     file_put_contents($zip[$i]['filename'], $decompressed_str);
  10. }
  11.  
  12. ?>


For reference sake, here's my go-to post for when I need to write zip files without the zip extensions available.
programming-forum/php-zipping-and-entire-directory-t54069.html#p282162 :D
  • Anonymous
  • Bot
  • No Avatar
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post 3+ Months Ago

  • navidimran
  • Graduate
  • Graduate
  • navidimran
  • Posts: 142

Post 3+ Months Ago

You have my day with the PHP function that unzips zip file without an extractor. Thanks a lot for this help.

Post Information

  • Total Posts in this topic: 2 posts
  • Users browsing this forum: No registered users and 70 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
cron
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.