[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/Horde/Compress/ -> zip.php (source)

   1  <?php
   2  
   3  /**
   4   * For decompress(), return a list of files/information about the zipfile.
   5   */
   6  define('HORDE_COMPRESS_ZIP_LIST', 1);
   7  
   8  /**
   9   * For decompress(), return the data for an individual file in the zipfile.
  10   */
  11  define('HORDE_COMPRESS_ZIP_DATA', 2);
  12  
  13  /**
  14   * The Horde_Compress_zip class allows ZIP files to be created and
  15   * read.
  16   *
  17   * $Horde: framework/Compress/Compress/zip.php,v 1.11.12.16 2006/06/29 08:34:30 jan Exp $
  18   *
  19   * The ZIP compression code is partially based on code from:
  20   *   Eric Mueller <eric@themepark.com>
  21   *   http://www.zend.com/codex.php?id=535&single=1
  22   *
  23   *   Deins125 <webmaster@atlant.ru>
  24   *   http://www.zend.com/codex.php?id=470&single=1
  25   *
  26   * The ZIP compression date code is partially based on code from
  27   *   Peter Listiak <mlady@users.sourceforge.net>
  28   *
  29   * Copyright 2000-2006 Chuck Hagenbuch <chuck@horde.org>
  30   * Copyright 2002-2006 Michael Cochrane <mike@graftonhall.co.nz>
  31   * Copyright 2003-2006 Michael Slusarz <slusarz@bigworm.colorado.edu>
  32   *
  33   * See the enclosed file COPYING for license information (LGPL). If you
  34   * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  35   *
  36   * @author  Chuck Hagenbuch <chuck@horde.org>
  37   * @author  Michael Cochrane <mike@graftonhall.co.nz>
  38   * @author  Michael Slusarz <slusarz@bigworm.colorado.edu>
  39   * @since   Horde 3.0
  40   * @package Horde_Compress
  41   */
  42  class Horde_Compress_zip extends Horde_Compress {
  43  
  44      /**
  45       * ZIP compression methods.
  46       *
  47       * @var array
  48       */
  49      var $_methods = array(
  50          0x0 => 'None',
  51          0x1 => 'Shrunk',
  52          0x2 => 'Super Fast',
  53          0x3 => 'Fast',
  54          0x4 => 'Normal',
  55          0x5 => 'Maximum',
  56          0x6 => 'Imploded',
  57          0x8 => 'Deflated'
  58      );
  59  
  60      /**
  61       * Beginning of central directory record.
  62       *
  63       * @var string
  64       */
  65      var $_ctrlDirHeader = "\x50\x4b\x01\x02";
  66  
  67      /**
  68       * End of central directory record.
  69       *
  70       * @var string
  71       */
  72      var $_ctrlDirEnd = "\x50\x4b\x05\x06\x00\x00\x00\x00";
  73  
  74      /**
  75       * Beginning of file contents.
  76       *
  77       * @var string
  78       */
  79      var $_fileHeader = "\x50\x4b\x03\x04";
  80  
  81      /**
  82       * Create a ZIP compressed file from an array of file data.
  83       *
  84       * @param array $data    The data to compress.
  85       * <pre>
  86       * Requires an array of arrays - each subarray should contain the
  87       * following fields:
  88       * 'data' (string)   --  The data to compress.
  89       * 'name' (string)   --  The pathname to the file.
  90       * 'time' (integer)  --  [optional] The timestamp to use for the file.
  91       * </pre>
  92       * @param array $params  The parameter array (Unused).
  93       *
  94       * @return string  The ZIP file.
  95       */
  96      function compress($data, $params = array())
  97      {
  98          $contents = $ctrldir = array();
  99  
 100          foreach ($data as $val) {
 101              $this->_addToZIPFile($val, $contents, $ctrldir);
 102          }
 103  
 104          return $this->_createZIPFile($contents, $ctrldir);
 105      }
 106  
 107      /**
 108       * Decompress a ZIP file and get information from it.
 109       *
 110       * @param string $data   The zipfile data.
 111       * @param array $params  The parameter array.
 112       * <pre>
 113       * The following parameters are REQUIRED:
 114       * 'action' (integer)  =>  The action to take on the data.  Either
 115       *                         HORDE_COMPRESS_ZIP_LIST or
 116       *                         HORDE_COMPRESS_ZIP_DATA.
 117       *
 118       * The following parameters are REQUIRED for HORDE_COMPRESS_ZIP_DATA also:
 119       * 'info' (array)   =>  The zipfile list.
 120       * 'key' (integer)  =>  The position of the file in the archive list.
 121       * </pre>
 122       *
 123       * @return mixed  The requested data.
 124       */
 125      function decompress($data, $params)
 126      {
 127          if (isset($params['action'])) {
 128              if ($params['action'] == HORDE_COMPRESS_ZIP_LIST) {
 129                  return $this->_getZipInfo($data);
 130              } elseif ($params['action'] == HORDE_COMPRESS_ZIP_DATA) {
 131                  // TODO: Check for parameters.
 132                  return $this->_getZipData($data, $params['info'], $params['key']);
 133              } else {
 134                  return PEAR::raiseError(_("Incorrect action code given."), 'horde.error');
 135              }
 136          }
 137  
 138          return PEAR::raiseError(_("You must specify what action to perform."), 'horde.error');
 139      }
 140  
 141      /**
 142       * Get the list of files/data from the zip archive.
 143       *
 144       * @access private
 145       *
 146       * @param string &$data  The zipfile data.
 147       *
 148       * @return array  KEY: Position in zipfile
 149       *                VALUES: 'attr'    --  File attributes
 150       *                        'crc'     --  CRC checksum
 151       *                        'csize'   --  Compressed file size
 152       *                        'date'    --  File modification time
 153       *                        'name'    --  Filename
 154       *                        'method'  --  Compression method
 155       *                        'size'    --  Original file size
 156       *                        'type'    --  File type
 157       */
 158      function _getZipInfo(&$data)
 159      {
 160          $entries = array();
 161  
 162          /* Get details from Central directory structure. */
 163          $fhStart = strpos($data, $this->_ctrlDirHeader);
 164  
 165          do {
 166              if (strlen($data) < $fhStart + 31) {
 167                  return PEAR::raiseError(_("Invalid ZIP data"));
 168              }
 169              $info = unpack('vMethod/VTime/VCRC32/VCompressed/VUncompressed/vLength', substr($data, $fhStart + 10, 20));
 170              $name = substr($data, $fhStart + 46, $info['Length']);
 171  
 172              $entries[$name] = array(
 173                  'attr' => null,
 174                  'crc' => sprintf("%08s", dechex($info['CRC32'])),
 175                  'csize' => $info['Compressed'],
 176                  'date' => null,
 177                  '_dataStart' => null,
 178                  'name' => $name,
 179                  'method' => $this->_methods[$info['Method']],
 180                  '_method' => $info['Method'],
 181                  'size' => $info['Uncompressed'],
 182                  'type' => null
 183              );
 184  
 185              $entries[$name]['date'] =
 186                  mktime((($info['Time'] >> 11) & 0x1f),
 187                         (($info['Time'] >> 5) & 0x3f),
 188                         (($info['Time'] << 1) & 0x3e),
 189                         (($info['Time'] >> 21) & 0x07),
 190                         (($info['Time'] >> 16) & 0x1f),
 191                         ((($info['Time'] >> 25) & 0x7f) + 1980));
 192  
 193              if (strlen($data) < $fhStart + 43) {
 194                  return PEAR::raiseError(_("Invalid ZIP data"));
 195              }
 196              $info = unpack('vInternal/VExternal', substr($data, $fhStart + 36, 6));
 197  
 198              $entries[$name]['type'] = ($info['Internal'] & 0x01) ? 'text' : 'binary';
 199              $entries[$name]['attr'] =
 200                  (($info['External'] & 0x10) ? 'D' : '-') .
 201                  (($info['External'] & 0x20) ? 'A' : '-') .
 202                  (($info['External'] & 0x03) ? 'S' : '-') .
 203                  (($info['External'] & 0x02) ? 'H' : '-') .
 204                  (($info['External'] & 0x01) ? 'R' : '-');
 205          } while (($fhStart = strpos($data, $this->_ctrlDirHeader, $fhStart + 46)) !== false);
 206  
 207          /* Get details from local file header. */
 208          $fhStart = strpos($data, $this->_fileHeader);
 209  
 210          do {
 211              if (strlen($data) < $fhStart + 34) {
 212                  return PEAR::raiseError(_("Invalid ZIP data"));
 213              }
 214              $info = unpack('vMethod/VTime/VCRC32/VCompressed/VUncompressed/vLength/vExtraLength', substr($data, $fhStart + 8, 25));
 215              $name = substr($data, $fhStart + 30, $info['Length']);
 216              $entries[$name]['_dataStart'] = $fhStart + 30 + $info['Length'] + $info['ExtraLength'];
 217          } while (strlen($data) > $fhStart + 30 + $info['Length'] &&
 218                   ($fhStart = strpos($data, $this->_fileHeader, $fhStart + 30 + $info['Length'])) !== false);
 219  
 220          return array_values($entries);
 221      }
 222  
 223      /**
 224       * Returns the data for a specific archived file.
 225       *
 226       * @access private
 227       *
 228       * @param string &$data  The zip archive contents.
 229       * @param array &$info   The information array from _getZipInfo().
 230       * @param integer $key   The position of the file in the archive.
 231       *
 232       * @return string  The file data.
 233       */
 234      function _getZipData(&$data, &$info, $key)
 235      {
 236          if (($info[$key]['_method'] == 0x8) && Util::extensionExists('zlib')) {
 237              /* If the file has been deflated, and zlib is installed,
 238                 then inflate the data again. */
 239              return @gzinflate(substr($data, $info[$key]['_dataStart'], $info[$key]['csize']));
 240          } elseif ($info[$key]['_method'] == 0x0) {
 241              /* Files that aren't compressed. */
 242              return substr($data, $info[$key]['_dataStart'], $info[$key]['csize']);
 243          }
 244  
 245          return '';
 246      }
 247  
 248      /**
 249       * Checks to see if the data is a valid ZIP file.
 250       *
 251       * @param string &$data  The ZIP file data.
 252       *
 253       * @return boolean  True if valid, false if invalid.
 254       */
 255      function checkZipData(&$data)
 256      {
 257          if (strpos($data, $this->_fileHeader) === false) {
 258              return false;
 259          } else {
 260              return true;
 261          }
 262      }
 263  
 264      /**
 265       * Converts a UNIX timestamp to a 4-byte DOS date and time format
 266       * (date in high 2-bytes, time in low 2-bytes allowing magnitude
 267       * comparison).
 268       *
 269       * @access private
 270       *
 271       * @param integer $unixtime  The current UNIX timestamp.
 272       *
 273       * @return integer  The current date in a 4-byte DOS format.
 274       */
 275      function _unix2DOSTime($unixtime = null)
 276      {
 277          $timearray = (is_null($unixtime)) ? getdate() : getdate($unixtime);
 278  
 279          if ($timearray['year'] < 1980) {
 280              $timearray['year']    = 1980;
 281              $timearray['mon']     = 1;
 282              $timearray['mday']    = 1;
 283              $timearray['hours']   = 0;
 284              $timearray['minutes'] = 0;
 285              $timearray['seconds'] = 0;
 286          }
 287  
 288          return (($timearray['year'] - 1980) << 25) |
 289                  ($timearray['mon'] << 21) |
 290                  ($timearray['mday'] << 16) |
 291                  ($timearray['hours'] << 11) |
 292                  ($timearray['minutes'] << 5) |
 293                  ($timearray['seconds'] >> 1);
 294      }
 295  
 296      /**
 297       * Adds a "file" to the ZIP archive.
 298       *
 299       * @access private
 300       *
 301       * @param array &$file      See Horde_Compress_zip::createZipFile().
 302       * @param array &$contents  An array of existing zipped files.
 303       * @param array &$ctrldir   An array of central directory information.
 304       */
 305      function _addToZIPFile(&$file, &$contents, &$ctrldir)
 306      {
 307          $data = &$file['data'];
 308          $name = str_replace('\\', '/', $file['name']);
 309  
 310          /* See if time/date information has been provided. */
 311          $ftime = null;
 312          if (isset($file['time'])) {
 313              $ftime = $file['time'];
 314          }
 315  
 316          /* Get the hex time. */
 317          $dtime    = dechex($this->_unix2DosTime($ftime));
 318          $hexdtime = chr(hexdec($dtime[6] . $dtime[7])) .
 319                      chr(hexdec($dtime[4] . $dtime[5])) .
 320                      chr(hexdec($dtime[2] . $dtime[3])) .
 321                      chr(hexdec($dtime[0] . $dtime[1]));
 322  
 323          $fr  = $this->_fileHeader;   /* Begin creating the ZIP data. */
 324          $fr .= "\x14\x00";           /* Version needed to extract. */
 325          $fr .= "\x00\x00";           /* General purpose bit flag. */
 326          $fr .= "\x08\x00";           /* Compression method. */
 327          $fr .= $hexdtime;            /* Last modification time/date. */
 328  
 329          /* "Local file header" segment. */
 330          $unc_len = strlen($data);
 331          $crc     = crc32($data);
 332          $zdata   = gzcompress($data);
 333          $zdata   = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
 334          $c_len   = strlen($zdata);
 335  
 336          $fr .= pack('V', $crc);            /* CRC 32 information. */
 337          $fr .= pack('V', $c_len);          /* Compressed filesize. */
 338          $fr .= pack('V', $unc_len);        /* Uncompressed filesize. */
 339          $fr .= pack('v', strlen($name));   /* Length of filename. */
 340          $fr .= pack('v', 0);               /* Extra field length. */
 341          $fr .= $name;                      /* File name. */
 342  
 343          /* "File data" segment. */
 344          $fr .= $zdata;
 345  
 346          /* "Data descriptor" segment (optional but necessary if archive is
 347             not served as file). */
 348          $fr .= pack('V', $crc);
 349          $fr .= pack('V', $c_len);
 350          $fr .= pack('V', $unc_len);
 351  
 352          /* Add this entry to array. */
 353          $old_offset = strlen(implode('', $contents));
 354          $contents[] = &$fr;
 355  
 356          /* Add to central directory record. */
 357          $cdrec  = $this->_ctrlDirHeader;
 358          $cdrec .= "\x00\x00";                /* Version made by. */
 359          $cdrec .= "\x14\x00";                /* Version needed to extract */
 360          $cdrec .= "\x00\x00";                /* General purpose bit flag */
 361          $cdrec .= "\x08\x00";                /* Compression method */
 362          $cdrec .= $hexdtime;                 /* Last mod time/date. */
 363          $cdrec .= pack('V', $crc);           /* CRC 32 information. */
 364          $cdrec .= pack('V', $c_len);         /* Compressed filesize. */
 365          $cdrec .= pack('V', $unc_len);       /* Uncompressed filesize. */
 366          $cdrec .= pack('v', strlen($name));  /* Length of filename. */
 367          $cdrec .= pack('v', 0);              /* Extra field length. */
 368          $cdrec .= pack('v', 0);              /* File comment length. */
 369          $cdrec .= pack('v', 0);              /* Disk number start. */
 370          $cdrec .= pack('v', 0);              /* Internal file attributes. */
 371          $cdrec .= pack('V', 32);             /* External file attributes -
 372                                                  'archive' bit set. */
 373          $cdrec .= pack('V', $old_offset);    /* Relative offset of local
 374                                                  header. */
 375          $cdrec .= $name;                     /* File name. */
 376          /* Optional extra field, file comment goes here. */
 377  
 378          // Save to central directory array. */
 379          $ctrldir[] = &$cdrec;
 380      }
 381  
 382      /**
 383       * Creates the ZIP file.
 384       * Official ZIP file format: http://www.pkware.com/appnote.txt
 385       *
 386       * @access private
 387       *
 388       * @return string  The ZIP file.
 389       */
 390      function _createZIPFile(&$contents, &$ctrlDir)
 391      {
 392          $data = implode('', $contents);
 393          $dir = implode('', $ctrlDir);
 394  
 395          return $data . $dir . $this->_ctrlDirEnd .
 396              /* Total # of entries "on this disk". */
 397              pack('v', count($ctrlDir)) .
 398              /* Total # of entries overall. */
 399              pack('v', count($ctrlDir)) .
 400              /* Size of central directory. */
 401              pack('V', strlen($dir)) .
 402              /* Offset to start of central dir. */
 403              pack('V', strlen($data)) .
 404              /* ZIP file comment length. */
 405              "\x00\x00";
 406      }
 407  
 408  }


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7