Removed global variables with array counts in sqlparser.lib.php
[phpmyadmin.git] / libraries / zip.lib.php
blob443b173783553ff6a047dd5419a6b47339aa384d
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
5 * @package phpMyAdmin
6 */
8 /**
9 * Zip file creation class.
10 * Makes zip files.
12 * Based on :
14 * http://www.zend.com/codex.php?id=535&single=1
15 * By Eric Mueller <eric@themepark.com>
17 * http://www.zend.com/codex.php?id=470&single=1
18 * by Denis125 <webmaster@atlant.ru>
20 * a patch from Peter Listiak <mlady@users.sourceforge.net> for last modified
21 * date and time of the compressed file
23 * Official ZIP file format: http://www.pkware.com/appnote.txt
25 * @access public
26 * @package phpMyAdmin
28 class zipfile
30 /**
31 * Whether to echo zip as it's built or return as string from -> file
33 * @var boolean $doWrite
35 var $doWrite = false;
37 /**
38 * Array to store compressed data
40 * @var array $datasec
42 var $datasec = array();
44 /**
45 * Central directory
47 * @var array $ctrl_dir
49 var $ctrl_dir = array();
51 /**
52 * End of central directory record
54 * @var string $eof_ctrl_dir
56 var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
58 /**
59 * Last offset position
61 * @var integer $old_offset
63 var $old_offset = 0;
66 /**
67 * Sets member variable this -> doWrite to true
68 * - Should be called immediately after class instantiantion
69 * - If set to true, then ZIP archive are echo'ed to STDOUT as each
70 * file is added via this -> addfile(), and central directories are
71 * echoed to STDOUT on final call to this -> file(). Also,
72 * this -> file() returns an empty string so it is safe to issue a
73 * "echo $zipfile;" command
75 * @access public
77 function setDoWrite() {
78 $this -> doWrite = true;
79 } // end of the 'setDoWrite()' method
81 /**
82 * Converts an Unix timestamp to a four byte DOS date and time format (date
83 * in high two bytes, time in low two bytes allowing magnitude comparison).
85 * @param integer the current Unix timestamp
87 * @return integer the current date in a four byte DOS format
89 * @access private
91 function unix2DosTime($unixtime = 0) {
92 $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
94 if ($timearray['year'] < 1980) {
95 $timearray['year'] = 1980;
96 $timearray['mon'] = 1;
97 $timearray['mday'] = 1;
98 $timearray['hours'] = 0;
99 $timearray['minutes'] = 0;
100 $timearray['seconds'] = 0;
101 } // end if
103 return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
104 ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
105 } // end of the 'unix2DosTime()' method
109 * Adds "file" to archive
111 * @param string file contents
112 * @param string name of the file in the archive (may contains the path)
113 * @param integer the current timestamp
115 * @access public
117 function addFile($data, $name, $time = 0)
119 $name = str_replace('\\', '/', $name);
121 $dtime = substr( "00000000" . dechex($this->unix2DosTime($time)), -8);
122 $hexdtime = '\x' . $dtime[6] . $dtime[7]
123 . '\x' . $dtime[4] . $dtime[5]
124 . '\x' . $dtime[2] . $dtime[3]
125 . '\x' . $dtime[0] . $dtime[1];
126 eval('$hexdtime = "' . $hexdtime . '";');
128 $fr = "\x50\x4b\x03\x04";
129 $fr .= "\x14\x00"; // ver needed to extract
130 $fr .= "\x00\x00"; // gen purpose bit flag
131 $fr .= "\x08\x00"; // compression method
132 $fr .= $hexdtime; // last mod time and date
134 // "local file header" segment
135 $unc_len = strlen($data);
136 $crc = crc32($data);
137 $zdata = gzcompress($data);
138 $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
139 $c_len = strlen($zdata);
140 $fr .= pack('V', $crc); // crc32
141 $fr .= pack('V', $c_len); // compressed filesize
142 $fr .= pack('V', $unc_len); // uncompressed filesize
143 $fr .= pack('v', strlen($name)); // length of filename
144 $fr .= pack('v', 0); // extra field length
145 $fr .= $name;
147 // "file data" segment
148 $fr .= $zdata;
150 // "data descriptor" segment (optional but necessary if archive is not
151 // served as file)
152 // this seems not to be needed at all and causes
153 // problems in some cases (bug #1037737)
154 //$fr .= pack('V', $crc); // crc32
155 //$fr .= pack('V', $c_len); // compressed filesize
156 //$fr .= pack('V', $unc_len); // uncompressed filesize
158 // echo this entry on the fly, ...
159 if ( $this -> doWrite) {
160 echo $fr;
161 } else { // ... OR add this entry to array
162 $this -> datasec[] = $fr;
165 // now add to central directory record
166 $cdrec = "\x50\x4b\x01\x02";
167 $cdrec .= "\x00\x00"; // version made by
168 $cdrec .= "\x14\x00"; // version needed to extract
169 $cdrec .= "\x00\x00"; // gen purpose bit flag
170 $cdrec .= "\x08\x00"; // compression method
171 $cdrec .= $hexdtime; // last mod time & date
172 $cdrec .= pack('V', $crc); // crc32
173 $cdrec .= pack('V', $c_len); // compressed filesize
174 $cdrec .= pack('V', $unc_len); // uncompressed filesize
175 $cdrec .= pack('v', strlen($name)); // length of filename
176 $cdrec .= pack('v', 0); // extra field length
177 $cdrec .= pack('v', 0); // file comment length
178 $cdrec .= pack('v', 0); // disk number start
179 $cdrec .= pack('v', 0); // internal file attributes
180 $cdrec .= pack('V', 32); // external file attributes - 'archive' bit set
182 $cdrec .= pack('V', $this -> old_offset); // relative offset of local header
183 $this -> old_offset += strlen($fr);
185 $cdrec .= $name;
187 // optional extra field, file comment goes here
188 // save to central directory
189 $this -> ctrl_dir[] = $cdrec;
190 } // end of the 'addFile()' method
194 * Echo central dir if ->doWrite==true, else build string to return
196 * @return string if ->doWrite {empty string} else the ZIP file contents
198 * @access public
200 function file()
202 $ctrldir = implode('', $this -> ctrl_dir);
203 $header = $ctrldir .
204 $this -> eof_ctrl_dir .
205 pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk"
206 pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall
207 pack('V', strlen($ctrldir)) . // size of central dir
208 pack('V', strlen($data)) . // offset to start of central dir
209 "\x00\x00"; // .zip file comment length
211 if ( $this -> doWrite ) { // Send central directory & end ctrl dir to STDOUT
212 echo $header;
213 return ""; // Return empty string
214 } else { // Return entire ZIP archive as string
215 $data = implode('', $this -> datasec);
216 return $data . $header;
218 } // end of the 'file()' method
220 } // end of the 'zipfile' class