Translated using Weblate (Albanian)
[phpmyadmin.git] / libraries / ZipFile.php
blob652d0eafd4011c94f035d75bb76a9c1ea242a627
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Zip file creation
6 * @package PhpMyAdmin
7 */
8 namespace PMA\libraries;
10 if (!defined('PHPMYADMIN')) {
11 exit;
14 /**
15 * Zip file creation class.
16 * Makes zip files.
18 * @access public
19 * @package PhpMyAdmin
20 * @see Official ZIP file format: https://www.pkware.com/support/zip-app-note
22 class ZipFile
24 /**
25 * Whether to echo zip as it's built or return as string from -> file
27 * @var boolean $doWrite
29 var $doWrite = false;
30 /**
31 * Array to store compressed data
33 * @var array $datasec
35 var $datasec = array();
36 /**
37 * Central directory
39 * @var array $ctrl_dir
41 var $ctrl_dir = array();
42 /**
43 * End of central directory record
45 * @var string $eof_ctrl_dir
47 var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
48 /**
49 * Last offset position
51 * @var integer $old_offset
53 var $old_offset = 0;
55 /**
56 * Sets member variable this -> doWrite to true
57 * - Should be called immediately after class instantiation
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 * @return void
68 function setDoWrite()
70 $this->doWrite = true;
71 } // end of the 'setDoWrite()' method
73 /**
74 * Converts an Unix timestamp to a four byte DOS date and time format (date
75 * in high two bytes, time in low two bytes allowing magnitude comparison).
77 * @param integer $unixtime the current Unix timestamp
79 * @return integer the current date in a four byte DOS format
81 * @access private
83 function unix2DosTime($unixtime = 0)
85 $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
87 if ($timearray['year'] < 1980) {
88 $timearray['year'] = 1980;
89 $timearray['mon'] = 1;
90 $timearray['mday'] = 1;
91 $timearray['hours'] = 0;
92 $timearray['minutes'] = 0;
93 $timearray['seconds'] = 0;
94 } // end if
96 return (($timearray['year'] - 1980) << 25)
97 | ($timearray['mon'] << 21)
98 | ($timearray['mday'] << 16)
99 | ($timearray['hours'] << 11)
100 | ($timearray['minutes'] << 5)
101 | ($timearray['seconds'] >> 1);
102 } // end of the 'unix2DosTime()' method
105 * Adds "file" to archive
107 * @param string $data file contents
108 * @param string $name name of the file in the archive (may contains the path)
109 * @param integer $time the current timestamp
111 * @access public
113 * @return void
115 function addFile($data, $name, $time = 0)
117 $name = str_replace('\\', '/', $name);
119 $hexdtime = pack('V', $this->unix2DosTime($time));
121 $fr = "\x50\x4b\x03\x04";
122 $fr .= "\x14\x00"; // ver needed to extract
123 $fr .= "\x00\x00"; // gen purpose bit flag
124 $fr .= "\x08\x00"; // compression method
125 $fr .= $hexdtime; // last mod time and date
127 // "local file header" segment
128 $unc_len = strlen($data);
129 $crc = crc32($data);
130 $zdata = gzcompress($data);
131 $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
132 $c_len = strlen($zdata);
133 $fr .= pack('V', $crc); // crc32
134 $fr .= pack('V', $c_len); // compressed filesize
135 $fr .= pack('V', $unc_len); // uncompressed filesize
136 $fr .= pack('v', strlen($name)); // length of filename
137 $fr .= pack('v', 0); // extra field length
138 $fr .= $name;
140 // "file data" segment
141 $fr .= $zdata;
143 // echo this entry on the fly, ...
144 if ($this->doWrite) {
145 echo $fr;
146 } else { // ... OR add this entry to array
147 $this->datasec[] = $fr;
150 // now add to central directory record
151 $cdrec = "\x50\x4b\x01\x02";
152 $cdrec .= "\x00\x00"; // version made by
153 $cdrec .= "\x14\x00"; // version needed to extract
154 $cdrec .= "\x00\x00"; // gen purpose bit flag
155 $cdrec .= "\x08\x00"; // compression method
156 $cdrec .= $hexdtime; // last mod time & date
157 $cdrec .= pack('V', $crc); // crc32
158 $cdrec .= pack('V', $c_len); // compressed filesize
159 $cdrec .= pack('V', $unc_len); // uncompressed filesize
160 $cdrec .= pack('v', strlen($name)); // length of filename
161 $cdrec .= pack('v', 0); // extra field length
162 $cdrec .= pack('v', 0); // file comment length
163 $cdrec .= pack('v', 0); // disk number start
164 $cdrec .= pack('v', 0); // internal file attributes
165 $cdrec .= pack('V', 32); // external file attributes
166 // - 'archive' bit set
168 $cdrec .= pack('V', $this->old_offset); // relative offset of local header
169 $this->old_offset += strlen($fr);
171 $cdrec .= $name;
173 // optional extra field, file comment goes here
174 // save to central directory
175 $this->ctrl_dir[] = $cdrec;
176 } // end of the 'addFile()' method
179 * Echo central dir if ->doWrite==true, else build string to return
181 * @return string if ->doWrite {empty string} else the ZIP file contents
183 * @access public
185 function file()
187 $ctrldir = implode('', $this->ctrl_dir);
188 $header = $ctrldir .
189 $this->eof_ctrl_dir .
190 pack('v', sizeof($this->ctrl_dir)) . //total #of entries "on this disk"
191 pack('v', sizeof($this->ctrl_dir)) . //total #of entries overall
192 pack('V', strlen($ctrldir)) . //size of central dir
193 pack('V', $this->old_offset) . //offset to start of central dir
194 "\x00\x00"; //.zip file comment length
196 if ($this->doWrite) { // Send central directory & end ctrl dir to STDOUT
197 echo $header;
199 return ""; // Return empty string
200 } else { // Return entire ZIP archive as string
201 $data = implode('', $this->datasec);
203 return $data . $header;
205 } // end of the 'file()' method
206 } // end of the 'PMA\libraries\ZipFile' class