Subversion Repositories Applications.bazar

Rev

Details | Last modification | View Log | RSS feed

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