1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
5 * An open source application development framework for PHP 4.3.2 or newer
8 * @author ExpressionEngine Dev Team
9 * @copyright Copyright (c) 2008 - 2009, EllisLab, Inc.
10 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
16 // ------------------------------------------------------------------------
19 * Zip Compression Class
21 * This class is based on a library I found at Zend:
22 * http://www.zend.com/codex.php?id=696&single=1
24 * The original library is a little rough around the edges so I
25 * refactored it and added several additional methods -- Rick Ellis
27 * @package CodeIgniter
28 * @subpackage Libraries
29 * @category Encryption
30 * @author ExpressionEngine Dev Team
31 * @link http://codeigniter.com/user_guide/libraries/zip.html
43 log_message('debug', "Zip Compression Class Initialized");
46 // --------------------------------------------------------------------
51 * Lets you add a virtual directory into which you can place files.
54 * @param mixed the directory name. Can be string or array
57 function add_dir($directory)
59 foreach ((array)$directory as $dir)
61 if ( ! preg_match("|.+/$|", $dir))
66 $this->_add_dir($dir);
70 // --------------------------------------------------------------------
76 * @param string the directory name
79 function _add_dir($dir)
81 $dir = str_replace("\\", "/", $dir);
84 "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00"
85 .pack('V', 0) // crc32
86 .pack('V', 0) // compressed filesize
87 .pack('V', 0) // uncompressed filesize
88 .pack('v', strlen($dir)) // length of pathname
89 .pack('v', 0) // extra field length
91 // below is "data descriptor" segment
92 .pack('V', 0) // crc32
93 .pack('V', 0) // compressed filesize
94 .pack('V', 0); // uncompressed filesize
97 "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00"
99 .pack('V',0) // compressed filesize
100 .pack('V',0) // uncompressed filesize
101 .pack('v', strlen($dir)) // length of pathname
102 .pack('v', 0) // extra field length
103 .pack('v', 0) // file comment length
104 .pack('v', 0) // disk number start
105 .pack('v', 0) // internal file attributes
106 .pack('V', 16) // external file attributes - 'directory' bit set
107 .pack('V', $this->offset) // relative offset of local header
110 $this->offset = strlen($this->zipdata);
114 // --------------------------------------------------------------------
119 * Lets you add files to the archive. If the path is included
120 * in the filename it will be placed within a directory. Make
121 * sure you use add_dir() first to create the folder.
128 function add_data($filepath, $data = NULL)
130 if (is_array($filepath))
132 foreach ($filepath as $path => $data)
134 $this->_add_data($path, $data);
139 $this->_add_data($filepath, $data);
143 // --------------------------------------------------------------------
149 * @param string the file name/path
150 * @param string the data to be encoded
153 function _add_data($filepath, $data)
155 $filepath = str_replace("\\", "/", $filepath);
157 $uncompressed_size = strlen($data);
158 $crc32 = crc32($data);
160 $gzdata = gzcompress($data);
161 $gzdata = substr($gzdata, 2, -4);
162 $compressed_size = strlen($gzdata);
165 "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00\x00\x00\x00\x00"
167 .pack('V', $compressed_size)
168 .pack('V', $uncompressed_size)
169 .pack('v', strlen($filepath)) // length of filename
170 .pack('v', 0) // extra field length
172 .$gzdata; // "file data" segment
175 "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00\x00\x00\x00\x00"
177 .pack('V', $compressed_size)
178 .pack('V', $uncompressed_size)
179 .pack('v', strlen($filepath)) // length of filename
180 .pack('v', 0) // extra field length
181 .pack('v', 0) // file comment length
182 .pack('v', 0) // disk number start
183 .pack('v', 0) // internal file attributes
184 .pack('V', 32) // external file attributes - 'archive' bit set
185 .pack('V', $this->offset) // relative offset of local header
188 $this->offset = strlen($this->zipdata);
193 // --------------------------------------------------------------------
196 * Read the contents of a file and add it to the zip
201 function read_file($path, $preserve_filepath = FALSE)
203 if ( ! file_exists($path))
208 if (FALSE !== ($data = file_get_contents($path)))
210 $name = str_replace("\\", "/", $path);
212 if ($preserve_filepath === FALSE)
214 $name = preg_replace("|.*/(.+)|", "\\1", $name);
217 $this->add_data($name, $data);
223 // ------------------------------------------------------------------------
226 * Read a directory and add it to the zip.
228 * This function recursively reads a folder and everything it contains (including
229 * sub-folders) and creates a zip based on it. Whatever directory structure
230 * is in the original file path will be recreated in the zip file.
233 * @param string path to source
236 function read_dir($path)
238 if ($fp = @opendir($path))
240 while (FALSE !== ($file = readdir($fp)))
242 if (@is_dir($path.$file) && substr($file, 0, 1) != '.')
244 $this->read_dir($path.$file."/");
246 elseif (substr($file, 0, 1) != ".")
248 if (FALSE !== ($data = file_get_contents($path.$file)))
250 $this->add_data(str_replace("\\", "/", $path).$file, $data);
258 // --------------------------------------------------------------------
264 * @return binary string
268 // Is there any data to return?
269 if ($this->entries == 0)
274 $zip_data = $this->zipdata;
275 $zip_data .= $this->directory."\x50\x4b\x05\x06\x00\x00\x00\x00";
276 $zip_data .= pack('v', $this->entries); // total # of entries "on this disk"
277 $zip_data .= pack('v', $this->entries); // total # of entries overall
278 $zip_data .= pack('V', strlen($this->directory)); // size of central dir
279 $zip_data .= pack('V', strlen($this->zipdata)); // offset to start of central dir
280 $zip_data .= "\x00\x00"; // .zip file comment length
285 // --------------------------------------------------------------------
288 * Write File to the specified directory
290 * Lets you write a file
293 * @param string the file name
296 function archive($filepath)
298 if ( ! ($fp = @fopen($filepath, FOPEN_WRITE_CREATE_DESTRUCTIVE)))
304 fwrite($fp, $this->get_zip());
311 // --------------------------------------------------------------------
317 * @param string the file name
318 * @param string the data to be encoded
321 function download($filename = 'backup.zip')
323 if ( ! preg_match("|.+?\.zip$|", $filename))
328 $zip_content =& $this->get_zip();
330 $CI =& get_instance();
331 $CI->load->helper('download');
333 force_download($filename, $zip_content);
336 // --------------------------------------------------------------------
341 * Lets you clear current zip data. Useful if you need to create
342 * multiple zips with different data.
347 function clear_data()
350 $this->directory = '';
358 /* End of file Zip.php */
359 /* Location: ./system/libraries/Zip.php */