phpbar.de logo

Mailinglisten-Archive

[php] Entpacken von ZIP Files

[php] Entpacken von ZIP Files

Niels Jäckel niels.jaeckel at silice.de
Mon Nov 29 20:03:42 CET 2004


Hallo zusammen,

ich habe mir vor einiger Zeit selber mal eine Funktion geschrieben, die 
einen String als Zip-Datei behandelt und entpacken kann. Ich hatte zwar 
auch mal mit der ZipLib rumprobiert, und war auch zufrieden, musste 
jedoch feststellen, dass die nicht auf jedem x-beliebigen Server 
installiert ist.

Also hab ich mir das Zip-Format mal angesehn, und eine Funktion 
geschrieben, die Zip-Strings entpackt und als Array zurückliefert.

Ein Aufruf könnte so aussehen:

$content = file_get_contents('mein_zip.zip');
$data = getZipFileContents($content);


Wenn man ausführliche Informationen erhalten möchte, ruft man die 
Funktion mit dem zusätzlichen (optionalen) Parameter TRUE auf.

Die Struktur des Ergebnis-Arrays ändert sich jeweils, ist aber per 
print_f einfach rauszubekommen.


Weiterer Vorteil dieser Funktion:
Man könnte auch eine per HTTP abgerufene Zip-Datei somit einfach 
entpacken. Das Anlegen einer temporären Datei entfällt.
Da die Funktion so kurz gehalten ist, arbeitet sie auch schnell.


Nachteil:
Die Funktion ist reduziert auf die nötigsten Funktionen und unterstützt 
z.B. keine Passwort-Entschlüsselung oder gesplittete Archive.

Ausserdem wird die zlib Bibliothek von Jean-loup Gailly und Mark Adler 
benutzt, die jedoch auf den meisten (Low-Cost) Host Servern installiert ist.



       /*
       * zip file extraction function
       *
       * REDUCED TO THE MOST COMMON OPTIONS:
       * - no password decryption
       * - no splitted archives
       *
       * Copyright (C) 2004 Niels Jäckel <niels.jaeckel at silice.de>
       *
       *
       * @param string $file_contents this is the *full* content of the 
.zip file
       * @param $full_information optional parameter to get full 
information (TRUE | FALSE)
       *
       * @return array $contents
       *
       */

       function getZipFileContents($file_contents, $full_information = 
FALSE)
          {

              /* getting position of central directory */

             $file_size = strlen($file_contents);
             $pointer = $file_size - 277;

             if ($pointer < 0) { $pointer = 0; }
             $pointer = strpos($file_contents, 
"\x50\x4b\x05\x06\x00\x00\x00\x00", $pointer) + 4;


             /* reading central directory */

             $central_directory = 
unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', 
substr($file_contents, $pointer, 18));

             $pointer = $central_directory['offset'];
             $archive_data = array();

             /* getting archive data */

             for ($t = $central_directory['disk_start']; $t < 
$central_directory['disk_entries']; $t++)
                {

                   /* reading central file header */
                   $central_file_header = 
unpack('vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', 
substr($file_contents, $pointer, 46));

                   /* extracting filename */
                   $filename = substr($file_contents, $pointer + 46, 
$central_file_header['filename_len']);

                   /* extracting extrafield */
                   $extra = substr($file_contents, $pointer + 46 + 
$central_file_header['filename_len'], $central_file_header['extra_len']);

                   /* extracting comment */
                   $comment = substr($file_contents, $pointer + 46 + 
$central_file_header['filename_len'] + 
$central_file_header['extra_len'], $central_file_header['comment_len']);

                   $pointer += 46 + $central_file_header['filename_len'] 
+ $central_file_header['extra_len'] + $central_file_header['comment_len'];


                   /* filter directories */
                   if ($filename{strlen($filename) - 1} != '/')
                      {

                         /* calculating position of compressed content */
                         $content_start = $central_file_header['offset'] 
+ 30 + $central_file_header['filename_len'] + 
$central_file_header['extra_len'];

                         if ($central_file_header['compression'] == 0)
                            {

                               /* extracting uncompressed content */
                               $content = substr($file_contents, 
$content_start, $central_file_header['compressed_size']);

                            }
                            else
                            {

                               /* extracting compressed content */
                               $content = substr($file_contents, 
$content_start, $central_file_header['compressed_size']);
                               $content .= pack('VV', 
$central_file_header['crc'], $central_file_header['size']);

                               /* decompressing content */
                               $content = @gzinflate($content);

                            }

                         /* getting filestatus */
                         $status = 'ok';

                         if ($content === FALSE && $status == 'ok') { 
$status = 'err_decompress'; }
                         if (crc32($content) != 
$central_file_header['crc'] && $status == 'ok') { $status = 'err_crc'; }
                         if (strlen($content) != 
$central_file_header['size'] && $status == 'ok') { $status = 'err_length'; }


                         /* saving information */
                         if ($full_information)
                            {

                               if ($central_file_header['mdate'] && 
$central_file_header['mtime'])
                                  {
                                     $hour = 
($central_file_header['mtime'] & 0xF800) >> 11;
                                     $minute = 
($central_file_header['mtime'] & 0x07E0) >> 5;
                                     $seconde = 
($central_file_header['mtime'] & 0x001F)*2;
                                     $year = 
(($central_file_header['mdate'] & 0xFE00) >> 9) + 1980;
                                     $month = 
($central_file_header['mdate'] & 0x01E0) >> 5;
                                     $day = 
$central_file_header['mdate'] & 0x001F;
                                     $timestamp = mktime($hour, $minute, 
$seconde, $month, $day, $year);
                                  }
                                  else
                                  {
                                     $timestamp = time();
                                  }

                               $i = count($archive_data);

                               $archive_data[$i] = array();
                               $archive_data[$i]['filename'] = $filename;
                               $archive_data[$i]['timestamp'] = $timestamp;
                               $archive_data[$i]['comment'] = $comment;
                               $archive_data[$i]['extrafield'] = $extra;
                               $archive_data[$i]['status'] = $status;

                               if ($status == 'ok')
                                  {
                                     $archive_data[$i]['content'] = 
$content;
                                  }
                                  else
                                  {
                                     $archive_data[$i]['content'] = FALSE;
                                  }

                            }
                            else
                            {
                               if ($status == 'ok')
                                  {
                                     $archive_data[$filename] = $content;
                                  }
                                  else
                                  {
                                     $archive_data[$filename] = FALSE;
                                  }
                            }
                      }
                }

             return $archive_data;

          }

php::bar PHP Wiki   -   Listenarchive