sTEFANs Subversion Web Contol (SWC)
Inc
[ class tree: Swc ] [ index: Swc ] [ all elements ]

Source for file zip.inc.php

Documentation is available at zip.inc.php

  1.  <?php
  2. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3. SVN Web Control
  4. Copyright ©2006 by sTEFANs
  5. Created on 25.02.2006
  6. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330,
  20. Boston, MA 02111-1307, USA.
  21. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  22. */
  23.  
  24. /**
  25.  * This file contains a classes for creating ZIP archive files.ed.
  26.  * 
  27.  * @package Swc
  28.  * @subpackage Inc
  29.  * @author Eric Mueller
  30.  * @author Denis125
  31.  * @author Stefan Schraml
  32.  * @license http://opensource.org/licenses/lgpl-license.php GNU General Public License
  33.  * @version v1.1.0
  34.  * @since v1.1.0
  35.  */
  36.  
  37. /**
  38.  * Zip file creation class.
  39.  * Makes zip files.
  40.  *
  41.  * Based on :
  42.  * <br>
  43.  * http://www.zend.com/codex.php?id=535&single=1
  44.  * By Eric Mueller <eric@themepark.com>
  45.  * <br>
  46.  * http://www.zend.com/codex.php?id=470&single=1
  47.  * by Denis125 <webmaster@atlant.ru>
  48.  * <br>
  49.  * http://www.traum-projekt.com/forum/sitemap/t-62354.html
  50.  * by Peter Listiak <mlady@users.sourceforge.net>, pathch for last modified
  51.  * date and time of the compressed file
  52.  * <br>
  53.  * Interface and public methods by Stefan Schraml
  54.  * <br>
  55.  * Official ZIP file format: http://www.pkware.com/appnote.txt
  56.  * <br>
  57.  * @access public
  58.  * @version v1.1.0
  59.  * @since v1.1.0
  60. */
  61. class zipfile  
  62. {
  63.     /** 
  64.      * Array to store compressed data
  65.      * @var array $datasec 
  66.      * @since v1.1.0
  67.      */
  68.   private $datasec = array()// array to store compressed data
  69.     
  70.     
  71.     
  72.     /**
  73.      * Central directory
  74.      * @var array $ctrl_dir 
  75.      * @since v1.1.0
  76.      */
  77.   private $ctrl_dir = array()// central directory
  78.     
  79.     
  80.     
  81.     /**
  82.      * End of central directory record
  83.      * @var string $eof_ctrl_dir 
  84.      * @since v1.1.0
  85.      */
  86.   private $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"//end of Central directory record
  87.     
  88.     
  89.     
  90.     /**
  91.      * Last offset position
  92.      * @var integer $old_offset 
  93.      * @since v1.1.0
  94.      */
  95.     private $old_offset = 0;
  96.  
  97.     /** 
  98.      * Adds the given file or directory tree to the archive.
  99.      * @param string $path File or directory to zip. If a directory is given, the content
  100.      *  (all the files and subdirectories) will be added to the archive.
  101.      * @param boolean $recursive If set to TRUE, content of the given directory and all its
  102.      *  sub directories will be added to the archive. Otherwise only the content of directory is added.
  103.      *  Has no effect $path is a file.
  104.      * @return boolean TRUE if zipping was successful.
  105.      * @access public
  106.      * @since v1.1.0
  107.      */
  108.     function zip($path$recursive true){
  109.         return $this->zipReplacePath($pathNULLNULL$recursive);        
  110.     }
  111.  
  112.     /** 
  113.      * Adds the given file or directory tree to the archive.
  114.      * @param string $path File or directory to zip. If a directory is given, the content
  115.      *  (all the files and subdirectories) will be added to the archive.
  116.      * @param string $search_pattern If it is not NULL, it defines the part of $path which will
  117.      *  be replaced by $replace_pattern.
  118.      * @param string $replace_pattern Text which is substituted for $search_pattern. If it is
  119.      *  set NULL, $search_pattern will be replaced by empty ("").
  120.      * @param boolean $recursive If set to TRUE, content of the given directory and all its
  121.      *  sub directories will be added to the archive. Otherwise only the content of directory is added.
  122.      *  Has no effect $path is a file.
  123.      * @return boolean TRUE if zipping was successful.
  124.      * @access public
  125.      * @since v1.1.0
  126.      */
  127.     function zipReplacePath($path$search_pattern$replace_pattern$recursive true){
  128.         $rc true;
  129.         $src $path;
  130.         $name $path;
  131.         if ($search_pattern != NULL){
  132.             $replace_pattern ($replace_pattern == NULL "" $replace_pattern);
  133.             $name str_replace($search_pattern$replace_pattern$path);
  134.             if (strpos($name"/"=== 0){
  135.                 $name substr($name1);
  136.             }
  137.         }
  138.         if (@is_dir($src)) {
  139.             if ($name != ""){
  140. // Removed because it doesn't work
  141. //                $this->addDir($name, filemtime($src));
  142.             }
  143.             if(!$dh @opendir($src)){
  144.                 $rc false;
  145.             }
  146.             while ($rc && $obj @readdir($dh)){
  147.                 if($obj != '.' && $obj != '..'){
  148.                     $path $src.'/'.$obj;
  149.                     if ($recursive || !@is_dir($path)){
  150.                         $rc $this->zipReplacePath($path$search_pattern$replace_pattern$recursive);
  151.                     }
  152.                 }
  153.             }
  154.         else {
  155.             $this->addFile(file_get_contents($src)$namefilemtime($src));
  156.         }
  157.         return $rc;        
  158.     }
  159.  
  160.   /** 
  161.    * Writes the archive to the given path.
  162.    * @param string $path Path for the ZIP-File (e.g. /mydir/myfile.zip).
  163.    * @access public
  164.      * @since v1.1.0
  165.    */
  166.   function store($path){
  167.       $fh fopen($path'wb');
  168.       $rc $fh !== false
  169.       $rc $rc && fwrite($fh$this->getFileContent());
  170.       $rc $rc && fflush($fh);
  171.       $rc $rc && fclose($fh);
  172.       return $rc;
  173.   }
  174.     
  175.     /**
  176.      * Don't really know what it does. If method is invoked to add a directory
  177.      * to the archive, LINUX zip (Zip 2.3 (November 29th 1999), by Info-ZIP)
  178.      * is not able to extract the archive. I leave it for the reason
  179.      * of completness but it's not invoked anymore (and this works great!).
  180.      * <b>Note: The following description is wrong!</b><br>
  181.      * Adds the given directory path into archive.
  182.      * Do this before putting any files in directory!
  183.      * E.g. add "path/" before adding file "path/file.txt".
  184.      * @param string name of the directory in the archive (e.g. "path/").
  185.      * @param integer the current unix-style timestamp
  186.      * @access private
  187.      * @since v1.1.0
  188.     */
  189.     function addDir($name$timestamp 0){  
  190.         $name str_replace("\\""/"$name);
  191.         $hexdtime $this->encodeUnixTimestamp($timestamp);
  192.         
  193.         $fr "\x50\x4b\x03\x04";
  194.         $fr .= "\x0a\x00";        // ver needed to extract
  195.         $fr .= "\x00\x00";        // gen purpose bit flag
  196.         $fr .= "\x00\x00";        // compression method
  197.         $fr .= $hexdtime;         // last mod time and date
  198.  
  199.         $fr .= pack("V",0)// crc32
  200.         $fr .= pack("V",0)//compressed filesize
  201.         $fr .= pack("V",0)//uncompressed filesize
  202.         $fr .= pack("v"strlen($name) )//length of pathname
  203.         $fr .= pack("v")//extra field length
  204.         $fr .= $name;  
  205.         // end of "local file header" segment
  206.  
  207.         // no "file data" segment for path
  208.  
  209.         // "data descriptor" segment (optional but necessary if archive is not served as file)
  210.         $unc_len 0;  
  211.         $crc 0;  
  212.         $c_len 0;
  213.         
  214.         $fr .= pack("V",$crc)//crc32
  215.         $fr .= pack("V",$c_len)//compressed filesize
  216.         $fr .= pack("V",$unc_len)//uncompressed filesize
  217.  
  218.         // add this entry to array
  219.         $this -> datasec[$fr;
  220.  
  221.         $new_offset strlen(implode(""$this->datasec));
  222.  
  223.         // ext. file attributes mirrors MS-DOS directory attr byte, detailed
  224.         // at http://support.microsoft.com/support/kb/articles/Q125/0/19.asp
  225.  
  226.         // now add to central record
  227.         $cdrec "\x50\x4b\x01\x02";
  228.         $cdrec .="\x00\x00";    // version made by
  229.         $cdrec .="\x0a\x00";    // version needed to extract
  230.         $cdrec .="\x00\x00";    // gen purpose bit flag
  231.         $cdrec .="\x00\x00";    // compression method
  232.         $cdrec .=$hexdtime;        // last mod time & date
  233.         $cdrec .= pack("V",0)// crc32
  234.         $cdrec .= pack("V",0)//compressed filesize
  235.         $cdrec .= pack("V",0)//uncompressed filesize
  236.         $cdrec .= pack("v"strlen($name) )//length of filename
  237.         $cdrec .= pack("v")//extra field length   
  238.         $cdrec .= pack("v")//file comment length
  239.         $cdrec .= pack("v")//disk number start
  240.         $cdrec .= pack("v")//internal file attributes
  241.         $ext "\x00\x00\x10\x00";
  242.         $ext "\xff\xff\xff\xff";  
  243.         $cdrec .= pack("V"16 )//external file attributes  - 'directory' bit set
  244.  
  245.         $cdrec .= pack("V"$this -> old_offset )//relative offset of local header
  246.         $this -> old_offset = $new_offset;
  247.  
  248.         $cdrec .= $name;  
  249.         // optional extra field, file comment goes here
  250.         // save to array
  251.         $this -> ctrl_dir[$cdrec;  
  252.  
  253.          
  254.     }
  255.  
  256.     /**
  257.      * Adds "file" to archive
  258.      * @param string data content
  259.      * @param string name of the file in the archive (may contains the path).
  260.      *  Path must have been added previously via <i>addDir</i>
  261.      * @param integer the current unix-style timestamp
  262.      * @access private
  263.      * @since v1.1.0
  264.     */
  265.     function addFile($data$name$timestamp 0)
  266.     {  
  267.         $name str_replace("\\""/"$name);
  268.         $hexdtime $this->encodeUnixTimestamp($timestamp);
  269.  
  270.         $fr "\x50\x4b\x03\x04";
  271.         $fr .= "\x14\x00";    // ver needed to extract
  272.         $fr .= "\x00\x00";    // gen purpose bit flag
  273.         $fr .= "\x08\x00";    // compression method
  274.         $fr .= $hexdtime;     // last mod time and date
  275.  
  276.         $unc_len strlen($data);  
  277.         $crc crc32($data);  
  278.         $zdata gzcompress($data);  
  279.         $zdata substrsubstr($zdata0strlen($zdata4)2)// fix crc bug
  280.         $c_len strlen($zdata);  
  281.         $fr .= pack("V",$crc)// crc32
  282.         $fr .= pack("V",$c_len)//compressed filesize
  283.         $fr .= pack("V",$unc_len)//uncompressed filesize
  284.         $fr .= pack("v"strlen($name) )//length of filename
  285.         $fr .= pack("v")//extra field length
  286.         $fr .= $name;  
  287.         // end of "local file header" segment
  288.          
  289.         // "file data" segment
  290.         $fr .= $zdata;  
  291.  
  292.         // "data descriptor" segment (optional but necessary if archive is not served as file)
  293.         $fr .= pack("V",$crc)//crc32
  294.         $fr .= pack("V",$c_len)//compressed filesize
  295.         $fr .= pack("V",$unc_len)//uncompressed filesize
  296.  
  297.         // add this entry to array
  298.         $this -> datasec[$fr;
  299.  
  300.         $new_offset strlen(implode(""$this->datasec));
  301.  
  302.         // now add to central directory record
  303.         $cdrec "\x50\x4b\x01\x02";
  304.         $cdrec .="\x00\x00";    // version made by
  305.         $cdrec .="\x14\x00";    // version needed to extract
  306.         $cdrec .="\x00\x00";    // gen purpose bit flag
  307.         $cdrec .="\x08\x00";    // compression method
  308.         $cdrec .=$hexdtime;        // last mod time & date
  309.         $cdrec .= pack("V",$crc)// crc32
  310.         $cdrec .= pack("V",$c_len)//compressed filesize
  311.         $cdrec .= pack("V",$unc_len)//uncompressed filesize
  312.         $cdrec .= pack("v"strlen($name) )//length of filename
  313.         $cdrec .= pack("v")//extra field length   
  314.         $cdrec .= pack("v")//file comment length
  315.         $cdrec .= pack("v")//disk number start
  316.         $cdrec .= pack("v")//internal file attributes
  317.         $cdrec .= pack("V"32 )//external file attributes - 'archive' bit set
  318.  
  319.         $cdrec .= pack("V"$this -> old_offset )//relative offset of local header
  320. //      &n // bsp; echo "old offset is ".$this->old_offset.", new offset is $new_offset<br>";
  321.         $this -> old_offset = $new_offset;
  322.  
  323.         $cdrec .= $name;  
  324.         // optional extra field, file comment goes here
  325.         // save to central directory
  326.         $this -> ctrl_dir[$cdrec;  
  327.     }       
  328.     
  329.     /** 
  330.      * Returns the archive file content.
  331.      * @return Binary content of ZIP file.
  332.      * @access private
  333.      * @since v1.1.0
  334.      */
  335.   function getFileContent(// dump out file   
  336.     $data implode(""$this -> datasec);  
  337.     $ctrldir implode(""$this -> ctrl_dir);  
  338.  
  339.     return   
  340.         $data.  
  341.         $ctrldir.  
  342.         $this -> eof_ctrl_dir.  
  343.         pack("v"sizeof($this -> ctrl_dir)).     // total # of entries "on this disk"
  344.         pack("v"sizeof($this -> ctrl_dir)).     // total # of entries overall
  345.         pack("V"strlen($ctrldir)).             // size of central dir
  346.         pack("V"strlen($data)).                 // offset to start of central dir
  347.         "\x00\x00";                             // .zip file comment length
  348.   }
  349.   
  350.   /**
  351.    * Returns timestamp in format needed by zip archive.
  352.    * @param int $timestamp UNIX timestamp.
  353.    * @return string Timestamp encoded to ZIP format.
  354.      * @since v1.1.0
  355.    */
  356.   function encodeUnixTimestamp($timestamp){
  357.       $hexdtime "\x00\x00\x00\x00";
  358.       if ($timestamp != 0){
  359.         $dtime dechex($this->unix2DosTime($timestamp));
  360.         $hexdtime '\x'.$dtime[6].$dtime[7]
  361.         . '\x'.$dtime[4].$dtime[5]
  362.         . '\x'.$dtime[2].$dtime[3]
  363.         . '\x'.$dtime[0].$dtime[1];
  364.         eval('$hexdtime = "' $hexdtime '";');
  365.       }
  366.       return $hexdtime;
  367.   }
  368.     
  369.     
  370.     /**
  371.      * Converts an Unix timestamp to a four byte DOS date and time format (date
  372.      * in high two bytes, time in low two bytes allowing magnitude comparison).
  373.      * @param integer the current Unix timestamp
  374.      * @return integer the current date in a four byte DOS format
  375.      * @access private
  376.      * @since v1.1.0
  377.     */
  378.     function unix2DosTime($unixtime 0{
  379.         $timearray ($unixtime == 0getdate(getdate($unixtime);
  380.         
  381.         if ($timearray['year'1980{
  382.             $timearray['year'1980;
  383.             $timearray['mon'1;
  384.             $timearray['mday'1;
  385.             $timearray['hours'0;
  386.             $timearray['minutes'0;
  387.             $timearray['seconds'0;
  388.         // end if
  389.         
  390.         return (($timearray['year'1980<< 25($timearray['mon'<< 21|
  391.             ($timearray['mday'<< 16|
  392.             ($timearray['hours'<< 11($timearray['minutes'<< 5|
  393.             ($timearray['seconds'>> 1);
  394.     }
  395. }
  396. ?>

Documentation generated on Fri, 03 Nov 2006 18:45:08 +0100 by phpDocumentor 1.3.0RC6
for sTEFANs POWERED BY eBC.bz