Adhere to PEAR coding standards
[phpmyadmin/crack.git] / libraries / zip.lib.php
blob9208e937268cf6baf34575356a5a4246e50a0ac2
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 * @see Official ZIP file format: http://www.pkware.com/support/zip-app-note
14 * @access public
15 * @package phpMyAdmin
17 class zipfile
19 /**
20 * Whether to echo zip as it's built or return as string from -> file
22 * @var boolean $doWrite
24 var $doWrite = false;
26 /**
27 * Array to store compressed data
29 * @var array $datasec
31 var $datasec = array();
33 /**
34 * Central directory
36 * @var array $ctrl_dir
38 var $ctrl_dir = array();
40 /**
41 * End of central directory record
43 * @var string $eof_ctrl_dir
45 var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
47 /**
48 * Last offset position
50 * @var integer $old_offset
52 var $old_offset = 0;
55 /**
56 * Sets member variable this -> doWrite to true
57 * - Should be called immediately after class instantiantion
58 * - If set to true, then ZIP archive are echo'ed to STDOUT as each
59 * file is added via this -> addfile(), and central directories are
60 * echoed to STDOUT on final call to this -> file(). Also,
61 * this -> file() returns an empty string so it is safe to issue a
62 * "echo $zipfile;" command
64 * @access public
66 function setDoWrite() {
67 $this -> doWrite = true;
68 } // end of the 'setDoWrite()' method
70 /**
71 * Converts an Unix timestamp to a four byte DOS date and time format (date
72 * in high two bytes, time in low two bytes allowing magnitude comparison).
74 * @param integer the current Unix timestamp
76 * @return integer the current date in a four byte DOS format
78 * @access private
80 function unix2DosTime($unixtime = 0) {
81 $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
83 if ($timearray['year'] < 1980) {
84 $timearray['year'] = 1980;
85 $timearray['mon'] = 1;
86 $timearray['mday'] = 1;
87 $timearray['hours'] = 0;
88 $timearray['minutes'] = 0;
89 $timearray['seconds'] = 0;
90 } // end if
92 return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
93 ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
94 } // end of the 'unix2DosTime()' method
97 /**
98 * Adds "file" to archive
100 * @param string file contents
101 * @param string name of the file in the archive (may contains the path)
102 * @param integer the current timestamp
104 * @access public
106 function addFile($data, $name, $time = 0)
108 $name = str_replace('\\', '/', $name);
110 $dtime = substr( "00000000" . dechex($this->unix2DosTime($time)), -8);
111 $hexdtime = '\x' . $dtime[6] . $dtime[7]
112 . '\x' . $dtime[4] . $dtime[5]
113 . '\x' . $dtime[2] . $dtime[3]
114 . '\x' . $dtime[0] . $dtime[1];
115 eval('$hexdtime = "' . $hexdtime . '";');
117 $fr = "\x50\x4b\x03\x04";
118 $fr .= "\x14\x00"; // ver needed to extract
119 $fr .= "\x00\x00"; // gen purpose bit flag
120 $fr .= "\x08\x00"; // compression method
121 $fr .= $hexdtime; // last mod time and date
123 // "local file header" segment
124 $unc_len = strlen($data);
125 $crc = crc32($data);
126 $zdata = gzcompress($data);
127 $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
128 $c_len = strlen($zdata);
129 $fr .= pack('V', $crc); // crc32
130 $fr .= pack('V', $c_len); // compressed filesize
131 $fr .= pack('V', $unc_len); // uncompressed filesize
132 $fr .= pack('v', strlen($name)); // length of filename
133 $fr .= pack('v', 0); // extra field length
134 $fr .= $name;
136 // "file data" segment
137 $fr .= $zdata;
139 // echo this entry on the fly, ...
140 if ( $this -> doWrite) {
141 echo $fr;
142 } else { // ... OR add this entry to array
143 $this -> datasec[] = $fr;
146 // now add to central directory record
147 $cdrec = "\x50\x4b\x01\x02";
148 $cdrec .= "\x00\x00"; // version made by
149 $cdrec .= "\x14\x00"; // version needed to extract
150 $cdrec .= "\x00\x00"; // gen purpose bit flag
151 $cdrec .= "\x08\x00"; // compression method
152 $cdrec .= $hexdtime; // last mod time & date
153 $cdrec .= pack('V', $crc); // crc32
154 $cdrec .= pack('V', $c_len); // compressed filesize
155 $cdrec .= pack('V', $unc_len); // uncompressed filesize
156 $cdrec .= pack('v', strlen($name)); // length of filename
157 $cdrec .= pack('v', 0); // extra field length
158 $cdrec .= pack('v', 0); // file comment length
159 $cdrec .= pack('v', 0); // disk number start
160 $cdrec .= pack('v', 0); // internal file attributes
161 $cdrec .= pack('V', 32); // external file attributes - 'archive' bit set
163 $cdrec .= pack('V', $this -> old_offset); // relative offset of local header
164 $this -> old_offset += strlen($fr);
166 $cdrec .= $name;
168 // optional extra field, file comment goes here
169 // save to central directory
170 $this -> ctrl_dir[] = $cdrec;
171 } // end of the 'addFile()' method
175 * Echo central dir if ->doWrite==true, else build string to return
177 * @return string if ->doWrite {empty string} else the ZIP file contents
179 * @access public
181 function file()
183 $ctrldir = implode('', $this -> ctrl_dir);
184 $header = $ctrldir .
185 $this -> eof_ctrl_dir .
186 pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk"
187 pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall
188 pack('V', strlen($ctrldir)) . // size of central dir
189 pack('V', $this -> old_offset) . // offset to start of central dir
190 "\x00\x00"; // .zip file comment length
192 if ( $this -> doWrite ) { // Send central directory & end ctrl dir to STDOUT
193 echo $header;
194 return ""; // Return empty string
195 } else { // Return entire ZIP archive as string
196 $data = implode('', $this -> datasec);
197 return $data . $header;
199 } // end of the 'file()' method
201 } // end of the 'zipfile' class