Upgraded phpmyadmin to 4.0.4 (All Languages) - No modifications yet
[openemr.git] / phpmyadmin / libraries / zip.lib.php
blob6ecea2f58130935c2691207b21978c2edd77e81b
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Zip file creation
6 * @package PhpMyAdmin
7 */
8 if (! defined('PHPMYADMIN')) {
9 exit;
12 /**
13 * Zip file creation class.
14 * Makes zip files.
16 * @access public
17 * @package PhpMyAdmin
18 * @see Official ZIP file format: http://www.pkware.com/support/zip-app-note
20 class ZipFile
22 /**
23 * Whether to echo zip as it's built or return as string from -> file
25 * @var boolean $doWrite
27 var $doWrite = false;
29 /**
30 * Array to store compressed data
32 * @var array $datasec
34 var $datasec = array();
36 /**
37 * Central directory
39 * @var array $ctrl_dir
41 var $ctrl_dir = array();
43 /**
44 * End of central directory record
46 * @var string $eof_ctrl_dir
48 var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
50 /**
51 * Last offset position
53 * @var integer $old_offset
55 var $old_offset = 0;
58 /**
59 * Sets member variable this -> doWrite to true
60 * - Should be called immediately after class instantiantion
61 * - If set to true, then ZIP archive are echo'ed to STDOUT as each
62 * file is added via this -> addfile(), and central directories are
63 * echoed to STDOUT on final call to this -> file(). Also,
64 * this -> file() returns an empty string so it is safe to issue a
65 * "echo $zipfile;" command
67 * @access public
69 * @return void
71 function setDoWrite()
73 $this -> doWrite = true;
74 } // end of the 'setDoWrite()' method
76 /**
77 * Converts an Unix timestamp to a four byte DOS date and time format (date
78 * in high two bytes, time in low two bytes allowing magnitude comparison).
80 * @param integer $unixtime the current Unix timestamp
82 * @return integer the current date in a four byte DOS format
84 * @access private
86 function unix2DosTime($unixtime = 0)
88 $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
90 if ($timearray['year'] < 1980) {
91 $timearray['year'] = 1980;
92 $timearray['mon'] = 1;
93 $timearray['mday'] = 1;
94 $timearray['hours'] = 0;
95 $timearray['minutes'] = 0;
96 $timearray['seconds'] = 0;
97 } // end if
99 return (($timearray['year'] - 1980) << 25)
100 | ($timearray['mon'] << 21)
101 | ($timearray['mday'] << 16)
102 | ($timearray['hours'] << 11)
103 | ($timearray['minutes'] << 5)
104 | ($timearray['seconds'] >> 1);
105 } // end of the 'unix2DosTime()' method
109 * Adds "file" to archive
111 * @param string $data file contents
112 * @param string $name name of the file in the archive (may contains the path)
113 * @param integer $time the current timestamp
115 * @access public
117 * @return void
119 function addFile($data, $name, $time = 0)
121 $name = str_replace('\\', '/', $name);
123 $dtime = substr("00000000" . dechex($this->unix2DosTime($time)), -8);
124 $hexdtime = '\x' . $dtime[6] . $dtime[7]
125 . '\x' . $dtime[4] . $dtime[5]
126 . '\x' . $dtime[2] . $dtime[3]
127 . '\x' . $dtime[0] . $dtime[1];
128 eval('$hexdtime = "' . $hexdtime . '";');
130 $fr = "\x50\x4b\x03\x04";
131 $fr .= "\x14\x00"; // ver needed to extract
132 $fr .= "\x00\x00"; // gen purpose bit flag
133 $fr .= "\x08\x00"; // compression method
134 $fr .= $hexdtime; // last mod time and date
136 // "local file header" segment
137 $unc_len = strlen($data);
138 $crc = crc32($data);
139 $zdata = gzcompress($data);
140 $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
141 $c_len = strlen($zdata);
142 $fr .= pack('V', $crc); // crc32
143 $fr .= pack('V', $c_len); // compressed filesize
144 $fr .= pack('V', $unc_len); // uncompressed filesize
145 $fr .= pack('v', strlen($name)); // length of filename
146 $fr .= pack('v', 0); // extra field length
147 $fr .= $name;
149 // "file data" segment
150 $fr .= $zdata;
152 // echo this entry on the fly, ...
153 if ( $this -> doWrite) {
154 echo $fr;
155 } else { // ... OR add this entry to array
156 $this -> datasec[] = $fr;
159 // now add to central directory record
160 $cdrec = "\x50\x4b\x01\x02";
161 $cdrec .= "\x00\x00"; // version made by
162 $cdrec .= "\x14\x00"; // version needed to extract
163 $cdrec .= "\x00\x00"; // gen purpose bit flag
164 $cdrec .= "\x08\x00"; // compression method
165 $cdrec .= $hexdtime; // last mod time & date
166 $cdrec .= pack('V', $crc); // crc32
167 $cdrec .= pack('V', $c_len); // compressed filesize
168 $cdrec .= pack('V', $unc_len); // uncompressed filesize
169 $cdrec .= pack('v', strlen($name)); // length of filename
170 $cdrec .= pack('v', 0); // extra field length
171 $cdrec .= pack('v', 0); // file comment length
172 $cdrec .= pack('v', 0); // disk number start
173 $cdrec .= pack('v', 0); // internal file attributes
174 $cdrec .= pack('V', 32); // external file attributes
175 // - 'archive' bit set
177 $cdrec .= pack('V', $this -> old_offset); // relative offset of local header
178 $this -> old_offset += strlen($fr);
180 $cdrec .= $name;
182 // optional extra field, file comment goes here
183 // save to central directory
184 $this -> ctrl_dir[] = $cdrec;
185 } // end of the 'addFile()' method
189 * Echo central dir if ->doWrite==true, else build string to return
191 * @return string if ->doWrite {empty string} else the ZIP file contents
193 * @access public
195 function file()
197 $ctrldir = implode('', $this -> ctrl_dir);
198 $header = $ctrldir .
199 $this -> eof_ctrl_dir .
200 pack('v', sizeof($this -> ctrl_dir)) . //total #of entries "on this disk"
201 pack('v', sizeof($this -> ctrl_dir)) . //total #of entries overall
202 pack('V', strlen($ctrldir)) . //size of central dir
203 pack('V', $this -> old_offset) . //offset to start of central dir
204 "\x00\x00"; //.zip file comment length
206 if ( $this -> doWrite ) { // Send central directory & end ctrl dir to STDOUT
207 echo $header;
208 return ""; // Return empty string
209 } else { // Return entire ZIP archive as string
210 $data = implode('', $this -> datasec);
211 return $data . $header;
213 } // end of the 'file()' method
215 } // end of the 'ZipFile' class