source: temp/test-xoops.ec-cube.net/html/class/class.zipfile.php @ 405

Revision 405, 6.4 KB checked in by root, 20 years ago (diff)
Line 
1<?php
2// $Id: class.zipfile.php,v 1.2 2005/03/18 12:51:55 onokazu Exp $
3/*
4    package::i.tools
5
6    php-downloader  v1.0    -   www.ipunkt.biz
7
8    (c) 2002 - www.ipunkt.biz (rok)
9
10 * Zip file creation class.
11 * Makes zip files.
12 *
13 * Based on :
14 *
15 *  http://www.zend.com/codex.php?id=535&single=1
16 *  By Eric Mueller <[email protected]>
17 *
18 *  http://www.zend.com/codex.php?id=470&single=1
19 *  by Denis125 <[email protected]>
20 *
21 *  a patch from Peter Listiak <[email protected]> for last modified
22 *  date and time of the compressed file
23 *
24 * Official ZIP file format: http://www.pkware.com/appnote.txt
25 *
26 * @copyright   (c) 2002 - www.ipunkt.biz (rok)
27 * @access  public
28 *
29 * @package     kernel
30 * @subpackage  core
31 */
32class zipfile
33{
34    /**
35     * Array to store compressed data
36     *
37     * @var  array    $datasec
38     */
39    var $datasec      = array();
40
41    /**
42     * Central directory
43     *
44     * @var  array    $ctrl_dir
45     */
46    var $ctrl_dir     = array();
47
48    /**
49     * End of central directory record
50     *
51     * @var  string   $eof_ctrl_dir
52     */
53    var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
54
55    /**
56     * Last offset position
57     *
58     * @var  integer  $old_offset
59     */
60    var $old_offset   = 0;
61
62
63    /**
64     * Converts an Unix timestamp to a four byte DOS date and time format (date
65     * in high two bytes, time in low two bytes allowing magnitude comparison).
66     *
67     * @param  integer  the current Unix timestamp
68     *
69     * @return integer  the current date in a four byte DOS format
70     *
71     * @access private
72     */
73    function unix2DosTime($unixtime = 0)
74    {
75        $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
76
77        if ($timearray['year'] < 1980) {
78            $timearray['year']    = 1980;
79            $timearray['mon']     = 1;
80            $timearray['mday']    = 1;
81            $timearray['hours']   = 0;
82            $timearray['minutes'] = 0;
83            $timearray['seconds'] = 0;
84        } // end if
85
86        return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
87                ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
88    } // end of the 'unix2DosTime()' method
89
90
91    /**
92     * Adds "file" to archive
93     *
94     * @param  string   file contents
95     * @param  string   name of the file in the archive (may contains the path)
96     * @param  integer  the current timestamp
97     *
98     * @access public
99     */
100    function addFile($data, $name, $time = 0)
101    {
102        $name     = str_replace('\\', '/', $name);
103
104        $dtime    = dechex($this->unix2DosTime($time));
105        $hexdtime = '\x' . $dtime[6] . $dtime[7]
106                  . '\x' . $dtime[4] . $dtime[5]
107                  . '\x' . $dtime[2] . $dtime[3]
108                  . '\x' . $dtime[0] . $dtime[1];
109        eval('$hexdtime = "' . $hexdtime . '";');
110
111        $fr   = "\x50\x4b\x03\x04";
112        $fr   .= "\x14\x00";            // ver needed to extract
113        $fr   .= "\x00\x00";            // gen purpose bit flag
114        $fr   .= "\x08\x00";            // compression method
115        $fr   .= $hexdtime;             // last mod time and date
116
117        // "local file header" segment
118        $unc_len = strlen($data);
119        $crc     = crc32($data);
120        $zdata   = gzcompress($data);
121        $zdata   = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
122        $c_len   = strlen($zdata);
123        $fr      .= pack('V', $crc);             // crc32
124        $fr      .= pack('V', $c_len);           // compressed filesize
125        $fr      .= pack('V', $unc_len);         // uncompressed filesize
126        $fr      .= pack('v', strlen($name));    // length of filename
127        $fr      .= pack('v', 0);                // extra field length
128        $fr      .= $name;
129
130        // "file data" segment
131        $fr .= $zdata;
132
133        // "data descriptor" segment (optional but necessary if archive is not
134        // served as file)
135        $fr .= pack('V', $crc);                 // crc32
136        $fr .= pack('V', $c_len);               // compressed filesize
137        $fr .= pack('V', $unc_len);             // uncompressed filesize
138
139        // add this entry to array
140        $this -> datasec[] = $fr;
141        $new_offset        = strlen(implode('', $this->datasec));
142
143        // now add to central directory record
144        $cdrec = "\x50\x4b\x01\x02";
145        $cdrec .= "\x00\x00";                // version made by
146        $cdrec .= "\x14\x00";                // version needed to extract
147        $cdrec .= "\x00\x00";                // gen purpose bit flag
148        $cdrec .= "\x08\x00";                // compression method
149        $cdrec .= $hexdtime;                 // last mod time & date
150        $cdrec .= pack('V', $crc);           // crc32
151        $cdrec .= pack('V', $c_len);         // compressed filesize
152        $cdrec .= pack('V', $unc_len);       // uncompressed filesize
153        $cdrec .= pack('v', strlen($name) ); // length of filename
154        $cdrec .= pack('v', 0 );             // extra field length
155        $cdrec .= pack('v', 0 );             // file comment length
156        $cdrec .= pack('v', 0 );             // disk number start
157        $cdrec .= pack('v', 0 );             // internal file attributes
158        $cdrec .= pack('V', 32 );            // external file attributes - 'archive' bit set
159
160        $cdrec .= pack('V', $this -> old_offset ); // relative offset of local header
161        $this -> old_offset = $new_offset;
162
163        $cdrec .= $name;
164
165        // optional extra field, file comment goes here
166        // save to central directory
167        $this -> ctrl_dir[] = $cdrec;
168    } // end of the 'addFile()' method
169
170
171    /**
172     * Dumps out file
173     *
174     * @return  string  the zipped file
175     *
176     * @access public
177     */
178    function file()
179    {
180        $data    = implode('', $this -> datasec);
181        $ctrldir = implode('', $this -> ctrl_dir);
182
183        return
184            $data .
185            $ctrldir .
186            $this -> eof_ctrl_dir .
187            pack('v', count($this -> ctrl_dir)) .  // total # of entries "on this disk"
188            pack('v', count($this -> ctrl_dir)) .  // total # of entries overall
189            pack('V', strlen($ctrldir)) .           // size of central dir
190            pack('V', strlen($data)) .              // offset to start of central dir
191            "\x00\x00";                             // .zip file comment length
192    } // end of the 'file()' method
193
194} // end of the 'zipfile' class
195
196?>
Note: See TracBrowser for help on using the repository browser.