2
/* $Id: zip.lib.php 6461 2004-11-03 13:56:52Z garvinhicking $ */
3
// vim: expandtab sw=4 ts=4 sts=4:
7
* Zip file creation class.
12
* http://www.zend.com/codex.php?id=535&single=1
13
* By Eric Mueller <eric@themepark.com>
15
* http://www.zend.com/codex.php?id=470&single=1
16
* by Denis125 <webmaster@atlant.ru>
18
* a patch from Peter Listiak <mlady@users.sourceforge.net> for last modified
19
* date and time of the compressed file
21
* Official ZIP file format: http://www.pkware.com/appnote.txt
28
* Array to store compressed data
32
var $datasec = array();
37
* @var array $ctrl_dir
39
var $ctrl_dir = array();
42
* End of central directory record
44
* @var string $eof_ctrl_dir
46
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
49
* Last offset position
51
* @var integer $old_offset
57
* Converts an Unix timestamp to a four byte DOS date and time format (date
58
* in high two bytes, time in low two bytes allowing magnitude comparison).
60
* @param integer the current Unix timestamp
62
* @return integer the current date in a four byte DOS format
66
function unix2DosTime($unixtime = 0) {
67
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
69
if ($timearray['year'] < 1980) {
70
$timearray['year'] = 1980;
71
$timearray['mon'] = 1;
72
$timearray['mday'] = 1;
73
$timearray['hours'] = 0;
74
$timearray['minutes'] = 0;
75
$timearray['seconds'] = 0;
78
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
79
($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
80
} // end of the 'unix2DosTime()' method
84
* Adds "file" to archive
86
* @param string file contents
87
* @param string name of the file in the archive (may contains the path)
88
* @param integer the current timestamp
92
function addFile($data, $name, $time = 0)
94
$name = str_replace('\\', '/', $name);
96
$dtime = dechex($this->unix2DosTime($time));
97
$hexdtime = '\x' . $dtime[6] . $dtime[7]
98
. '\x' . $dtime[4] . $dtime[5]
99
. '\x' . $dtime[2] . $dtime[3]
100
. '\x' . $dtime[0] . $dtime[1];
101
eval('$hexdtime = "' . $hexdtime . '";');
103
$fr = "\x50\x4b\x03\x04";
104
$fr .= "\x14\x00"; // ver needed to extract
105
$fr .= "\x00\x00"; // gen purpose bit flag
106
$fr .= "\x08\x00"; // compression method
107
$fr .= $hexdtime; // last mod time and date
109
// "local file header" segment
110
$unc_len = strlen($data);
112
$zdata = gzcompress($data);
113
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
114
$c_len = strlen($zdata);
115
$fr .= pack('V', $crc); // crc32
116
$fr .= pack('V', $c_len); // compressed filesize
117
$fr .= pack('V', $unc_len); // uncompressed filesize
118
$fr .= pack('v', strlen($name)); // length of filename
119
$fr .= pack('v', 0); // extra field length
122
// "file data" segment
125
// "data descriptor" segment (optional but necessary if archive is not
127
// nijel(2004-10-19): this seems not to be needed at all and causes
128
// problems in some cases (bug #1037737)
129
//$fr .= pack('V', $crc); // crc32
130
//$fr .= pack('V', $c_len); // compressed filesize
131
//$fr .= pack('V', $unc_len); // uncompressed filesize
133
// add this entry to array
134
$this -> datasec[] = $fr;
136
// now add to central directory record
137
$cdrec = "\x50\x4b\x01\x02";
138
$cdrec .= "\x00\x00"; // version made by
139
$cdrec .= "\x14\x00"; // version needed to extract
140
$cdrec .= "\x00\x00"; // gen purpose bit flag
141
$cdrec .= "\x08\x00"; // compression method
142
$cdrec .= $hexdtime; // last mod time & date
143
$cdrec .= pack('V', $crc); // crc32
144
$cdrec .= pack('V', $c_len); // compressed filesize
145
$cdrec .= pack('V', $unc_len); // uncompressed filesize
146
$cdrec .= pack('v', strlen($name) ); // length of filename
147
$cdrec .= pack('v', 0 ); // extra field length
148
$cdrec .= pack('v', 0 ); // file comment length
149
$cdrec .= pack('v', 0 ); // disk number start
150
$cdrec .= pack('v', 0 ); // internal file attributes
151
$cdrec .= pack('V', 32 ); // external file attributes - 'archive' bit set
153
$cdrec .= pack('V', $this -> old_offset ); // relative offset of local header
154
$this -> old_offset += strlen($fr);
158
// optional extra field, file comment goes here
159
// save to central directory
160
$this -> ctrl_dir[] = $cdrec;
161
} // end of the 'addFile()' method
167
* @return string the zipped file
173
$data = implode('', $this -> datasec);
174
$ctrldir = implode('', $this -> ctrl_dir);
179
$this -> eof_ctrl_dir .
180
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk"
181
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall
182
pack('V', strlen($ctrldir)) . // size of central dir
183
pack('V', strlen($data)) . // offset to start of central dir
184
"\x00\x00"; // .zip file comment length
185
} // end of the 'file()' method
187
} // end of the 'zipfile' class