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