These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /* vim: set ts=4 sw=4: */ |
||
3 | // +----------------------------------------------------------------------+ |
||
4 | // | PHP Version 4 | |
||
5 | // +----------------------------------------------------------------------+ |
||
6 | // | Copyright (c) 1997-2003 The PHP Group | |
||
7 | // +----------------------------------------------------------------------+ |
||
8 | // | This library is free software; you can redistribute it and/or | |
||
9 | // | modify it under the terms of the GNU Lesser General Public | |
||
10 | // | License as published by the Free Software Foundation; either | |
||
11 | // | version 2.1 of the License, or (at your option) any later version. | |
||
12 | // | | |
||
13 | // | This library is distributed in the hope that it will be useful, | |
||
14 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
||
15 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
||
16 | // | Lesser General Public License for more details. | |
||
17 | // | | |
||
18 | // | You should have received a copy of the GNU Lesser General Public | |
||
19 | // | License along with this library; if not, write to the Free Software | |
||
20 | // | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
||
21 | // | MA 02110-1301 USA | |
||
22 | // +----------------------------------------------------------------------+ |
||
23 | // | Author: Vincent Blavet <[email protected]> | |
||
24 | // +----------------------------------------------------------------------+ |
||
25 | // |
||
26 | // $Id: Zip.php,v 1.2 2005/11/21 06:51:57 vblavet Exp $ |
||
27 | |||
28 | // require_once 'PEAR.php'; // GIJ |
||
29 | |||
30 | // ----- Constants |
||
31 | define('ARCHIVE_ZIP_READ_BLOCK_SIZE', 2048); |
||
32 | |||
33 | // ----- File list separator |
||
34 | define('ARCHIVE_ZIP_SEPARATOR', ','); |
||
35 | |||
36 | // ----- Optional static temporary directory |
||
37 | // By default temporary files are generated in the script current |
||
38 | // path. |
||
39 | // If defined : |
||
40 | // - MUST BE terminated by a '/'. |
||
41 | // - MUST be a valid, already created directory |
||
42 | // Samples : |
||
43 | // define( 'ARCHIVE_ZIP_TEMPORARY_DIR', '/temp/' ); |
||
44 | // define( 'ARCHIVE_ZIP_TEMPORARY_DIR', 'C:/Temp/' ); |
||
45 | define('ARCHIVE_ZIP_TEMPORARY_DIR', ''); |
||
46 | |||
47 | // ----- Error codes |
||
48 | define('ARCHIVE_ZIP_ERR_NO_ERROR', 0); |
||
49 | define('ARCHIVE_ZIP_ERR_WRITE_OPEN_FAIL', -1); |
||
50 | define('ARCHIVE_ZIP_ERR_READ_OPEN_FAIL', -2); |
||
51 | define('ARCHIVE_ZIP_ERR_INVALID_PARAMETER', -3); |
||
52 | define('ARCHIVE_ZIP_ERR_MISSING_FILE', -4); |
||
53 | define('ARCHIVE_ZIP_ERR_FILENAME_TOO_LONG', -5); |
||
54 | define('ARCHIVE_ZIP_ERR_INVALID_ZIP', -6); |
||
55 | define('ARCHIVE_ZIP_ERR_BAD_EXTRACTED_FILE', -7); |
||
56 | define('ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL', -8); |
||
57 | define('ARCHIVE_ZIP_ERR_BAD_EXTENSION', -9); |
||
58 | define('ARCHIVE_ZIP_ERR_BAD_FORMAT', -10); |
||
59 | define('ARCHIVE_ZIP_ERR_DELETE_FILE_FAIL', -11); |
||
60 | define('ARCHIVE_ZIP_ERR_RENAME_FILE_FAIL', -12); |
||
61 | define('ARCHIVE_ZIP_ERR_BAD_CHECKSUM', -13); |
||
62 | define('ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP', -14); |
||
63 | define('ARCHIVE_ZIP_ERR_MISSING_OPTION_VALUE', -15); |
||
64 | define('ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE', -16); |
||
65 | |||
66 | // ----- Warning codes |
||
67 | define('ARCHIVE_ZIP_WARN_NO_WARNING', 0); |
||
68 | define('ARCHIVE_ZIP_WARN_FILE_EXIST', 1); |
||
69 | |||
70 | // ----- Methods parameters |
||
71 | define('ARCHIVE_ZIP_PARAM_PATH', 'path'); |
||
72 | define('ARCHIVE_ZIP_PARAM_ADD_PATH', 'add_path'); |
||
73 | define('ARCHIVE_ZIP_PARAM_REMOVE_PATH', 'remove_path'); |
||
74 | define('ARCHIVE_ZIP_PARAM_REMOVE_ALL_PATH', 'remove_all_path'); |
||
75 | define('ARCHIVE_ZIP_PARAM_SET_CHMOD', 'set_chmod'); |
||
76 | define('ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING', 'extract_as_string'); |
||
77 | define('ARCHIVE_ZIP_PARAM_NO_COMPRESSION', 'no_compression'); |
||
78 | define('ARCHIVE_ZIP_PARAM_BY_NAME', 'by_name'); |
||
79 | define('ARCHIVE_ZIP_PARAM_BY_INDEX', 'by_index'); |
||
80 | define('ARCHIVE_ZIP_PARAM_BY_EREG', 'by_ereg'); |
||
81 | define('ARCHIVE_ZIP_PARAM_BY_PREG', 'by_preg'); |
||
82 | |||
83 | define('ARCHIVE_ZIP_PARAM_PRE_EXTRACT', 'callback_pre_extract'); |
||
84 | define('ARCHIVE_ZIP_PARAM_POST_EXTRACT', 'callback_post_extract'); |
||
85 | define('ARCHIVE_ZIP_PARAM_PRE_ADD', 'callback_pre_add'); |
||
86 | define('ARCHIVE_ZIP_PARAM_POST_ADD', 'callback_post_add'); |
||
87 | |||
88 | |||
89 | |||
90 | /** |
||
91 | * Class for manipulating zip archive files |
||
92 | * |
||
93 | * A class which provided common methods to manipulate ZIP formatted |
||
94 | * archive files. |
||
95 | * It provides creation, extraction, deletion and add features. |
||
96 | * |
||
97 | * @author Vincent Blavet <[email protected]> |
||
98 | * @version $Revision: 1.2 $ |
||
99 | * @package Archive_Zip |
||
100 | * @category Archive |
||
101 | */ |
||
102 | class Archive_Zip |
||
103 | { |
||
104 | /** |
||
105 | * The filename of the zip archive. |
||
106 | * |
||
107 | * @var string Name of the Zip file |
||
108 | */ |
||
109 | public $_zipname=''; |
||
110 | |||
111 | /** |
||
112 | * File descriptor of the opened Zip file. |
||
113 | * |
||
114 | * @var int Internal zip file descriptor |
||
115 | */ |
||
116 | public $_zip_fd=0; |
||
117 | |||
118 | /** |
||
119 | * @var int last error code |
||
120 | */ |
||
121 | public $_error_code=1; |
||
122 | |||
123 | /** |
||
124 | * @var string Last error description |
||
125 | */ |
||
126 | public $_error_string=''; |
||
127 | |||
128 | // {{{ constructor |
||
129 | /** |
||
130 | * Archive_Zip Class constructor. This flavour of the constructor only |
||
131 | * declare a new Archive_Zip object, identifying it by the name of the |
||
132 | * zip file. |
||
133 | * |
||
134 | * @param string $p_zipname The name of the zip archive to create |
||
135 | * @access public |
||
136 | */ |
||
137 | //HACK by domifara |
||
138 | // function Archive_Zip($p_zipname) |
||
139 | public function __construct($p_zipname) |
||
140 | { |
||
141 | |||
142 | // ----- Check the zlib |
||
143 | /* if (!extension_loaded('zlib')) { |
||
144 | PEAR::loadExtension('zlib'); |
||
145 | }*/ // GIJ |
||
146 | if (!extension_loaded('zlib')) { |
||
147 | die("The extension 'zlib' couldn't be found.\n". 'Please make sure your version of PHP was built ' . |
||
148 | "with 'zlib' support.\n"); |
||
149 | return false; |
||
150 | } |
||
151 | |||
152 | // ----- Set the attributes |
||
153 | $this->_zipname = $p_zipname; |
||
154 | $this->_zip_fd = 0; |
||
155 | |||
156 | return; |
||
157 | } |
||
158 | // }}} |
||
159 | |||
160 | // {{{ create() |
||
161 | /** |
||
162 | * This method creates a Zip Archive with the filename set with |
||
163 | * the constructor. |
||
164 | * The files and directories indicated in $p_filelist |
||
165 | * are added in the archive. |
||
166 | * When a directory is in the list, the directory and its content is added |
||
167 | * in the archive. |
||
168 | * The methods takes a variable list of parameters in $p_params. |
||
169 | * The supported parameters for this method are : |
||
170 | * 'add_path' : Add a path to the archived files. |
||
171 | * 'remove_path' : Remove the specified 'root' path of the archived files. |
||
172 | * 'remove_all_path' : Remove all the path of the archived files. |
||
173 | * 'no_compression' : The archived files will not be compressed. |
||
174 | * |
||
175 | * @access public |
||
176 | * @param mixed $p_filelist The list of the files or folders to add. |
||
177 | * It can be a string with filenames separated |
||
178 | * by a comma, or an array of filenames. |
||
179 | * @param mixed $p_params An array of variable parameters and values. |
||
180 | * @return mixed An array of file description on success, |
||
181 | * an error code on error |
||
182 | */ |
||
183 | public function create($p_filelist, $p_params=0) |
||
184 | { |
||
185 | $this->_errorReset(); |
||
186 | |||
187 | // ----- Set default values |
||
188 | if ($p_params === 0) { |
||
189 | $p_params = array(); |
||
190 | } |
||
191 | if ($this->_check_parameters($p_params, |
||
192 | array('no_compression' => false, |
||
193 | 'add_path' => '', |
||
194 | 'remove_path' => '', |
||
195 | 'remove_all_path' => false)) != 1) { |
||
196 | return 0; |
||
197 | } |
||
198 | |||
199 | // ----- Look if the $p_filelist is really an array |
||
200 | $p_result_list = array(); |
||
201 | View Code Duplication | if (is_array($p_filelist)) { |
|
202 | $v_result = $this->_create($p_filelist, $p_result_list, $p_params); |
||
203 | } |
||
204 | |||
205 | // ----- Look if the $p_filelist is a string |
||
206 | elseif (is_string($p_filelist)) { |
||
207 | // ----- Create a list with the elements from the string |
||
208 | $v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist); |
||
209 | |||
210 | $v_result = $this->_create($v_list, $p_result_list, $p_params); |
||
211 | } |
||
212 | |||
213 | // ----- Invalid variable |
||
214 | else { |
||
215 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, |
||
216 | 'Invalid variable type p_filelist'); |
||
217 | $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; |
||
218 | } |
||
219 | |||
220 | if ($v_result != 1) { |
||
221 | return 0; |
||
222 | } |
||
223 | |||
224 | return $p_result_list; |
||
225 | } |
||
226 | // }}} |
||
227 | |||
228 | // {{{ add() |
||
229 | /** |
||
230 | * This method add files or directory in an existing Zip Archive. |
||
231 | * If the Zip Archive does not exist it is created. |
||
232 | * The files and directories to add are indicated in $p_filelist. |
||
233 | * When a directory is in the list, the directory and its content is added |
||
234 | * in the archive. |
||
235 | * The methods takes a variable list of parameters in $p_params. |
||
236 | * The supported parameters for this method are : |
||
237 | * 'add_path' : Add a path to the archived files. |
||
238 | * 'remove_path' : Remove the specified 'root' path of the archived files. |
||
239 | * 'remove_all_path' : Remove all the path of the archived files. |
||
240 | * 'no_compression' : The archived files will not be compressed. |
||
241 | * 'callback_pre_add' : A callback function that will be called before |
||
242 | * each entry archiving. |
||
243 | * 'callback_post_add' : A callback function that will be called after |
||
244 | * each entry archiving. |
||
245 | * |
||
246 | * @access public |
||
247 | * @param mixed $p_filelist The list of the files or folders to add. |
||
248 | * It can be a string with filenames separated |
||
249 | * by a comma, or an array of filenames. |
||
250 | * @param mixed $p_params An array of variable parameters and values. |
||
251 | * @return mixed An array of file description on success, |
||
252 | * 0 on an unrecoverable failure, an error code is logged. |
||
253 | */ |
||
254 | public function add($p_filelist, $p_params=0) |
||
255 | { |
||
256 | $this->_errorReset(); |
||
257 | |||
258 | // ----- Set default values |
||
259 | if ($p_params === 0) { |
||
260 | $p_params = array(); |
||
261 | } |
||
262 | if ($this->_check_parameters($p_params, |
||
263 | array('no_compression' => false, |
||
264 | 'add_path' => '', |
||
265 | 'remove_path' => '', |
||
266 | 'remove_all_path' => false, |
||
267 | 'callback_pre_add' => '', |
||
268 | 'callback_post_add' => '')) != 1) { |
||
269 | return 0; |
||
270 | } |
||
271 | |||
272 | // ----- Look if the $p_filelist is really an array |
||
273 | $p_result_list = array(); |
||
274 | View Code Duplication | if (is_array($p_filelist)) { |
|
275 | // ----- Call the create fct |
||
276 | $v_result = $this->_add($p_filelist, $p_result_list, $p_params); |
||
277 | } |
||
278 | |||
279 | // ----- Look if the $p_filelist is a string |
||
280 | elseif (is_string($p_filelist)) { |
||
281 | // ----- Create a list with the elements from the string |
||
282 | $v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist); |
||
283 | |||
284 | // ----- Call the create fct |
||
285 | $v_result = $this->_add($v_list, $p_result_list, $p_params); |
||
286 | } |
||
287 | |||
288 | // ----- Invalid variable |
||
289 | else { |
||
290 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'add() : Invalid variable type p_filelist'); |
||
291 | $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; |
||
292 | } |
||
293 | |||
294 | if ($v_result != 1) { |
||
295 | return 0; |
||
296 | } |
||
297 | |||
298 | // ----- Return the result list |
||
299 | return $p_result_list; |
||
300 | } |
||
301 | // }}} |
||
302 | |||
303 | // {{{ listContent() |
||
304 | /** |
||
305 | * This method gives the names and properties of the files and directories |
||
306 | * which are present in the zip archive. |
||
307 | * The properties of each entries in the list are : |
||
308 | * filename : Name of the file. |
||
309 | * For create() or add() it's the filename given by the user. |
||
310 | * For an extract() it's the filename of the extracted file. |
||
311 | * stored_filename : Name of the file / directory stored in the archive. |
||
312 | * size : Size of the stored file. |
||
313 | * compressed_size : Size of the file's data compressed in the archive |
||
314 | * (without the zip headers overhead) |
||
315 | * mtime : Last known modification date of the file (UNIX timestamp) |
||
316 | * comment : Comment associated with the file |
||
317 | * folder : true | false (indicates if the entry is a folder) |
||
318 | * index : index of the file in the archive (-1 when not available) |
||
319 | * status : status of the action on the entry (depending of the action) : |
||
320 | * Values are : |
||
321 | * ok : OK ! |
||
322 | * filtered : the file/dir was not extracted (filtered by user) |
||
323 | * already_a_directory : the file can't be extracted because a |
||
324 | * directory with the same name already |
||
325 | * exists |
||
326 | * write_protected : the file can't be extracted because a file |
||
327 | * with the same name already exists and is |
||
328 | * write protected |
||
329 | * newer_exist : the file was not extracted because a newer |
||
330 | * file already exists |
||
331 | * path_creation_fail : the file is not extracted because the |
||
332 | * folder does not exists and can't be |
||
333 | * created |
||
334 | * write_error : the file was not extracted because there was a |
||
335 | * error while writing the file |
||
336 | * read_error : the file was not extracted because there was a |
||
337 | * error while reading the file |
||
338 | * invalid_header : the file was not extracted because of an |
||
339 | * archive format error (bad file header) |
||
340 | * Note that each time a method can continue operating when there |
||
341 | * is an error on a single file, the error is only logged in the file status. |
||
342 | * |
||
343 | * @access public |
||
344 | * @return mixed An array of file description on success, |
||
345 | * 0 on an unrecoverable failure, an error code is logged. |
||
346 | */ |
||
347 | public function listContent() |
||
348 | { |
||
349 | $this->_errorReset(); |
||
350 | |||
351 | // ----- Check archive |
||
352 | if (!$this->_checkFormat()) { |
||
353 | return 0; |
||
354 | } |
||
355 | |||
356 | $v_list = array(); |
||
357 | if ($this->_list($v_list) != 1) { |
||
358 | unset($v_list); |
||
359 | return 0; |
||
360 | } |
||
361 | |||
362 | return $v_list; |
||
363 | } |
||
364 | // }}} |
||
365 | |||
366 | // {{{ extract() |
||
367 | /** |
||
368 | * This method extract the files and folders which are in the zip archive. |
||
369 | * It can extract all the archive or a part of the archive by using filter |
||
370 | * feature (extract by name, by index, by ereg, by preg). The extraction |
||
371 | * can occur in the current path or an other path. |
||
372 | * All the advanced features are activated by the use of variable |
||
373 | * parameters. |
||
374 | * The return value is an array of entry descriptions which gives |
||
375 | * information on extracted files (See listContent()). |
||
376 | * The method may return a success value (an array) even if some files |
||
377 | * are not correctly extracted (see the file status in listContent()). |
||
378 | * The supported variable parameters for this method are : |
||
379 | * 'add_path' : Path where the files and directories are to be extracted |
||
380 | * 'remove_path' : First part ('root' part) of the memorized path |
||
381 | * (if similar) to remove while extracting. |
||
382 | * 'remove_all_path' : Remove all the memorized path while extracting. |
||
383 | * 'extract_as_string' : |
||
384 | * 'set_chmod' : After the extraction of the file the indicated mode |
||
385 | * will be set. |
||
386 | * 'by_name' : It can be a string with file/dir names separated by ',', |
||
387 | * or an array of file/dir names to extract from the archive. |
||
388 | * 'by_index' : A string with range of indexes separated by ',', |
||
389 | * (sample "1,3-5,12"). |
||
390 | * 'by_ereg' : A regular expression (ereg) that must match the extracted |
||
391 | * filename. |
||
392 | * 'by_preg' : A regular expression (preg) that must match the extracted |
||
393 | * filename. |
||
394 | * 'callback_pre_extract' : A callback function that will be called before |
||
395 | * each entry extraction. |
||
396 | * 'callback_post_extract' : A callback function that will be called after |
||
397 | * each entry extraction. |
||
398 | * |
||
399 | * @access public |
||
400 | * @param mixed $p_params An array of variable parameters and values. |
||
401 | * @return mixed An array of file description on success, |
||
402 | * 0 on an unrecoverable failure, an error code is logged. |
||
403 | */ |
||
404 | public function extract($p_params=0) |
||
405 | { |
||
406 | $this->_errorReset(); |
||
407 | |||
408 | // ----- Check archive |
||
409 | if (!$this->_checkFormat()) { |
||
410 | return 0; |
||
411 | } |
||
412 | |||
413 | // ----- Set default values |
||
414 | if ($p_params === 0) { |
||
415 | $p_params = array(); |
||
416 | } |
||
417 | if ($this->_check_parameters($p_params, |
||
418 | array('extract_as_string' => false, |
||
419 | 'add_path' => '', |
||
420 | 'remove_path' => '', |
||
421 | 'remove_all_path' => false, |
||
422 | 'callback_pre_extract' => '', |
||
423 | 'callback_post_extract' => '', |
||
424 | 'set_chmod' => 0, |
||
425 | 'by_name' => '', |
||
426 | 'by_index' => '', |
||
427 | 'by_ereg' => '', |
||
428 | 'by_preg' => '')) != 1) { |
||
429 | return 0; |
||
430 | } |
||
431 | |||
432 | // ----- Call the extracting fct |
||
433 | $v_list = array(); |
||
434 | if ($this->_extractByRule($v_list, $p_params) != 1) { |
||
435 | unset($v_list); |
||
436 | return 0; |
||
437 | } |
||
438 | |||
439 | return $v_list; |
||
440 | } |
||
441 | // }}} |
||
442 | |||
443 | |||
444 | // {{{ delete() |
||
445 | /** |
||
446 | * This methods delete archive entries in the zip archive. |
||
447 | * Notice that at least one filtering rule (set by the variable parameter |
||
448 | * list) must be set. |
||
449 | * Also notice that if you delete a folder entry, only the folder entry |
||
450 | * is deleted, not all the files bellonging to this folder. |
||
451 | * The supported variable parameters for this method are : |
||
452 | * 'by_name' : It can be a string with file/dir names separated by ',', |
||
453 | * or an array of file/dir names to delete from the archive. |
||
454 | * 'by_index' : A string with range of indexes separated by ',', |
||
455 | * (sample "1,3-5,12"). |
||
456 | * 'by_ereg' : A regular expression (ereg) that must match the extracted |
||
457 | * filename. |
||
458 | * 'by_preg' : A regular expression (preg) that must match the extracted |
||
459 | * filename. |
||
460 | * |
||
461 | * @access public |
||
462 | * @param mixed $p_params An array of variable parameters and values. |
||
463 | * @return mixed An array of file description on success, |
||
464 | * 0 on an unrecoverable failure, an error code is logged. |
||
465 | */ |
||
466 | public function delete($p_params) |
||
467 | { |
||
468 | $this->_errorReset(); |
||
469 | |||
470 | // ----- Check archive |
||
471 | if (!$this->_checkFormat()) { |
||
472 | return 0; |
||
473 | } |
||
474 | |||
475 | // ----- Set default values |
||
476 | if ($this->_check_parameters($p_params, |
||
477 | array('by_name' => '', |
||
478 | 'by_index' => '', |
||
479 | 'by_ereg' => '', |
||
480 | 'by_preg' => '')) != 1) { |
||
481 | return 0; |
||
482 | } |
||
483 | |||
484 | // ----- Check that at least one rule is set |
||
485 | if (($p_params['by_name'] == '') |
||
486 | && ($p_params['by_index'] == '') |
||
487 | && ($p_params['by_ereg'] == '') |
||
488 | && ($p_params['by_preg'] == '')) { |
||
489 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, |
||
490 | 'At least one filtering rule must' |
||
491 | .' be set as parameter'); |
||
492 | return 0; |
||
493 | } |
||
494 | |||
495 | // ----- Call the delete fct |
||
496 | $v_list = array(); |
||
497 | if ($this->_deleteByRule($v_list, $p_params) != 1) { |
||
498 | unset($v_list); |
||
499 | return 0; |
||
500 | } |
||
501 | |||
502 | return $v_list; |
||
503 | } |
||
504 | // }}} |
||
505 | |||
506 | // {{{ properties() |
||
507 | /** |
||
508 | * This method gives the global properties of the archive. |
||
509 | * The properties are : |
||
510 | * nb : Number of files in the archive |
||
511 | * comment : Comment associated with the archive file |
||
512 | * status : not_exist, ok |
||
513 | * |
||
514 | * @access public |
||
515 | * @param mixed $p_params {Description} |
||
516 | * @return mixed An array with the global properties or 0 on error. |
||
517 | */ |
||
518 | public function properties() |
||
519 | { |
||
520 | $this->_errorReset(); |
||
521 | |||
522 | // ----- Check archive |
||
523 | if (!$this->_checkFormat()) { |
||
524 | return 0; |
||
525 | } |
||
526 | |||
527 | // ----- Default properties |
||
528 | $v_prop = array(); |
||
529 | $v_prop['comment'] = ''; |
||
530 | $v_prop['nb'] = 0; |
||
531 | $v_prop['status'] = 'not_exist'; |
||
532 | |||
533 | // ----- Look if file exists |
||
534 | if (@is_file($this->_zipname)) { |
||
535 | // ----- Open the zip file |
||
536 | if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0) { |
||
537 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, |
||
538 | 'Unable to open archive \''.$this->_zipname |
||
539 | .'\' in binary read mode'); |
||
540 | return 0; |
||
541 | } |
||
542 | |||
543 | // ----- Read the central directory informations |
||
544 | $v_central_dir = array(); |
||
545 | if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
||
546 | return 0; |
||
547 | } |
||
548 | |||
549 | $this->_closeFd(); |
||
550 | |||
551 | // ----- Set the user attributes |
||
552 | $v_prop['comment'] = $v_central_dir['comment']; |
||
553 | $v_prop['nb'] = $v_central_dir['entries']; |
||
554 | $v_prop['status'] = 'ok'; |
||
555 | } |
||
556 | |||
557 | return $v_prop; |
||
558 | } |
||
559 | // }}} |
||
560 | |||
561 | |||
562 | // {{{ duplicate() |
||
563 | /** |
||
564 | * This method creates an archive by copying the content of an other one. |
||
565 | * If the archive already exist, it is replaced by the new one without |
||
566 | * any warning. |
||
567 | * |
||
568 | * @access public |
||
569 | * @param mixed $p_archive It can be a valid Archive_Zip object or |
||
570 | * the filename of a valid zip archive. |
||
571 | * @return integer 1 on success, 0 on failure. |
||
572 | */ |
||
573 | public function duplicate($p_archive) |
||
574 | { |
||
575 | $this->_errorReset(); |
||
576 | |||
577 | // ----- Look if the $p_archive is a Archive_Zip object |
||
578 | if (is_object($p_archive) |
||
579 | && (strtolower(get_class($p_archive)) == 'archive_zip')) { |
||
580 | $v_result = $this->_duplicate($p_archive->_zipname); |
||
581 | } |
||
582 | |||
583 | // ----- Look if the $p_archive is a string (so a filename) |
||
584 | elseif (is_string($p_archive)) { |
||
585 | // ----- Check that $p_archive is a valid zip file |
||
586 | // TBC : Should also check the archive format |
||
587 | if (!is_file($p_archive)) { |
||
588 | $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, |
||
589 | "No file with filename '".$p_archive."'"); |
||
590 | $v_result = ARCHIVE_ZIP_ERR_MISSING_FILE; |
||
591 | } else { |
||
592 | $v_result = $this->_duplicate($p_archive); |
||
593 | } |
||
594 | } |
||
595 | |||
596 | // ----- Invalid variable |
||
597 | else { |
||
598 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Invalid variable type p_archive_to_add'); |
||
599 | $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; |
||
600 | } |
||
601 | |||
602 | return $v_result; |
||
603 | } |
||
604 | // }}} |
||
605 | |||
606 | // {{{ merge() |
||
607 | /** |
||
608 | * This method merge a valid zip archive at the end of the |
||
609 | * archive identified by the Archive_Zip object. |
||
610 | * If the archive ($this) does not exist, the merge becomes a duplicate. |
||
611 | * If the archive to add does not exist, the merge is a success. |
||
612 | * |
||
613 | * @access public |
||
614 | * @param mixed $p_archive_to_add It can be a valid Archive_Zip object or |
||
615 | * the filename of a valid zip archive. |
||
616 | * @return integer 1 on success, 0 on failure. |
||
617 | */ |
||
618 | public function merge($p_archive_to_add) |
||
619 | { |
||
620 | $v_result = 1; |
||
621 | $this->_errorReset(); |
||
622 | |||
623 | // ----- Check archive |
||
624 | if (!$this->_checkFormat()) { |
||
625 | return 0; |
||
626 | } |
||
627 | |||
628 | // ----- Look if the $p_archive_to_add is a Archive_Zip object |
||
629 | if (is_object($p_archive_to_add) |
||
630 | && (strtolower(get_class($p_archive_to_add)) == 'archive_zip')) { |
||
631 | $v_result = $this->_merge($p_archive_to_add); |
||
632 | } |
||
633 | |||
634 | // ----- Look if the $p_archive_to_add is a string (so a filename) |
||
635 | elseif (is_string($p_archive_to_add)) { |
||
636 | // ----- Create a temporary archive |
||
637 | $v_object_archive = new Archive_Zip($p_archive_to_add); |
||
638 | |||
639 | // ----- Merge the archive |
||
640 | $v_result = $this->_merge($v_object_archive); |
||
641 | } |
||
642 | |||
643 | // ----- Invalid variable |
||
644 | else { |
||
645 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Invalid variable type p_archive_to_add'); |
||
646 | $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; |
||
647 | } |
||
648 | |||
649 | return $v_result; |
||
650 | } |
||
651 | // }}} |
||
652 | |||
653 | // {{{ errorCode() |
||
654 | /** |
||
655 | * Method that gives the lastest error code. |
||
656 | * |
||
657 | * @access public |
||
658 | * @return integer The error code value. |
||
659 | */ |
||
660 | public function errorCode() |
||
661 | { |
||
662 | return $this->_error_code; |
||
663 | } |
||
664 | // }}} |
||
665 | |||
666 | // {{{ errorName() |
||
667 | /** |
||
668 | * This method gives the latest error code name. |
||
669 | * |
||
670 | * @access public |
||
671 | * @param boolean $p_with_code If true, gives the name and the int value. |
||
672 | * @return string The error name. |
||
673 | */ |
||
674 | public function errorName($p_with_code=false) |
||
675 | { |
||
676 | $v_const_list = get_defined_constants(); |
||
677 | |||
678 | // ----- Extract error constants from all const. |
||
679 | for (reset($v_const_list); |
||
680 | list($v_key, $v_value) = each($v_const_list);) { |
||
681 | if (substr($v_key, 0, strlen('ARCHIVE_ZIP_ERR_')) |
||
682 | =='ARCHIVE_ZIP_ERR_') { |
||
683 | $v_error_list[$v_key] = $v_value; |
||
684 | } |
||
685 | } |
||
686 | |||
687 | // ----- Search the name form the code value |
||
688 | $v_key=array_search($this->_error_code, $v_error_list, true); |
||
689 | if ($v_key!=false) { |
||
690 | $v_value = $v_key; |
||
691 | } else { |
||
692 | $v_value = 'NoName'; |
||
693 | } |
||
694 | |||
695 | if ($p_with_code) { |
||
696 | return($v_value.' ('.$this->_error_code.')'); |
||
697 | } else { |
||
698 | return $v_value; |
||
699 | } |
||
700 | } |
||
701 | // }}} |
||
702 | |||
703 | // {{{ errorInfo() |
||
704 | /** |
||
705 | * This method returns the description associated with the latest error. |
||
706 | * |
||
707 | * @access public |
||
708 | * @param boolean $p_full If set to true gives the description with the |
||
709 | * error code, the name and the description. |
||
710 | * If set to false gives only the description |
||
711 | * and the error code. |
||
712 | * @return string The error description. |
||
713 | */ |
||
714 | public function errorInfo($p_full=false) |
||
715 | { |
||
716 | if ($p_full) { |
||
717 | return($this->errorName(true) . ' : ' . $this->_error_string); |
||
718 | } else { |
||
719 | return($this->_error_string . ' [code ' . $this->_error_code . ']'); |
||
720 | } |
||
721 | } |
||
722 | // }}} |
||
723 | |||
724 | |||
725 | // ----------------------------------------------------------------------------- |
||
726 | // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** |
||
727 | // ***** ***** |
||
728 | // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** |
||
729 | // ----------------------------------------------------------------------------- |
||
730 | |||
731 | // --------------------------------------------------------------------------- |
||
732 | // Function : _checkFormat() |
||
733 | // Description : |
||
734 | // This method check that the archive exists and is a valid zip archive. |
||
735 | // Several level of check exists. (futur) |
||
736 | // Parameters : |
||
737 | // $p_level : Level of check. Default 0. |
||
738 | // 0 : Check the first bytes (magic codes) (default value)) |
||
739 | // 1 : 0 + Check the central directory (futur) |
||
740 | // 2 : 1 + Check each file header (futur) |
||
741 | // Return Values : |
||
742 | // true on success, |
||
743 | // false on error, the error code is set. |
||
744 | // --------------------------------------------------------------------------- |
||
745 | /** |
||
746 | * Archive_Zip::_checkFormat() |
||
747 | * |
||
748 | * { Description } |
||
749 | * |
||
750 | * @param integer $p_level |
||
751 | */ |
||
752 | public function _checkFormat($p_level=0) |
||
753 | { |
||
754 | $v_result = true; |
||
755 | |||
756 | // ----- Reset the error handler |
||
757 | $this->_errorReset(); |
||
758 | |||
759 | // ----- Look if the file exits |
||
760 | if (!is_file($this->_zipname)) { |
||
761 | // ----- Error log |
||
762 | $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, |
||
763 | "Missing archive file '".$this->_zipname."'"); |
||
764 | return false; |
||
765 | } |
||
766 | |||
767 | // ----- Check that the file is readeable |
||
768 | if (!is_readable($this->_zipname)) { |
||
769 | // ----- Error log |
||
770 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, |
||
771 | "Unable to read archive '".$this->_zipname."'"); |
||
772 | return false; |
||
773 | } |
||
774 | |||
775 | // ----- Check the magic code |
||
776 | // TBC |
||
777 | |||
778 | // ----- Check the central header |
||
779 | // TBC |
||
780 | |||
781 | // ----- Check each file header |
||
782 | // TBC |
||
783 | |||
784 | // ----- Return |
||
785 | return $v_result; |
||
786 | } |
||
787 | // --------------------------------------------------------------------------- |
||
788 | |||
789 | // --------------------------------------------------------------------------- |
||
790 | // Function : _create() |
||
791 | // Description : |
||
792 | // Parameters : |
||
793 | // Return Values : |
||
794 | // --------------------------------------------------------------------------- |
||
795 | /** |
||
796 | * Archive_Zip::_create() |
||
797 | * |
||
798 | * { Description } |
||
799 | * |
||
800 | */ |
||
801 | public function _create($p_list, &$p_result_list, &$p_params) |
||
802 | { |
||
803 | $v_result=1; |
||
804 | $v_list_detail = array(); |
||
805 | |||
806 | $p_add_dir = $p_params['add_path']; |
||
807 | $p_remove_dir = $p_params['remove_path']; |
||
808 | $p_remove_all_dir = $p_params['remove_all_path']; |
||
809 | |||
810 | // ----- Open the file in write mode |
||
811 | if (($v_result = $this->_openFd('wb')) != 1) { |
||
812 | // ----- Return |
||
813 | return $v_result; |
||
814 | } |
||
815 | |||
816 | // ----- Add the list of files |
||
817 | $v_result = $this->_addList($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params); |
||
818 | |||
819 | // ----- Close |
||
820 | $this->_closeFd(); |
||
821 | |||
822 | // ----- Return |
||
823 | return $v_result; |
||
824 | } |
||
825 | // --------------------------------------------------------------------------- |
||
826 | |||
827 | // --------------------------------------------------------------------------- |
||
828 | // Function : _add() |
||
829 | // Description : |
||
830 | // Parameters : |
||
831 | // Return Values : |
||
832 | // --------------------------------------------------------------------------- |
||
833 | /** |
||
834 | * Archive_Zip::_add() |
||
835 | * |
||
836 | * { Description } |
||
837 | * |
||
838 | */ |
||
839 | public function _add($p_list, &$p_result_list, &$p_params) |
||
840 | { |
||
841 | $v_result=1; |
||
842 | $v_list_detail = array(); |
||
843 | |||
844 | $p_add_dir = $p_params['add_path']; |
||
845 | $p_remove_dir = $p_params['remove_path']; |
||
846 | $p_remove_all_dir = $p_params['remove_all_path']; |
||
847 | |||
848 | // ----- Look if the archive exists or is empty and need to be created |
||
849 | if ((!is_file($this->_zipname)) || (filesize($this->_zipname) == 0)) { |
||
850 | $v_result = $this->_create($p_list, $p_result_list, $p_params); |
||
851 | return $v_result; |
||
852 | } |
||
853 | |||
854 | // ----- Open the zip file |
||
855 | if (($v_result=$this->_openFd('rb')) != 1) { |
||
856 | return $v_result; |
||
857 | } |
||
858 | |||
859 | // ----- Read the central directory informations |
||
860 | $v_central_dir = array(); |
||
861 | if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
||
862 | $this->_closeFd(); |
||
863 | return $v_result; |
||
864 | } |
||
865 | |||
866 | // ----- Go to beginning of File |
||
867 | @rewind($this->_zip_fd); |
||
868 | |||
869 | // ----- Creates a temporay file |
||
870 | $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-').'.tmp'; |
||
871 | |||
872 | // ----- Open the temporary file in write mode |
||
873 | View Code Duplication | if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) { |
|
874 | $this->_closeFd(); |
||
875 | |||
876 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, |
||
877 | 'Unable to open temporary file \'' |
||
878 | .$v_zip_temp_name.'\' in binary write mode'); |
||
879 | return Archive_Zip::errorCode(); |
||
880 | } |
||
881 | |||
882 | // ----- Copy the files from the archive to the temporary file |
||
883 | // TBC : Here I should better append the file and go back to erase the |
||
884 | // central dir |
||
885 | $v_size = $v_central_dir['offset']; |
||
886 | while ($v_size != 0) { |
||
887 | $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
888 | ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
889 | $v_buffer = fread($this->_zip_fd, $v_read_size); |
||
890 | @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
||
891 | $v_size -= $v_read_size; |
||
892 | } |
||
893 | |||
894 | // ----- Swap the file descriptor |
||
895 | // Here is a trick : I swap the temporary fd with the zip fd, in order to |
||
896 | // use the following methods on the temporary fil and not the real archive |
||
897 | $v_swap = $this->_zip_fd; |
||
898 | $this->_zip_fd = $v_zip_temp_fd; |
||
899 | $v_zip_temp_fd = $v_swap; |
||
900 | |||
901 | // ----- Add the files |
||
902 | $v_header_list = array(); |
||
903 | if (($v_result = $this->_addFileList($p_list, $v_header_list, |
||
904 | $p_add_dir, $p_remove_dir, |
||
905 | $p_remove_all_dir, $p_params)) != 1) { |
||
906 | fclose($v_zip_temp_fd); |
||
907 | $this->_closeFd(); |
||
908 | @unlink($v_zip_temp_name); |
||
909 | |||
910 | // ----- Return |
||
911 | return $v_result; |
||
912 | } |
||
913 | |||
914 | // ----- Store the offset of the central dir |
||
915 | $v_offset = @ftell($this->_zip_fd); |
||
916 | |||
917 | // ----- Copy the block of file headers from the old archive |
||
918 | $v_size = $v_central_dir['size']; |
||
919 | View Code Duplication | while ($v_size != 0) { |
|
920 | $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
921 | ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
922 | $v_buffer = @fread($v_zip_temp_fd, $v_read_size); |
||
923 | @fwrite($this->_zip_fd, $v_buffer, $v_read_size); |
||
924 | $v_size -= $v_read_size; |
||
925 | } |
||
926 | |||
927 | // ----- Create the Central Dir files header |
||
928 | for ($i=0, $v_count=0; $i < count($v_header_list); $i++) { |
||
929 | // ----- Create the file header |
||
930 | if ($v_header_list[$i]['status'] == 'ok') { |
||
931 | if (($v_result=$this->_writeCentralFileHeader($v_header_list[$i]))!=1) { |
||
932 | fclose($v_zip_temp_fd); |
||
933 | $this->_closeFd(); |
||
934 | @unlink($v_zip_temp_name); |
||
935 | |||
936 | // ----- Return |
||
937 | return $v_result; |
||
938 | } |
||
939 | $v_count++; |
||
940 | } |
||
941 | |||
942 | // ----- Transform the header to a 'usable' info |
||
943 | $this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); |
||
944 | } |
||
945 | |||
946 | // ----- Zip file comment |
||
947 | $v_comment = ''; |
||
948 | |||
949 | // ----- Calculate the size of the central header |
||
950 | $v_size = @ftell($this->_zip_fd)-$v_offset; |
||
951 | |||
952 | // ----- Create the central dir footer |
||
953 | if (($v_result = $this->_writeCentralHeader($v_count |
||
954 | +$v_central_dir['entries'], |
||
955 | $v_size, $v_offset, |
||
956 | $v_comment)) != 1) { |
||
957 | // ----- Reset the file list |
||
958 | unset($v_header_list); |
||
959 | |||
960 | // ----- Return |
||
961 | return $v_result; |
||
962 | } |
||
963 | |||
964 | // ----- Swap back the file descriptor |
||
965 | $v_swap = $this->_zip_fd; |
||
966 | $this->_zip_fd = $v_zip_temp_fd; |
||
967 | $v_zip_temp_fd = $v_swap; |
||
968 | |||
969 | // ----- Close |
||
970 | $this->_closeFd(); |
||
971 | |||
972 | // ----- Close the temporary file |
||
973 | @fclose($v_zip_temp_fd); |
||
974 | |||
975 | // ----- Delete the zip file |
||
976 | // TBC : I should test the result ... |
||
977 | @unlink($this->_zipname); |
||
978 | |||
979 | // ----- Rename the temporary file |
||
980 | // TBC : I should test the result ... |
||
981 | //@rename($v_zip_temp_name, $this->_zipname); |
||
982 | $this->_tool_Rename($v_zip_temp_name, $this->_zipname); |
||
983 | |||
984 | // ----- Return |
||
985 | return $v_result; |
||
986 | } |
||
987 | // --------------------------------------------------------------------------- |
||
988 | |||
989 | // --------------------------------------------------------------------------- |
||
990 | // Function : _openFd() |
||
991 | // Description : |
||
992 | // Parameters : |
||
993 | // --------------------------------------------------------------------------- |
||
994 | /** |
||
995 | * Archive_Zip::_openFd() |
||
996 | * |
||
997 | * { Description } |
||
998 | * |
||
999 | */ |
||
1000 | public function _openFd($p_mode) |
||
1001 | { |
||
1002 | $v_result=1; |
||
1003 | |||
1004 | // ----- Look if already open |
||
1005 | if ($this->_zip_fd != 0) { |
||
1006 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, |
||
1007 | 'Zip file \''.$this->_zipname.'\' already open'); |
||
1008 | return Archive_Zip::errorCode(); |
||
1009 | } |
||
1010 | |||
1011 | // ----- Open the zip file |
||
1012 | View Code Duplication | if (($this->_zip_fd = @fopen($this->_zipname, $p_mode)) == 0) { |
|
1013 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, |
||
1014 | 'Unable to open archive \''.$this->_zipname |
||
1015 | .'\' in '.$p_mode.' mode'); |
||
1016 | return Archive_Zip::errorCode(); |
||
1017 | } |
||
1018 | |||
1019 | // ----- Return |
||
1020 | return $v_result; |
||
1021 | } |
||
1022 | // --------------------------------------------------------------------------- |
||
1023 | |||
1024 | // --------------------------------------------------------------------------- |
||
1025 | // Function : _closeFd() |
||
1026 | // Description : |
||
1027 | // Parameters : |
||
1028 | // --------------------------------------------------------------------------- |
||
1029 | /** |
||
1030 | * Archive_Zip::_closeFd() |
||
1031 | * |
||
1032 | * { Description } |
||
1033 | * |
||
1034 | */ |
||
1035 | public function _closeFd() |
||
1036 | { |
||
1037 | $v_result=1; |
||
1038 | |||
1039 | if ($this->_zip_fd != 0) { |
||
1040 | @fclose($this->_zip_fd); |
||
1041 | } |
||
1042 | $this->_zip_fd = 0; |
||
1043 | |||
1044 | // ----- Return |
||
1045 | return $v_result; |
||
1046 | } |
||
1047 | // --------------------------------------------------------------------------- |
||
1048 | |||
1049 | // --------------------------------------------------------------------------- |
||
1050 | // Function : _addList() |
||
1051 | // Description : |
||
1052 | // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is |
||
1053 | // different from the real path of the file. This is usefull if you want to have PclTar |
||
1054 | // running in any directory, and memorize relative path from an other directory. |
||
1055 | // Parameters : |
||
1056 | // $p_list : An array containing the file or directory names to add in the tar |
||
1057 | // $p_result_list : list of added files with their properties (specially the status field) |
||
1058 | // $p_add_dir : Path to add in the filename path archived |
||
1059 | // $p_remove_dir : Path to remove in the filename path archived |
||
1060 | // Return Values : |
||
1061 | // --------------------------------------------------------------------------- |
||
1062 | /** |
||
1063 | * Archive_Zip::_addList() |
||
1064 | * |
||
1065 | * { Description } |
||
1066 | * |
||
1067 | */ |
||
1068 | public function _addList($p_list, &$p_result_list, |
||
1069 | $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params) |
||
1070 | { |
||
1071 | $v_result=1; |
||
1072 | |||
1073 | // ----- Add the files |
||
1074 | $v_header_list = array(); |
||
1075 | if (($v_result = $this->_addFileList($p_list, $v_header_list, |
||
1076 | $p_add_dir, $p_remove_dir, |
||
1077 | $p_remove_all_dir, $p_params)) != 1) { |
||
1078 | return $v_result; |
||
1079 | } |
||
1080 | |||
1081 | // ----- Store the offset of the central dir |
||
1082 | $v_offset = @ftell($this->_zip_fd); |
||
1083 | |||
1084 | // ----- Create the Central Dir files header |
||
1085 | for ($i=0, $v_count=0; $i < count($v_header_list); $i++) { |
||
1086 | // ----- Create the file header |
||
1087 | if ($v_header_list[$i]['status'] == 'ok') { |
||
1088 | if (($v_result = $this->_writeCentralFileHeader($v_header_list[$i])) != 1) { |
||
1089 | return $v_result; |
||
1090 | } |
||
1091 | $v_count++; |
||
1092 | } |
||
1093 | |||
1094 | // ----- Transform the header to a 'usable' info |
||
1095 | $this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); |
||
1096 | } |
||
1097 | |||
1098 | // ----- Zip file comment |
||
1099 | $v_comment = ''; |
||
1100 | |||
1101 | // ----- Calculate the size of the central header |
||
1102 | $v_size = @ftell($this->_zip_fd)-$v_offset; |
||
1103 | |||
1104 | // ----- Create the central dir footer |
||
1105 | if (($v_result = $this->_writeCentralHeader($v_count, $v_size, $v_offset, |
||
1106 | $v_comment)) != 1) { |
||
1107 | // ----- Reset the file list |
||
1108 | unset($v_header_list); |
||
1109 | |||
1110 | // ----- Return |
||
1111 | return $v_result; |
||
1112 | } |
||
1113 | |||
1114 | // ----- Return |
||
1115 | return $v_result; |
||
1116 | } |
||
1117 | // --------------------------------------------------------------------------- |
||
1118 | |||
1119 | // --------------------------------------------------------------------------- |
||
1120 | // Function : _addFileList() |
||
1121 | // Description : |
||
1122 | // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is |
||
1123 | // different from the real path of the file. This is usefull if you want to |
||
1124 | // run the lib in any directory, and memorize relative path from an other directory. |
||
1125 | // Parameters : |
||
1126 | // $p_list : An array containing the file or directory names to add in the tar |
||
1127 | // $p_result_list : list of added files with their properties (specially the status field) |
||
1128 | // $p_add_dir : Path to add in the filename path archived |
||
1129 | // $p_remove_dir : Path to remove in the filename path archived |
||
1130 | // Return Values : |
||
1131 | // --------------------------------------------------------------------------- |
||
1132 | /** |
||
1133 | * Archive_Zip::_addFileList() |
||
1134 | * |
||
1135 | * { Description } |
||
1136 | * |
||
1137 | */ |
||
1138 | public function _addFileList($p_list, &$p_result_list, |
||
1139 | $p_add_dir, $p_remove_dir, $p_remove_all_dir, |
||
1140 | &$p_params) |
||
1141 | { |
||
1142 | $v_result=1; |
||
1143 | $v_header = array(); |
||
1144 | |||
1145 | // ----- Recuperate the current number of elt in list |
||
1146 | $v_nb = count($p_result_list); |
||
1147 | |||
1148 | // ----- Loop on the files |
||
1149 | for ($j=0; ($j<count($p_list)) && ($v_result==1); $j++) { |
||
1150 | // ----- Recuperate the filename |
||
1151 | $p_filename = $this->_tool_TranslateWinPath($p_list[$j], false); |
||
1152 | |||
1153 | // ----- Skip empty file names |
||
1154 | if ($p_filename == '') { |
||
1155 | continue; |
||
1156 | } |
||
1157 | |||
1158 | // ----- Check the filename |
||
1159 | if (!file_exists($p_filename)) { |
||
1160 | $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, |
||
1161 | "File '$p_filename' does not exists"); |
||
1162 | return Archive_Zip::errorCode(); |
||
1163 | } |
||
1164 | |||
1165 | // ----- Look if it is a file or a dir with no all pathnre move |
||
1166 | if (is_file($p_filename) || (is_dir($p_filename) && !$p_remove_all_dir)) { |
||
1167 | // ----- Add the file |
||
1168 | if (($v_result = $this->_addFile($p_filename, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1) { |
||
1169 | // ----- Return status |
||
1170 | return $v_result; |
||
1171 | } |
||
1172 | |||
1173 | // ----- Store the file infos |
||
1174 | $p_result_list[$v_nb++] = $v_header; |
||
1175 | } |
||
1176 | |||
1177 | // ----- Look for directory |
||
1178 | if (is_dir($p_filename)) { |
||
1179 | |||
1180 | // ----- Look for path |
||
1181 | if ($p_filename != '.') { |
||
1182 | $v_path = $p_filename . '/'; |
||
1183 | } else { |
||
1184 | $v_path = ''; |
||
1185 | } |
||
1186 | |||
1187 | // ----- Read the directory for files and sub-directories |
||
1188 | $p_hdir = opendir($p_filename); |
||
1189 | $p_hitem = readdir($p_hdir); // '.' directory |
||
1190 | $p_hitem = readdir($p_hdir); // '..' directory |
||
1191 | while ($p_hitem = readdir($p_hdir)) { |
||
1192 | |||
1193 | // ----- Look for a file |
||
1194 | if (is_file($v_path.$p_hitem)) { |
||
1195 | |||
1196 | // ----- Add the file |
||
1197 | if (($v_result = $this->_addFile($v_path.$p_hitem, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1) { |
||
1198 | // ----- Return status |
||
1199 | return $v_result; |
||
1200 | } |
||
1201 | |||
1202 | // ----- Store the file infos |
||
1203 | $p_result_list[$v_nb++] = $v_header; |
||
1204 | } |
||
1205 | |||
1206 | // ----- Recursive call to _addFileList() |
||
1207 | else { |
||
1208 | |||
1209 | // ----- Need an array as parameter |
||
1210 | $p_temp_list[0] = $v_path.$p_hitem; |
||
1211 | $v_result = $this->_addFileList($p_temp_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params); |
||
1212 | |||
1213 | // ----- Update the number of elements of the list |
||
1214 | $v_nb = count($p_result_list); |
||
1215 | } |
||
1216 | } |
||
1217 | |||
1218 | // ----- Free memory for the recursive loop |
||
1219 | unset($p_temp_list, $p_hdir, $p_hitem); |
||
1220 | } |
||
1221 | } |
||
1222 | |||
1223 | return $v_result; |
||
1224 | } |
||
1225 | // --------------------------------------------------------------------------- |
||
1226 | |||
1227 | // --------------------------------------------------------------------------- |
||
1228 | // Function : _addFile() |
||
1229 | // Description : |
||
1230 | // Parameters : |
||
1231 | // Return Values : |
||
1232 | // --------------------------------------------------------------------------- |
||
1233 | /** |
||
1234 | * Archive_Zip::_addFile() |
||
1235 | * |
||
1236 | * { Description } |
||
1237 | * |
||
1238 | */ |
||
1239 | public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params) |
||
1240 | { |
||
1241 | $v_result=1; |
||
1242 | |||
1243 | if ($p_filename == '') { |
||
1244 | // ----- Error log |
||
1245 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Invalid file list parameter (invalid or empty list)'); |
||
1246 | |||
1247 | // ----- Return |
||
1248 | return Archive_Zip::errorCode(); |
||
1249 | } |
||
1250 | |||
1251 | // ----- Calculate the stored filename |
||
1252 | $v_stored_filename = $p_filename; |
||
1253 | |||
1254 | // ----- Look for all path to remove |
||
1255 | if ($p_remove_all_dir) { |
||
1256 | $v_stored_filename = basename($p_filename); |
||
1257 | } |
||
1258 | // ----- Look for partial path remove |
||
1259 | elseif ($p_remove_dir != '') { |
||
1260 | if (substr($p_remove_dir, -1) != '/') { |
||
1261 | $p_remove_dir .= '/'; |
||
1262 | } |
||
1263 | |||
1264 | if ((substr($p_filename, 0, 2) == './') || (substr($p_remove_dir, 0, 2) == './')) { |
||
1265 | View Code Duplication | if ((substr($p_filename, 0, 2) == './') && (substr($p_remove_dir, 0, 2) != './')) { |
|
1266 | $p_remove_dir = './' . $p_remove_dir; |
||
1267 | } |
||
1268 | View Code Duplication | if ((substr($p_filename, 0, 2) != './') && (substr($p_remove_dir, 0, 2) == './')) { |
|
1269 | $p_remove_dir = substr($p_remove_dir, 2); |
||
1270 | } |
||
1271 | } |
||
1272 | |||
1273 | $v_compare = $this->_tool_PathInclusion($p_remove_dir, $p_filename); |
||
1274 | if ($v_compare > 0) { |
||
1275 | // if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) |
||
1276 | |||
1277 | |||
1278 | if ($v_compare == 2) { |
||
1279 | $v_stored_filename = ''; |
||
1280 | } else { |
||
1281 | $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); |
||
1282 | } |
||
1283 | } |
||
1284 | } |
||
1285 | // ----- Look for path to add |
||
1286 | if ($p_add_dir != '') { |
||
1287 | if (substr($p_add_dir, -1) == '/') { |
||
1288 | $v_stored_filename = $p_add_dir.$v_stored_filename; |
||
1289 | } else { |
||
1290 | $v_stored_filename = $p_add_dir . '/' . $v_stored_filename; |
||
1291 | } |
||
1292 | } |
||
1293 | |||
1294 | // ----- Filename (reduce the path of stored name) |
||
1295 | $v_stored_filename = $this->_tool_PathReduction($v_stored_filename); |
||
1296 | |||
1297 | |||
1298 | /* filename length moved after call-back in release 1.3 |
||
1299 | // ----- Check the path length |
||
1300 | if (strlen($v_stored_filename) > 0xFF) |
||
1301 | { |
||
1302 | // ----- Error log |
||
1303 | $this->_errorLog(-5, "Stored file name is too long (max. 255) : '$v_stored_filename'"); |
||
1304 | |||
1305 | // ----- Return |
||
1306 | return Archive_Zip::errorCode(); |
||
1307 | } |
||
1308 | */ |
||
1309 | |||
1310 | // ----- Set the file properties |
||
1311 | clearstatcache(); |
||
1312 | $p_header['version'] = 20; |
||
1313 | $p_header['version_extracted'] = 10; |
||
1314 | $p_header['flag'] = 0; |
||
1315 | $p_header['compression'] = 0; |
||
1316 | $p_header['mtime'] = filemtime($p_filename); |
||
1317 | $p_header['crc'] = 0; |
||
1318 | $p_header['compressed_size'] = 0; |
||
1319 | $p_header['size'] = filesize($p_filename); |
||
1320 | $p_header['filename_len'] = strlen($p_filename); |
||
1321 | $p_header['extra_len'] = 0; |
||
1322 | $p_header['comment_len'] = 0; |
||
1323 | $p_header['disk'] = 0; |
||
1324 | $p_header['internal'] = 0; |
||
1325 | $p_header['external'] = (is_file($p_filename)?0xFE49FFE0:0x41FF0010); |
||
1326 | $p_header['offset'] = 0; |
||
1327 | $p_header['filename'] = $p_filename; |
||
1328 | $p_header['stored_filename'] = $v_stored_filename; |
||
1329 | $p_header['extra'] = ''; |
||
1330 | $p_header['comment'] = ''; |
||
1331 | $p_header['status'] = 'ok'; |
||
1332 | $p_header['index'] = -1; |
||
1333 | |||
1334 | // ----- Look for pre-add callback |
||
1335 | if (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD]) |
||
1336 | && ($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD] != '')) { |
||
1337 | |||
1338 | // ----- Generate a local information |
||
1339 | $v_local_header = array(); |
||
1340 | $this->_convertHeader2FileInfo($p_header, $v_local_header); |
||
1341 | |||
1342 | // ----- Call the callback |
||
1343 | // Here I do not use call_user_func() because I need to send a reference to the |
||
1344 | // header. |
||
1345 | eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_ADD].'(ARCHIVE_ZIP_PARAM_PRE_ADD, $v_local_header);'); |
||
1346 | if ($v_result == 0) { |
||
1347 | // ----- Change the file status |
||
1348 | $p_header['status'] = 'skipped'; |
||
1349 | $v_result = 1; |
||
1350 | } |
||
1351 | |||
1352 | // ----- Update the informations |
||
1353 | // Only some fields can be modified |
||
1354 | if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { |
||
1355 | $p_header['stored_filename'] = $this->_tool_PathReduction($v_local_header['stored_filename']); |
||
1356 | } |
||
1357 | } |
||
1358 | |||
1359 | // ----- Look for empty stored filename |
||
1360 | if ($p_header['stored_filename'] == '') { |
||
1361 | $p_header['status'] = 'filtered'; |
||
1362 | } |
||
1363 | |||
1364 | // ----- Check the path length |
||
1365 | if (strlen($p_header['stored_filename']) > 0xFF) { |
||
1366 | $p_header['status'] = 'filename_too_long'; |
||
1367 | } |
||
1368 | |||
1369 | // ----- Look if no error, or file not skipped |
||
1370 | if ($p_header['status'] == 'ok') { |
||
1371 | |||
1372 | // ----- Look for a file |
||
1373 | if (is_file($p_filename)) { |
||
1374 | // ----- Open the source file |
||
1375 | View Code Duplication | if (($v_file = @fopen($p_filename, 'rb')) == 0) { |
|
1376 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); |
||
1377 | return Archive_Zip::errorCode(); |
||
1378 | } |
||
1379 | |||
1380 | if ($p_params['no_compression']) { |
||
1381 | // ----- Read the file content |
||
1382 | $v_content_compressed = @fread($v_file, $p_header['size']); |
||
1383 | |||
1384 | // ----- Calculate the CRC |
||
1385 | $p_header['crc'] = crc32($v_content_compressed); |
||
1386 | } else { |
||
1387 | // ----- Read the file content |
||
1388 | $v_content = @fread($v_file, $p_header['size']); |
||
1389 | |||
1390 | // ----- Calculate the CRC |
||
1391 | $p_header['crc'] = crc32($v_content); |
||
1392 | |||
1393 | // ----- Compress the file |
||
1394 | $v_content_compressed = gzdeflate($v_content); |
||
1395 | } |
||
1396 | |||
1397 | // ----- Set header parameters |
||
1398 | $p_header['compressed_size'] = strlen($v_content_compressed); |
||
1399 | $p_header['compression'] = 8; |
||
1400 | |||
1401 | // ----- Call the header generation |
||
1402 | if (($v_result = $this->_writeFileHeader($p_header)) != 1) { |
||
1403 | @fclose($v_file); |
||
1404 | return $v_result; |
||
1405 | } |
||
1406 | |||
1407 | // ----- Write the compressed content |
||
1408 | $v_binary_data = pack('a'.$p_header['compressed_size'], $v_content_compressed); |
||
1409 | @fwrite($this->_zip_fd, $v_binary_data, $p_header['compressed_size']); |
||
1410 | |||
1411 | // ----- Close the file |
||
1412 | @fclose($v_file); |
||
1413 | } |
||
1414 | |||
1415 | // ----- Look for a directory |
||
1416 | else { |
||
1417 | // ----- Set the file properties |
||
1418 | $p_header['filename'] .= '/'; |
||
1419 | $p_header['filename_len']++; |
||
1420 | $p_header['size'] = 0; |
||
1421 | $p_header['external'] = 0x41FF0010; // Value for a folder : to be checked |
||
1422 | |||
1423 | // ----- Call the header generation |
||
1424 | if (($v_result = $this->_writeFileHeader($p_header)) != 1) { |
||
1425 | return $v_result; |
||
1426 | } |
||
1427 | } |
||
1428 | } |
||
1429 | |||
1430 | // ----- Look for pre-add callback |
||
1431 | if (isset($p_params[ARCHIVE_ZIP_PARAM_POST_ADD]) |
||
1432 | && ($p_params[ARCHIVE_ZIP_PARAM_POST_ADD] != '')) { |
||
1433 | |||
1434 | // ----- Generate a local information |
||
1435 | $v_local_header = array(); |
||
1436 | $this->_convertHeader2FileInfo($p_header, $v_local_header); |
||
1437 | |||
1438 | // ----- Call the callback |
||
1439 | // Here I do not use call_user_func() because I need to send a reference to the |
||
1440 | // header. |
||
1441 | eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_ADD].'(ARCHIVE_ZIP_PARAM_POST_ADD, $v_local_header);'); |
||
1442 | if ($v_result == 0) { |
||
1443 | // ----- Ignored |
||
1444 | $v_result = 1; |
||
1445 | } |
||
1446 | |||
1447 | // ----- Update the informations |
||
1448 | // Nothing can be modified |
||
1449 | } |
||
1450 | |||
1451 | // ----- Return |
||
1452 | return $v_result; |
||
1453 | } |
||
1454 | // --------------------------------------------------------------------------- |
||
1455 | |||
1456 | // --------------------------------------------------------------------------- |
||
1457 | // Function : _writeFileHeader() |
||
1458 | // Description : |
||
1459 | // Parameters : |
||
1460 | // Return Values : |
||
1461 | // --------------------------------------------------------------------------- |
||
1462 | /** |
||
1463 | * Archive_Zip::_writeFileHeader() |
||
1464 | * |
||
1465 | * { Description } |
||
1466 | * |
||
1467 | */ |
||
1468 | public function _writeFileHeader(&$p_header) |
||
1469 | { |
||
1470 | $v_result=1; |
||
1471 | |||
1472 | // TBC |
||
1473 | //for(reset($p_header); $key = key($p_header); next($p_header)) { |
||
1474 | //} |
||
1475 | |||
1476 | // ----- Store the offset position of the file |
||
1477 | $p_header['offset'] = ftell($this->_zip_fd); |
||
1478 | |||
1479 | // ----- Transform UNIX mtime to DOS format mdate/mtime |
||
1480 | $v_date = getdate($p_header['mtime']); |
||
1481 | $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; |
||
1482 | $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; |
||
1483 | |||
1484 | // ----- Packed data |
||
1485 | $v_binary_data = pack('VvvvvvVVVvv', 0x04034b50, $p_header['version'], $p_header['flag'], |
||
1486 | $p_header['compression'], $v_mtime, $v_mdate, |
||
1487 | $p_header['crc'], $p_header['compressed_size'], $p_header['size'], |
||
1488 | strlen($p_header['stored_filename']), $p_header['extra_len']); |
||
1489 | |||
1490 | // ----- Write the first 148 bytes of the header in the archive |
||
1491 | fwrite($this->_zip_fd, $v_binary_data, 30); |
||
1492 | |||
1493 | // ----- Write the variable fields |
||
1494 | View Code Duplication | if (strlen($p_header['stored_filename']) != 0) { |
|
1495 | fwrite($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); |
||
1496 | } |
||
1497 | View Code Duplication | if ($p_header['extra_len'] != 0) { |
|
1498 | fwrite($this->_zip_fd, $p_header['extra'], $p_header['extra_len']); |
||
1499 | } |
||
1500 | |||
1501 | // ----- Return |
||
1502 | return $v_result; |
||
1503 | } |
||
1504 | // --------------------------------------------------------------------------- |
||
1505 | |||
1506 | // --------------------------------------------------------------------------- |
||
1507 | // Function : _writeCentralFileHeader() |
||
1508 | // Description : |
||
1509 | // Parameters : |
||
1510 | // Return Values : |
||
1511 | // --------------------------------------------------------------------------- |
||
1512 | /** |
||
1513 | * Archive_Zip::_writeCentralFileHeader() |
||
1514 | * |
||
1515 | * { Description } |
||
1516 | * |
||
1517 | */ |
||
1518 | public function _writeCentralFileHeader(&$p_header) |
||
1519 | { |
||
1520 | $v_result=1; |
||
1521 | |||
1522 | // TBC |
||
1523 | //for(reset($p_header); $key = key($p_header); next($p_header)) { |
||
1524 | //} |
||
1525 | |||
1526 | // ----- Transform UNIX mtime to DOS format mdate/mtime |
||
1527 | $v_date = getdate($p_header['mtime']); |
||
1528 | $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; |
||
1529 | $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; |
||
1530 | |||
1531 | // ----- Packed data |
||
1532 | $v_binary_data = pack('VvvvvvvVVVvvvvvVV', 0x02014b50, $p_header['version'], $p_header['version_extracted'], |
||
1533 | $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], |
||
1534 | $p_header['compressed_size'], $p_header['size'], |
||
1535 | strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'], |
||
1536 | $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']); |
||
1537 | |||
1538 | // ----- Write the 42 bytes of the header in the zip file |
||
1539 | fwrite($this->_zip_fd, $v_binary_data, 46); |
||
1540 | |||
1541 | // ----- Write the variable fields |
||
1542 | View Code Duplication | if (strlen($p_header['stored_filename']) != 0) { |
|
1543 | fwrite($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); |
||
1544 | } |
||
1545 | View Code Duplication | if ($p_header['extra_len'] != 0) { |
|
1546 | fwrite($this->_zip_fd, $p_header['extra'], $p_header['extra_len']); |
||
1547 | } |
||
1548 | if ($p_header['comment_len'] != 0) { |
||
1549 | fwrite($this->_zip_fd, $p_header['comment'], $p_header['comment_len']); |
||
1550 | } |
||
1551 | |||
1552 | // ----- Return |
||
1553 | return $v_result; |
||
1554 | } |
||
1555 | // --------------------------------------------------------------------------- |
||
1556 | |||
1557 | // --------------------------------------------------------------------------- |
||
1558 | // Function : _writeCentralHeader() |
||
1559 | // Description : |
||
1560 | // Parameters : |
||
1561 | // Return Values : |
||
1562 | // --------------------------------------------------------------------------- |
||
1563 | /** |
||
1564 | * Archive_Zip::_writeCentralHeader() |
||
1565 | * |
||
1566 | * { Description } |
||
1567 | * |
||
1568 | */ |
||
1569 | public function _writeCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) |
||
1570 | { |
||
1571 | $v_result=1; |
||
1572 | |||
1573 | // ----- Packed data |
||
1574 | $v_binary_data = pack('VvvvvVVv', 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment)); |
||
1575 | |||
1576 | // ----- Write the 22 bytes of the header in the zip file |
||
1577 | fwrite($this->_zip_fd, $v_binary_data, 22); |
||
1578 | |||
1579 | // ----- Write the variable fields |
||
1580 | if (strlen($p_comment) != 0) { |
||
1581 | fwrite($this->_zip_fd, $p_comment, strlen($p_comment)); |
||
1582 | } |
||
1583 | |||
1584 | // ----- Return |
||
1585 | return $v_result; |
||
1586 | } |
||
1587 | // --------------------------------------------------------------------------- |
||
1588 | |||
1589 | // --------------------------------------------------------------------------- |
||
1590 | // Function : _list() |
||
1591 | // Description : |
||
1592 | // Parameters : |
||
1593 | // Return Values : |
||
1594 | // --------------------------------------------------------------------------- |
||
1595 | /** |
||
1596 | * Archive_Zip::_list() |
||
1597 | * |
||
1598 | * { Description } |
||
1599 | * |
||
1600 | */ |
||
1601 | public function _list(&$p_list) |
||
1602 | { |
||
1603 | $v_result=1; |
||
1604 | |||
1605 | // ----- Open the zip file |
||
1606 | View Code Duplication | if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0) { |
|
1607 | // ----- Error log |
||
1608 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->_zipname.'\' in binary read mode'); |
||
1609 | |||
1610 | // ----- Return |
||
1611 | return Archive_Zip::errorCode(); |
||
1612 | } |
||
1613 | |||
1614 | // ----- Read the central directory informations |
||
1615 | $v_central_dir = array(); |
||
1616 | if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
||
1617 | return $v_result; |
||
1618 | } |
||
1619 | |||
1620 | // ----- Go to beginning of Central Dir |
||
1621 | @rewind($this->_zip_fd); |
||
1622 | View Code Duplication | if (@fseek($this->_zip_fd, $v_central_dir['offset'])) { |
|
1623 | // ----- Error log |
||
1624 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
||
1625 | |||
1626 | // ----- Return |
||
1627 | return Archive_Zip::errorCode(); |
||
1628 | } |
||
1629 | |||
1630 | // ----- Read each entry |
||
1631 | for ($i=0; $i<$v_central_dir['entries']; $i++) { |
||
1632 | // ----- Read the file header |
||
1633 | if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) { |
||
1634 | return $v_result; |
||
1635 | } |
||
1636 | $v_header['index'] = $i; |
||
1637 | |||
1638 | // ----- Get the only interesting attributes |
||
1639 | $this->_convertHeader2FileInfo($v_header, $p_list[$i]); |
||
1640 | unset($v_header); |
||
1641 | } |
||
1642 | |||
1643 | // ----- Close the zip file |
||
1644 | $this->_closeFd(); |
||
1645 | |||
1646 | // ----- Return |
||
1647 | return $v_result; |
||
1648 | } |
||
1649 | // --------------------------------------------------------------------------- |
||
1650 | |||
1651 | // --------------------------------------------------------------------------- |
||
1652 | // Function : _convertHeader2FileInfo() |
||
1653 | // Description : |
||
1654 | // This function takes the file informations from the central directory |
||
1655 | // entries and extract the interesting parameters that will be given back. |
||
1656 | // The resulting file infos are set in the array $p_info |
||
1657 | // $p_info['filename'] : Filename with full path. Given by user (add), |
||
1658 | // extracted in the filesystem (extract). |
||
1659 | // $p_info['stored_filename'] : Stored filename in the archive. |
||
1660 | // $p_info['size'] = Size of the file. |
||
1661 | // $p_info['compressed_size'] = Compressed size of the file. |
||
1662 | // $p_info['mtime'] = Last modification date of the file. |
||
1663 | // $p_info['comment'] = Comment associated with the file. |
||
1664 | // $p_info['folder'] = true/false : indicates if the entry is a folder or not. |
||
1665 | // $p_info['status'] = status of the action on the file. |
||
1666 | // Parameters : |
||
1667 | // Return Values : |
||
1668 | // --------------------------------------------------------------------------- |
||
1669 | /** |
||
1670 | * Archive_Zip::_convertHeader2FileInfo() |
||
1671 | * |
||
1672 | * { Description } |
||
1673 | * |
||
1674 | */ |
||
1675 | public function _convertHeader2FileInfo($p_header, &$p_info) |
||
1676 | { |
||
1677 | $v_result=1; |
||
1678 | |||
1679 | // ----- Get the interesting attributes |
||
1680 | $p_info['filename'] = $p_header['filename']; |
||
1681 | $p_info['stored_filename'] = $p_header['stored_filename']; |
||
1682 | $p_info['size'] = $p_header['size']; |
||
1683 | $p_info['compressed_size'] = $p_header['compressed_size']; |
||
1684 | $p_info['mtime'] = $p_header['mtime']; |
||
1685 | $p_info['comment'] = $p_header['comment']; |
||
1686 | $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010); |
||
1687 | $p_info['index'] = $p_header['index']; |
||
1688 | $p_info['status'] = $p_header['status']; |
||
1689 | |||
1690 | // ----- Return |
||
1691 | return $v_result; |
||
1692 | } |
||
1693 | // --------------------------------------------------------------------------- |
||
1694 | |||
1695 | // --------------------------------------------------------------------------- |
||
1696 | // Function : _extractByRule() |
||
1697 | // Description : |
||
1698 | // Extract a file or directory depending of rules (by index, by name, ...) |
||
1699 | // Parameters : |
||
1700 | // $p_file_list : An array where will be placed the properties of each |
||
1701 | // extracted file |
||
1702 | // $p_path : Path to add while writing the extracted files |
||
1703 | // $p_remove_path : Path to remove (from the file memorized path) while writing the |
||
1704 | // extracted files. If the path does not match the file path, |
||
1705 | // the file is extracted with its memorized path. |
||
1706 | // $p_remove_path does not apply to 'list' mode. |
||
1707 | // $p_path and $p_remove_path are commulative. |
||
1708 | // Return Values : |
||
1709 | // 1 on success,0 or less on error (see error code list) |
||
1710 | // --------------------------------------------------------------------------- |
||
1711 | /** |
||
1712 | * Archive_Zip::_extractByRule() |
||
1713 | * |
||
1714 | * { Description } |
||
1715 | * |
||
1716 | */ |
||
1717 | public function _extractByRule(&$p_file_list, &$p_params) |
||
1718 | { |
||
1719 | $v_result=1; |
||
1720 | |||
1721 | $p_path = $p_params['add_path']; |
||
1722 | $p_remove_path = $p_params['remove_path']; |
||
1723 | $p_remove_all_path = $p_params['remove_all_path']; |
||
1724 | |||
1725 | // ----- Check the path |
||
1726 | if (($p_path == '') |
||
1727 | || ((substr($p_path, 0, 1) != '/') |
||
1728 | && (substr($p_path, 0, 3) != '../') && (substr($p_path, 1, 2) != ':/'))) { |
||
1729 | $p_path = './' . $p_path; |
||
1730 | } |
||
1731 | |||
1732 | // ----- Reduce the path last (and duplicated) '/' |
||
1733 | if (($p_path != './') && ($p_path != '/')) { |
||
1734 | // ----- Look for the path end '/' |
||
1735 | while (substr($p_path, -1) == '/') { |
||
1736 | $p_path = substr($p_path, 0, strlen($p_path)-1); |
||
1737 | } |
||
1738 | } |
||
1739 | |||
1740 | // ----- Look for path to remove format (should end by /) |
||
1741 | if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) { |
||
1742 | $p_remove_path .= '/'; |
||
1743 | } |
||
1744 | $p_remove_path_size = strlen($p_remove_path); |
||
1745 | |||
1746 | // ----- Open the zip file |
||
1747 | if (($v_result = $this->_openFd('rb')) != 1) { |
||
1748 | return $v_result; |
||
1749 | } |
||
1750 | |||
1751 | // ----- Read the central directory informations |
||
1752 | $v_central_dir = array(); |
||
1753 | if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
||
1754 | // ----- Close the zip file |
||
1755 | $this->_closeFd(); |
||
1756 | |||
1757 | return $v_result; |
||
1758 | } |
||
1759 | |||
1760 | // ----- Start at beginning of Central Dir |
||
1761 | $v_pos_entry = $v_central_dir['offset']; |
||
1762 | |||
1763 | // ----- Read each entry |
||
1764 | $j_start = 0; |
||
1765 | for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) { |
||
1766 | // ----- Read next Central dir entry |
||
1767 | @rewind($this->_zip_fd); |
||
1768 | View Code Duplication | if (@fseek($this->_zip_fd, $v_pos_entry)) { |
|
1769 | $this->_closeFd(); |
||
1770 | |||
1771 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, |
||
1772 | 'Invalid archive size'); |
||
1773 | |||
1774 | return Archive_Zip::errorCode(); |
||
1775 | } |
||
1776 | |||
1777 | // ----- Read the file header |
||
1778 | $v_header = array(); |
||
1779 | if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) { |
||
1780 | $this->_closeFd(); |
||
1781 | |||
1782 | return $v_result; |
||
1783 | } |
||
1784 | |||
1785 | // ----- Store the index |
||
1786 | $v_header['index'] = $i; |
||
1787 | |||
1788 | // ----- Store the file position |
||
1789 | $v_pos_entry = ftell($this->_zip_fd); |
||
1790 | |||
1791 | // ----- Look for the specific extract rules |
||
1792 | $v_extract = false; |
||
1793 | |||
1794 | // ----- Look for extract by name rule |
||
1795 | if (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]) |
||
1796 | && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) { |
||
1797 | |||
1798 | // ----- Look if the filename is in the list |
||
1799 | for ($j=0; |
||
1800 | ($j < count($p_params[ARCHIVE_ZIP_PARAM_BY_NAME])) |
||
1801 | && (!$v_extract); |
||
1802 | $j++) { |
||
1803 | |||
1804 | // ----- Look for a directory |
||
1805 | if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) == '/') { |
||
1806 | |||
1807 | // ----- Look if the directory is in the filename path |
||
1808 | if ((strlen($v_header['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) |
||
1809 | && (substr($v_header['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) { |
||
1810 | $v_extract = true; |
||
1811 | } |
||
1812 | } |
||
1813 | // ----- Look for a filename |
||
1814 | elseif ($v_header['stored_filename'] == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) { |
||
1815 | $v_extract = true; |
||
1816 | } |
||
1817 | } |
||
1818 | } |
||
1819 | |||
1820 | // ----- Look for extract by ereg rule |
||
1821 | elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG]) |
||
1822 | && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != '')) { |
||
1823 | if (ereg($p_params[ARCHIVE_ZIP_PARAM_BY_EREG], $v_header['stored_filename'])) { |
||
1824 | $v_extract = true; |
||
1825 | } |
||
1826 | } |
||
1827 | |||
1828 | // ----- Look for extract by preg rule |
||
1829 | View Code Duplication | elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG]) |
|
1830 | && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != '')) { |
||
1831 | if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG], $v_header['stored_filename'])) { |
||
1832 | $v_extract = true; |
||
1833 | } |
||
1834 | } |
||
1835 | |||
1836 | // ----- Look for extract by index rule |
||
1837 | View Code Duplication | elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]) |
|
1838 | && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) { |
||
1839 | |||
1840 | // ----- Look if the index is in the list |
||
1841 | for ($j=$j_start; ($j < count($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) && (!$v_extract); $j++) { |
||
1842 | if (($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']) && ($i<=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) { |
||
1843 | $v_extract = true; |
||
1844 | } |
||
1845 | if ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) { |
||
1846 | $j_start = $j+1; |
||
1847 | } |
||
1848 | |||
1849 | if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']>$i) { |
||
1850 | break; |
||
1851 | } |
||
1852 | } |
||
1853 | } |
||
1854 | |||
1855 | // ----- Look for no rule, which means extract all the archive |
||
1856 | else { |
||
1857 | $v_extract = true; |
||
1858 | } |
||
1859 | |||
1860 | |||
1861 | // ----- Look for real extraction |
||
1862 | if ($v_extract) { |
||
1863 | |||
1864 | // ----- Go to the file position |
||
1865 | @rewind($this->_zip_fd); |
||
1866 | View Code Duplication | if (@fseek($this->_zip_fd, $v_header['offset'])) { |
|
1867 | // ----- Close the zip file |
||
1868 | $this->_closeFd(); |
||
1869 | |||
1870 | // ----- Error log |
||
1871 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
||
1872 | |||
1873 | // ----- Return |
||
1874 | return Archive_Zip::errorCode(); |
||
1875 | } |
||
1876 | |||
1877 | // ----- Look for extraction as string |
||
1878 | if ($p_params[ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING]) { |
||
1879 | |||
1880 | // ----- Extracting the file |
||
1881 | if (($v_result = $this->_extractFileAsString($v_header, $v_string)) != 1) { |
||
1882 | // ----- Close the zip file |
||
1883 | $this->_closeFd(); |
||
1884 | |||
1885 | return $v_result; |
||
1886 | } |
||
1887 | |||
1888 | // ----- Get the only interesting attributes |
||
1889 | if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) { |
||
1890 | // ----- Close the zip file |
||
1891 | $this->_closeFd(); |
||
1892 | |||
1893 | return $v_result; |
||
1894 | } |
||
1895 | |||
1896 | // ----- Set the file content |
||
1897 | $p_file_list[$v_nb_extracted]['content'] = $v_string; |
||
1898 | |||
1899 | // ----- Next extracted file |
||
1900 | $v_nb_extracted++; |
||
1901 | } else { |
||
1902 | // ----- Extracting the file |
||
1903 | if (($v_result = $this->_extractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_params)) != 1) { |
||
1904 | // ----- Close the zip file |
||
1905 | $this->_closeFd(); |
||
1906 | |||
1907 | return $v_result; |
||
1908 | } |
||
1909 | |||
1910 | // ----- Get the only interesting attributes |
||
1911 | if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { |
||
1912 | // ----- Close the zip file |
||
1913 | $this->_closeFd(); |
||
1914 | |||
1915 | return $v_result; |
||
1916 | } |
||
1917 | } |
||
1918 | } |
||
1919 | } |
||
1920 | |||
1921 | // ----- Close the zip file |
||
1922 | $this->_closeFd(); |
||
1923 | |||
1924 | // ----- Return |
||
1925 | return $v_result; |
||
1926 | } |
||
1927 | // --------------------------------------------------------------------------- |
||
1928 | |||
1929 | // --------------------------------------------------------------------------- |
||
1930 | // Function : _extractFile() |
||
1931 | // Description : |
||
1932 | // Parameters : |
||
1933 | // Return Values : |
||
1934 | // --------------------------------------------------------------------------- |
||
1935 | /** |
||
1936 | * Archive_Zip::_extractFile() |
||
1937 | * |
||
1938 | * { Description } |
||
1939 | * |
||
1940 | */ |
||
1941 | public function _extractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_params) |
||
1942 | { |
||
1943 | $v_result=1; |
||
1944 | |||
1945 | // ----- Read the file header |
||
1946 | if (($v_result = $this->_readFileHeader($v_header)) != 1) { |
||
1947 | // ----- Return |
||
1948 | return $v_result; |
||
1949 | } |
||
1950 | |||
1951 | |||
1952 | // ----- Check that the file header is coherent with $p_entry info |
||
1953 | // TBC |
||
1954 | |||
1955 | // ----- Look for all path to remove |
||
1956 | if ($p_remove_all_path == true) { |
||
1957 | // ----- Get the basename of the path |
||
1958 | $p_entry['filename'] = basename($p_entry['filename']); |
||
1959 | } |
||
1960 | |||
1961 | // ----- Look for path to remove |
||
1962 | elseif ($p_remove_path != '') { |
||
1963 | //if (strcmp($p_remove_path, $p_entry['filename'])==0) |
||
1964 | if ($this->_tool_PathInclusion($p_remove_path, $p_entry['filename']) == 2) { |
||
1965 | |||
1966 | // ----- Change the file status |
||
1967 | $p_entry['status'] = 'filtered'; |
||
1968 | |||
1969 | // ----- Return |
||
1970 | return $v_result; |
||
1971 | } |
||
1972 | |||
1973 | $p_remove_path_size = strlen($p_remove_path); |
||
1974 | if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) { |
||
1975 | |||
1976 | // ----- Remove the path |
||
1977 | $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); |
||
1978 | } |
||
1979 | } |
||
1980 | |||
1981 | // ----- Add the path |
||
1982 | if ($p_path != '') { |
||
1983 | $p_entry['filename'] = $p_path . '/' . $p_entry['filename']; |
||
1984 | } |
||
1985 | |||
1986 | // ----- Look for pre-extract callback |
||
1987 | if (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT]) |
||
1988 | && ($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] != '')) { |
||
1989 | |||
1990 | // ----- Generate a local information |
||
1991 | $v_local_header = array(); |
||
1992 | $this->_convertHeader2FileInfo($p_entry, $v_local_header); |
||
1993 | |||
1994 | // ----- Call the callback |
||
1995 | // Here I do not use call_user_func() because I need to send a reference to the |
||
1996 | // header. |
||
1997 | eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT].'(ARCHIVE_ZIP_PARAM_PRE_EXTRACT, $v_local_header);'); |
||
1998 | if ($v_result == 0) { |
||
1999 | // ----- Change the file status |
||
2000 | $p_entry['status'] = 'skipped'; |
||
2001 | $v_result = 1; |
||
2002 | } |
||
2003 | |||
2004 | // ----- Update the informations |
||
2005 | // Only some fields can be modified |
||
2006 | $p_entry['filename'] = $v_local_header['filename']; |
||
2007 | } |
||
2008 | |||
2009 | // ----- Trace |
||
2010 | |||
2011 | // ----- Look if extraction should be done |
||
2012 | if ($p_entry['status'] == 'ok') { |
||
2013 | |||
2014 | // ----- Look for specific actions while the file exist |
||
2015 | if (file_exists($p_entry['filename'])) { |
||
2016 | |||
2017 | // ----- Look if file is a directory |
||
2018 | if (is_dir($p_entry['filename'])) { |
||
2019 | |||
2020 | // ----- Change the file status |
||
2021 | $p_entry['status'] = 'already_a_directory'; |
||
2022 | |||
2023 | // ----- Return |
||
2024 | //return $v_result; |
||
2025 | } |
||
2026 | // ----- Look if file is write protected |
||
2027 | elseif (!is_writable($p_entry['filename'])) { |
||
2028 | |||
2029 | // ----- Change the file status |
||
2030 | $p_entry['status'] = 'write_protected'; |
||
2031 | |||
2032 | // ----- Return |
||
2033 | //return $v_result; |
||
2034 | } |
||
2035 | |||
2036 | // ----- Look if the extracted file is older |
||
2037 | elseif (filemtime($p_entry['filename']) > $p_entry['mtime']) { |
||
2038 | |||
2039 | // ----- Change the file status |
||
2040 | $p_entry['status'] = 'newer_exist'; |
||
2041 | |||
2042 | // ----- Return |
||
2043 | //return $v_result; |
||
2044 | } |
||
2045 | } |
||
2046 | |||
2047 | // ----- Check the directory availability and create it if necessary |
||
2048 | else { |
||
2049 | if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) { |
||
2050 | $v_dir_to_check = $p_entry['filename']; |
||
2051 | } elseif (!strstr($p_entry['filename'], '/')) { |
||
2052 | $v_dir_to_check = ''; |
||
2053 | } else { |
||
2054 | $v_dir_to_check = dirname($p_entry['filename']); |
||
2055 | } |
||
2056 | |||
2057 | if (($v_result = $this->_dirCheck($v_dir_to_check, ($p_entry['external'] & 0x00000010) == 0x00000010)) != 1) { |
||
2058 | |||
2059 | // ----- Change the file status |
||
2060 | $p_entry['status'] = 'path_creation_fail'; |
||
2061 | |||
2062 | // ----- Return |
||
2063 | //return $v_result; |
||
2064 | $v_result = 1; |
||
2065 | } |
||
2066 | } |
||
2067 | } |
||
2068 | |||
2069 | // ----- Look if extraction should be done |
||
2070 | if ($p_entry['status'] == 'ok') { |
||
2071 | |||
2072 | // ----- Do the extraction (if not a folder) |
||
2073 | if (!(($p_entry['external']&0x00000010)==0x00000010)) { |
||
2074 | |||
2075 | // ----- Look for not compressed file |
||
2076 | if ($p_entry['compressed_size'] == $p_entry['size']) { |
||
2077 | |||
2078 | // ----- Opening destination file |
||
2079 | View Code Duplication | if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { |
|
2080 | |||
2081 | // ----- Change the file status |
||
2082 | $p_entry['status'] = 'write_error'; |
||
2083 | |||
2084 | // ----- Return |
||
2085 | return $v_result; |
||
2086 | } |
||
2087 | |||
2088 | |||
2089 | // ----- Read the file by ARCHIVE_ZIP_READ_BLOCK_SIZE octets blocks |
||
2090 | $v_size = $p_entry['compressed_size']; |
||
2091 | while ($v_size != 0) { |
||
2092 | $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
2093 | $v_buffer = fread($this->_zip_fd, $v_read_size); |
||
2094 | $v_binary_data = pack('a'.$v_read_size, $v_buffer); |
||
2095 | @fwrite($v_dest_file, $v_binary_data, $v_read_size); |
||
2096 | $v_size -= $v_read_size; |
||
2097 | } |
||
2098 | |||
2099 | // ----- Closing the destination file |
||
2100 | fclose($v_dest_file); |
||
2101 | |||
2102 | // ----- Change the file mtime |
||
2103 | touch($p_entry['filename'], $p_entry['mtime']); |
||
2104 | } else { |
||
2105 | // ----- Trace |
||
2106 | |||
2107 | // ----- Opening destination file |
||
2108 | View Code Duplication | if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { |
|
2109 | |||
2110 | // ----- Change the file status |
||
2111 | $p_entry['status'] = 'write_error'; |
||
2112 | |||
2113 | return $v_result; |
||
2114 | } |
||
2115 | |||
2116 | |||
2117 | // ----- Read the compressed file in a buffer (one shot) |
||
2118 | $v_buffer = @fread($this->_zip_fd, $p_entry['compressed_size']); |
||
2119 | |||
2120 | // ----- Decompress the file |
||
2121 | $v_file_content = gzinflate($v_buffer); |
||
2122 | unset($v_buffer); |
||
2123 | |||
2124 | // ----- Write the uncompressed data |
||
2125 | @fwrite($v_dest_file, $v_file_content, $p_entry['size']); |
||
2126 | unset($v_file_content); |
||
2127 | |||
2128 | // ----- Closing the destination file |
||
2129 | @fclose($v_dest_file); |
||
2130 | |||
2131 | // ----- Change the file mtime |
||
2132 | touch($p_entry['filename'], $p_entry['mtime']); |
||
2133 | } |
||
2134 | |||
2135 | // ----- Look for chmod option |
||
2136 | if (isset($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]) |
||
2137 | && ($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD] != 0)) { |
||
2138 | |||
2139 | // ----- Change the mode of the file |
||
2140 | chmod($p_entry['filename'], $p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]); |
||
2141 | } |
||
2142 | } |
||
2143 | } |
||
2144 | |||
2145 | // ----- Look for post-extract callback |
||
2146 | if (isset($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT]) |
||
2147 | && ($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] != '')) { |
||
2148 | |||
2149 | // ----- Generate a local information |
||
2150 | $v_local_header = array(); |
||
2151 | $this->_convertHeader2FileInfo($p_entry, $v_local_header); |
||
2152 | |||
2153 | // ----- Call the callback |
||
2154 | // Here I do not use call_user_func() because I need to send a reference to the |
||
2155 | // header. |
||
2156 | eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT].'(ARCHIVE_ZIP_PARAM_POST_EXTRACT, $v_local_header);'); |
||
2157 | } |
||
2158 | |||
2159 | // ----- Return |
||
2160 | return $v_result; |
||
2161 | } |
||
2162 | // --------------------------------------------------------------------------- |
||
2163 | |||
2164 | // --------------------------------------------------------------------------- |
||
2165 | // Function : _extractFileAsString() |
||
2166 | // Description : |
||
2167 | // Parameters : |
||
2168 | // Return Values : |
||
2169 | // --------------------------------------------------------------------------- |
||
2170 | /** |
||
2171 | * Archive_Zip::_extractFileAsString() |
||
2172 | * |
||
2173 | * { Description } |
||
2174 | * |
||
2175 | */ |
||
2176 | public function _extractFileAsString(&$p_entry, &$p_string) |
||
2177 | { |
||
2178 | $v_result=1; |
||
2179 | |||
2180 | // ----- Read the file header |
||
2181 | $v_header = array(); |
||
2182 | if (($v_result = $this->_readFileHeader($v_header)) != 1) { |
||
2183 | // ----- Return |
||
2184 | return $v_result; |
||
2185 | } |
||
2186 | |||
2187 | |||
2188 | // ----- Check that the file header is coherent with $p_entry info |
||
2189 | // TBC |
||
2190 | |||
2191 | // ----- Trace |
||
2192 | |||
2193 | // ----- Do the extraction (if not a folder) |
||
2194 | if (!(($p_entry['external']&0x00000010)==0x00000010)) { |
||
2195 | // ----- Look for not compressed file |
||
2196 | if ($p_entry['compressed_size'] == $p_entry['size']) { |
||
2197 | // ----- Trace |
||
2198 | |||
2199 | // ----- Reading the file |
||
2200 | $p_string = fread($this->_zip_fd, $p_entry['compressed_size']); |
||
2201 | } else { |
||
2202 | // ----- Trace |
||
2203 | |||
2204 | // ----- Reading the file |
||
2205 | $v_data = fread($this->_zip_fd, $p_entry['compressed_size']); |
||
2206 | |||
2207 | // ----- Decompress the file |
||
2208 | $p_string = gzinflate($v_data); |
||
2209 | } |
||
2210 | |||
2211 | // ----- Trace |
||
2212 | } else { |
||
2213 | // TBC : error : can not extract a folder in a string |
||
2214 | } |
||
2215 | |||
2216 | // ----- Return |
||
2217 | return $v_result; |
||
2218 | } |
||
2219 | // --------------------------------------------------------------------------- |
||
2220 | |||
2221 | // --------------------------------------------------------------------------- |
||
2222 | // Function : _readFileHeader() |
||
2223 | // Description : |
||
2224 | // Parameters : |
||
2225 | // Return Values : |
||
2226 | // --------------------------------------------------------------------------- |
||
2227 | /** |
||
2228 | * Archive_Zip::_readFileHeader() |
||
2229 | * |
||
2230 | * { Description } |
||
2231 | * |
||
2232 | */ |
||
2233 | public function _readFileHeader(&$p_header) |
||
2234 | { |
||
2235 | $v_result=1; |
||
2236 | |||
2237 | // ----- Read the 4 bytes signature |
||
2238 | $v_binary_data = @fread($this->_zip_fd, 4); |
||
2239 | $v_data = unpack('Vid', $v_binary_data); |
||
2240 | |||
2241 | // ----- Check signature |
||
2242 | if ($v_data['id'] != 0x04034b50) { |
||
2243 | |||
2244 | // ----- Error log |
||
2245 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); |
||
2246 | |||
2247 | // ----- Return |
||
2248 | return Archive_Zip::errorCode(); |
||
2249 | } |
||
2250 | |||
2251 | // ----- Read the first 42 bytes of the header |
||
2252 | $v_binary_data = fread($this->_zip_fd, 26); |
||
2253 | |||
2254 | // ----- Look for invalid block size |
||
2255 | View Code Duplication | if (strlen($v_binary_data) != 26) { |
|
2256 | $p_header['filename'] = ''; |
||
2257 | $p_header['status'] = 'invalid_header'; |
||
2258 | |||
2259 | // ----- Error log |
||
2260 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid block size : ' . strlen($v_binary_data)); |
||
2261 | |||
2262 | // ----- Return |
||
2263 | return Archive_Zip::errorCode(); |
||
2264 | } |
||
2265 | |||
2266 | // ----- Extract the values |
||
2267 | $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); |
||
2268 | |||
2269 | // ----- Get filename |
||
2270 | $p_header['filename'] = fread($this->_zip_fd, $v_data['filename_len']); |
||
2271 | |||
2272 | // ----- Get extra_fields |
||
2273 | if ($v_data['extra_len'] != 0) { |
||
2274 | $p_header['extra'] = fread($this->_zip_fd, $v_data['extra_len']); |
||
2275 | } else { |
||
2276 | $p_header['extra'] = ''; |
||
2277 | } |
||
2278 | |||
2279 | // ----- Extract properties |
||
2280 | $p_header['compression'] = $v_data['compression']; |
||
2281 | $p_header['size'] = $v_data['size']; |
||
2282 | $p_header['compressed_size'] = $v_data['compressed_size']; |
||
2283 | $p_header['crc'] = $v_data['crc']; |
||
2284 | $p_header['flag'] = $v_data['flag']; |
||
2285 | |||
2286 | // ----- Recuperate date in UNIX format |
||
2287 | $p_header['mdate'] = $v_data['mdate']; |
||
2288 | $p_header['mtime'] = $v_data['mtime']; |
||
2289 | View Code Duplication | if ($p_header['mdate'] && $p_header['mtime']) { |
|
2290 | // ----- Extract time |
||
2291 | $v_hour = ($p_header['mtime'] & 0xF800) >> 11; |
||
2292 | $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; |
||
2293 | $v_seconde = ($p_header['mtime'] & 0x001F)*2; |
||
2294 | |||
2295 | // ----- Extract date |
||
2296 | $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; |
||
2297 | $v_month = ($p_header['mdate'] & 0x01E0) >> 5; |
||
2298 | $v_day = $p_header['mdate'] & 0x001F; |
||
2299 | |||
2300 | // ----- Get UNIX date format |
||
2301 | $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); |
||
2302 | } else { |
||
2303 | $p_header['mtime'] = time(); |
||
2304 | } |
||
2305 | |||
2306 | // ----- Other informations |
||
2307 | |||
2308 | // TBC |
||
2309 | //for(reset($v_data); $key = key($v_data); next($v_data)) { |
||
2310 | //} |
||
2311 | |||
2312 | // ----- Set the stored filename |
||
2313 | $p_header['stored_filename'] = $p_header['filename']; |
||
2314 | |||
2315 | // ----- Set the status field |
||
2316 | $p_header['status'] = 'ok'; |
||
2317 | |||
2318 | // ----- Return |
||
2319 | return $v_result; |
||
2320 | } |
||
2321 | // --------------------------------------------------------------------------- |
||
2322 | |||
2323 | // --------------------------------------------------------------------------- |
||
2324 | // Function : _readCentralFileHeader() |
||
2325 | // Description : |
||
2326 | // Parameters : |
||
2327 | // Return Values : |
||
2328 | // --------------------------------------------------------------------------- |
||
2329 | /** |
||
2330 | * Archive_Zip::_readCentralFileHeader() |
||
2331 | * |
||
2332 | * { Description } |
||
2333 | * |
||
2334 | */ |
||
2335 | public function _readCentralFileHeader(&$p_header) |
||
2336 | { |
||
2337 | $v_result=1; |
||
2338 | |||
2339 | // ----- Read the 4 bytes signature |
||
2340 | $v_binary_data = @fread($this->_zip_fd, 4); |
||
2341 | $v_data = unpack('Vid', $v_binary_data); |
||
2342 | |||
2343 | // ----- Check signature |
||
2344 | if ($v_data['id'] != 0x02014b50) { |
||
2345 | |||
2346 | // ----- Error log |
||
2347 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); |
||
2348 | |||
2349 | // ----- Return |
||
2350 | return Archive_Zip::errorCode(); |
||
2351 | } |
||
2352 | |||
2353 | // ----- Read the first 42 bytes of the header |
||
2354 | $v_binary_data = fread($this->_zip_fd, 42); |
||
2355 | |||
2356 | // ----- Look for invalid block size |
||
2357 | View Code Duplication | if (strlen($v_binary_data) != 42) { |
|
2358 | $p_header['filename'] = ''; |
||
2359 | $p_header['status'] = 'invalid_header'; |
||
2360 | |||
2361 | // ----- Error log |
||
2362 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid block size : ' . strlen($v_binary_data)); |
||
2363 | |||
2364 | // ----- Return |
||
2365 | return Archive_Zip::errorCode(); |
||
2366 | } |
||
2367 | |||
2368 | // ----- Extract the values |
||
2369 | $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data); |
||
2370 | |||
2371 | // ----- Get filename |
||
2372 | View Code Duplication | if ($p_header['filename_len'] != 0) { |
|
2373 | $p_header['filename'] = fread($this->_zip_fd, $p_header['filename_len']); |
||
2374 | } else { |
||
2375 | $p_header['filename'] = ''; |
||
2376 | } |
||
2377 | |||
2378 | // ----- Get extra |
||
2379 | View Code Duplication | if ($p_header['extra_len'] != 0) { |
|
2380 | $p_header['extra'] = fread($this->_zip_fd, $p_header['extra_len']); |
||
2381 | } else { |
||
2382 | $p_header['extra'] = ''; |
||
2383 | } |
||
2384 | |||
2385 | // ----- Get comment |
||
2386 | View Code Duplication | if ($p_header['comment_len'] != 0) { |
|
2387 | $p_header['comment'] = fread($this->_zip_fd, $p_header['comment_len']); |
||
2388 | } else { |
||
2389 | $p_header['comment'] = ''; |
||
2390 | } |
||
2391 | |||
2392 | // ----- Extract properties |
||
2393 | |||
2394 | // ----- Recuperate date in UNIX format |
||
2395 | View Code Duplication | if ($p_header['mdate'] && $p_header['mtime']) { |
|
2396 | // ----- Extract time |
||
2397 | $v_hour = ($p_header['mtime'] & 0xF800) >> 11; |
||
2398 | $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; |
||
2399 | $v_seconde = ($p_header['mtime'] & 0x001F)*2; |
||
2400 | |||
2401 | // ----- Extract date |
||
2402 | $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; |
||
2403 | $v_month = ($p_header['mdate'] & 0x01E0) >> 5; |
||
2404 | $v_day = $p_header['mdate'] & 0x001F; |
||
2405 | |||
2406 | // ----- Get UNIX date format |
||
2407 | $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); |
||
2408 | } else { |
||
2409 | $p_header['mtime'] = time(); |
||
2410 | } |
||
2411 | |||
2412 | // ----- Set the stored filename |
||
2413 | $p_header['stored_filename'] = $p_header['filename']; |
||
2414 | |||
2415 | // ----- Set default status to ok |
||
2416 | $p_header['status'] = 'ok'; |
||
2417 | |||
2418 | // ----- Look if it is a directory |
||
2419 | if (substr($p_header['filename'], -1) == '/') { |
||
2420 | $p_header['external'] = 0x41FF0010; |
||
2421 | } |
||
2422 | |||
2423 | |||
2424 | // ----- Return |
||
2425 | return $v_result; |
||
2426 | } |
||
2427 | // --------------------------------------------------------------------------- |
||
2428 | |||
2429 | // --------------------------------------------------------------------------- |
||
2430 | // Function : _readEndCentralDir() |
||
2431 | // Description : |
||
2432 | // Parameters : |
||
2433 | // Return Values : |
||
2434 | // --------------------------------------------------------------------------- |
||
2435 | /** |
||
2436 | * Archive_Zip::_readEndCentralDir() |
||
2437 | * |
||
2438 | * { Description } |
||
2439 | * |
||
2440 | */ |
||
2441 | public function _readEndCentralDir(&$p_central_dir) |
||
2442 | { |
||
2443 | $v_result=1; |
||
2444 | |||
2445 | // ----- Go to the end of the zip file |
||
2446 | $v_size = filesize($this->_zipname); |
||
2447 | @fseek($this->_zip_fd, $v_size); |
||
2448 | View Code Duplication | if (@ftell($this->_zip_fd) != $v_size) { |
|
2449 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, |
||
2450 | 'Unable to go to the end of the archive \'' |
||
2451 | .$this->_zipname.'\''); |
||
2452 | return Archive_Zip::errorCode(); |
||
2453 | } |
||
2454 | |||
2455 | // ----- First try : look if this is an archive with no commentaries |
||
2456 | // (most of the time) |
||
2457 | // in this case the end of central dir is at 22 bytes of the file end |
||
2458 | $v_found = 0; |
||
2459 | if ($v_size > 26) { |
||
2460 | @fseek($this->_zip_fd, $v_size-22); |
||
2461 | View Code Duplication | if (($v_pos = @ftell($this->_zip_fd)) != ($v_size-22)) { |
|
2462 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, |
||
2463 | 'Unable to seek back to the middle of the archive \'' |
||
2464 | .$this->_zipname.'\''); |
||
2465 | return Archive_Zip::errorCode(); |
||
2466 | } |
||
2467 | |||
2468 | // ----- Read for bytes |
||
2469 | $v_binary_data = @fread($this->_zip_fd, 4); |
||
2470 | $v_data = unpack('Vid', $v_binary_data); |
||
2471 | |||
2472 | // ----- Check signature |
||
2473 | if ($v_data['id'] == 0x06054b50) { |
||
2474 | $v_found = 1; |
||
2475 | } |
||
2476 | |||
2477 | $v_pos = ftell($this->_zip_fd); |
||
2478 | } |
||
2479 | |||
2480 | // ----- Go back to the maximum possible size of the Central Dir End Record |
||
2481 | if (!$v_found) { |
||
2482 | $v_maximum_size = 65557; // 0xFFFF + 22; |
||
2483 | if ($v_maximum_size > $v_size) { |
||
2484 | $v_maximum_size = $v_size; |
||
2485 | } |
||
2486 | @fseek($this->_zip_fd, $v_size-$v_maximum_size); |
||
2487 | View Code Duplication | if (@ftell($this->_zip_fd) != ($v_size-$v_maximum_size)) { |
|
2488 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, |
||
2489 | 'Unable to seek back to the middle of the archive \'' |
||
2490 | .$this->_zipname.'\''); |
||
2491 | return Archive_Zip::errorCode(); |
||
2492 | } |
||
2493 | |||
2494 | // ----- Read byte per byte in order to find the signature |
||
2495 | $v_pos = ftell($this->_zip_fd); |
||
2496 | $v_bytes = 0x00000000; |
||
2497 | while ($v_pos < $v_size) { |
||
2498 | // ----- Read a byte |
||
2499 | $v_byte = @fread($this->_zip_fd, 1); |
||
2500 | |||
2501 | // ----- Add the byte |
||
2502 | $v_bytes = ($v_bytes << 8) | ord($v_byte); |
||
2503 | |||
2504 | // ----- Compare the bytes |
||
2505 | if ($v_bytes == 0x504b0506) { |
||
2506 | $v_pos++; |
||
2507 | break; |
||
2508 | } |
||
2509 | |||
2510 | $v_pos++; |
||
2511 | } |
||
2512 | |||
2513 | // ----- Look if not found end of central dir |
||
2514 | if ($v_pos == $v_size) { |
||
2515 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Unable to find End of Central Dir Record signature'); |
||
2516 | return Archive_Zip::errorCode(); |
||
2517 | } |
||
2518 | } |
||
2519 | |||
2520 | // ----- Read the first 18 bytes of the header |
||
2521 | $v_binary_data = fread($this->_zip_fd, 18); |
||
2522 | |||
2523 | // ----- Look for invalid block size |
||
2524 | if (strlen($v_binary_data) != 18) { |
||
2525 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, |
||
2526 | 'Invalid End of Central Dir Record size : ' |
||
2527 | . strlen($v_binary_data)); |
||
2528 | return Archive_Zip::errorCode(); |
||
2529 | } |
||
2530 | |||
2531 | // ----- Extract the values |
||
2532 | $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); |
||
2533 | |||
2534 | // ----- Check the global size |
||
2535 | if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { |
||
2536 | $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Fail to find the right signature'); |
||
2537 | return Archive_Zip::errorCode(); |
||
2538 | } |
||
2539 | |||
2540 | // ----- Get comment |
||
2541 | if ($v_data['comment_size'] != 0) { |
||
2542 | $p_central_dir['comment'] = fread($this->_zip_fd, $v_data['comment_size']); |
||
2543 | } else { |
||
2544 | $p_central_dir['comment'] = ''; |
||
2545 | } |
||
2546 | |||
2547 | $p_central_dir['entries'] = $v_data['entries']; |
||
2548 | $p_central_dir['disk_entries'] = $v_data['disk_entries']; |
||
2549 | $p_central_dir['offset'] = $v_data['offset']; |
||
2550 | $p_central_dir['size'] = $v_data['size']; |
||
2551 | $p_central_dir['disk'] = $v_data['disk']; |
||
2552 | $p_central_dir['disk_start'] = $v_data['disk_start']; |
||
2553 | |||
2554 | // ----- Return |
||
2555 | return $v_result; |
||
2556 | } |
||
2557 | // --------------------------------------------------------------------------- |
||
2558 | |||
2559 | // --------------------------------------------------------------------------- |
||
2560 | // Function : _deleteByRule() |
||
2561 | // Description : |
||
2562 | // Parameters : |
||
2563 | // Return Values : |
||
2564 | // --------------------------------------------------------------------------- |
||
2565 | /** |
||
2566 | * Archive_Zip::_deleteByRule() |
||
2567 | * |
||
2568 | * { Description } |
||
2569 | * |
||
2570 | */ |
||
2571 | public function _deleteByRule(&$p_result_list, &$p_params) |
||
2572 | { |
||
2573 | $v_result=1; |
||
2574 | $v_list_detail = array(); |
||
2575 | |||
2576 | // ----- Open the zip file |
||
2577 | if (($v_result=$this->_openFd('rb')) != 1) { |
||
2578 | // ----- Return |
||
2579 | return $v_result; |
||
2580 | } |
||
2581 | |||
2582 | // ----- Read the central directory informations |
||
2583 | $v_central_dir = array(); |
||
2584 | if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
||
2585 | $this->_closeFd(); |
||
2586 | return $v_result; |
||
2587 | } |
||
2588 | |||
2589 | // ----- Go to beginning of File |
||
2590 | @rewind($this->_zip_fd); |
||
2591 | |||
2592 | // ----- Scan all the files |
||
2593 | // ----- Start at beginning of Central Dir |
||
2594 | $v_pos_entry = $v_central_dir['offset']; |
||
2595 | @rewind($this->_zip_fd); |
||
2596 | View Code Duplication | if (@fseek($this->_zip_fd, $v_pos_entry)) { |
|
2597 | // ----- Clean |
||
2598 | $this->_closeFd(); |
||
2599 | |||
2600 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, |
||
2601 | 'Invalid archive size'); |
||
2602 | return Archive_Zip::errorCode(); |
||
2603 | } |
||
2604 | |||
2605 | // ----- Read each entry |
||
2606 | $v_header_list = array(); |
||
2607 | $j_start = 0; |
||
2608 | for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) { |
||
2609 | |||
2610 | // ----- Read the file header |
||
2611 | $v_header_list[$v_nb_extracted] = array(); |
||
2612 | $v_result |
||
2613 | = $this->_readCentralFileHeader($v_header_list[$v_nb_extracted]); |
||
2614 | if ($v_result != 1) { |
||
2615 | // ----- Clean |
||
2616 | $this->_closeFd(); |
||
2617 | |||
2618 | return $v_result; |
||
2619 | } |
||
2620 | |||
2621 | // ----- Store the index |
||
2622 | $v_header_list[$v_nb_extracted]['index'] = $i; |
||
2623 | |||
2624 | // ----- Look for the specific extract rules |
||
2625 | $v_found = false; |
||
2626 | |||
2627 | // ----- Look for extract by name rule |
||
2628 | if (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]) |
||
2629 | && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) { |
||
2630 | |||
2631 | // ----- Look if the filename is in the list |
||
2632 | for ($j=0; |
||
2633 | ($j < count($p_params[ARCHIVE_ZIP_PARAM_BY_NAME])) |
||
2634 | && (!$v_found); |
||
2635 | $j++) { |
||
2636 | |||
2637 | // ----- Look for a directory |
||
2638 | if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) == '/') { |
||
2639 | |||
2640 | // ----- Look if the directory is in the filename path |
||
2641 | if ((strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) |
||
2642 | && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) { |
||
2643 | $v_found = true; |
||
2644 | } elseif ((($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ |
||
2645 | && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) { |
||
2646 | $v_found = true; |
||
2647 | } |
||
2648 | } |
||
2649 | // ----- Look for a filename |
||
2650 | elseif ($v_header_list[$v_nb_extracted]['stored_filename'] |
||
2651 | == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) { |
||
2652 | $v_found = true; |
||
2653 | } |
||
2654 | } |
||
2655 | } |
||
2656 | |||
2657 | // ----- Look for extract by ereg rule |
||
2658 | View Code Duplication | elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG]) |
|
2659 | && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != '')) { |
||
2660 | if (ereg($p_params[ARCHIVE_ZIP_PARAM_BY_EREG], |
||
2661 | $v_header_list[$v_nb_extracted]['stored_filename'])) { |
||
2662 | $v_found = true; |
||
2663 | } |
||
2664 | } |
||
2665 | |||
2666 | // ----- Look for extract by preg rule |
||
2667 | View Code Duplication | elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG]) |
|
2668 | && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != '')) { |
||
2669 | if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG], |
||
2670 | $v_header_list[$v_nb_extracted]['stored_filename'])) { |
||
2671 | $v_found = true; |
||
2672 | } |
||
2673 | } |
||
2674 | |||
2675 | // ----- Look for extract by index rule |
||
2676 | View Code Duplication | elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]) |
|
2677 | && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) { |
||
2678 | |||
2679 | // ----- Look if the index is in the list |
||
2680 | for ($j=$j_start; |
||
2681 | ($j < count($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) |
||
2682 | && (!$v_found); |
||
2683 | $j++) { |
||
2684 | if (($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']) |
||
2685 | && ($i<=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) { |
||
2686 | $v_found = true; |
||
2687 | } |
||
2688 | if ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) { |
||
2689 | $j_start = $j+1; |
||
2690 | } |
||
2691 | |||
2692 | if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']>$i) { |
||
2693 | break; |
||
2694 | } |
||
2695 | } |
||
2696 | } |
||
2697 | |||
2698 | // ----- Look for deletion |
||
2699 | if ($v_found) { |
||
2700 | unset($v_header_list[$v_nb_extracted]); |
||
2701 | } else { |
||
2702 | $v_nb_extracted++; |
||
2703 | } |
||
2704 | } |
||
2705 | |||
2706 | // ----- Look if something need to be deleted |
||
2707 | if ($v_nb_extracted > 0) { |
||
2708 | |||
2709 | // ----- Creates a temporay file |
||
2710 | $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-') |
||
2711 | .'.tmp'; |
||
2712 | |||
2713 | // ----- Creates a temporary zip archive |
||
2714 | $v_temp_zip = new Archive_Zip($v_zip_temp_name); |
||
2715 | |||
2716 | // ----- Open the temporary zip file in write mode |
||
2717 | if (($v_result = $v_temp_zip->_openFd('wb')) != 1) { |
||
2718 | $this->_closeFd(); |
||
2719 | |||
2720 | // ----- Return |
||
2721 | return $v_result; |
||
2722 | } |
||
2723 | |||
2724 | // ----- Look which file need to be kept |
||
2725 | for ($i=0; $i < count($v_header_list); $i++) { |
||
2726 | |||
2727 | // ----- Calculate the position of the header |
||
2728 | @rewind($this->_zip_fd); |
||
2729 | if (@fseek($this->_zip_fd, $v_header_list[$i]['offset'])) { |
||
2730 | // ----- Clean |
||
2731 | $this->_closeFd(); |
||
2732 | $v_temp_zip->_closeFd(); |
||
2733 | @unlink($v_zip_temp_name); |
||
2734 | |||
2735 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, |
||
2736 | 'Invalid archive size'); |
||
2737 | return Archive_Zip::errorCode(); |
||
2738 | } |
||
2739 | |||
2740 | // ----- Read the file header |
||
2741 | View Code Duplication | if (($v_result = $this->_readFileHeader($v_header_list[$i])) != 1) { |
|
2742 | // ----- Clean |
||
2743 | $this->_closeFd(); |
||
2744 | $v_temp_zip->_closeFd(); |
||
2745 | @unlink($v_zip_temp_name); |
||
2746 | |||
2747 | return $v_result; |
||
2748 | } |
||
2749 | |||
2750 | // ----- Write the file header |
||
2751 | $v_result = $v_temp_zip->_writeFileHeader($v_header_list[$i]); |
||
2752 | if ($v_result != 1) { |
||
2753 | // ----- Clean |
||
2754 | $this->_closeFd(); |
||
2755 | $v_temp_zip->_closeFd(); |
||
2756 | @unlink($v_zip_temp_name); |
||
2757 | |||
2758 | return $v_result; |
||
2759 | } |
||
2760 | |||
2761 | // ----- Read/write the data block |
||
2762 | $v_result = $this->_tool_CopyBlock($this->_zip_fd, |
||
2763 | $v_temp_zip->_zip_fd, |
||
2764 | $v_header_list[$i]['compressed_size']); |
||
2765 | if ($v_result != 1) { |
||
2766 | // ----- Clean |
||
2767 | $this->_closeFd(); |
||
2768 | $v_temp_zip->_closeFd(); |
||
2769 | @unlink($v_zip_temp_name); |
||
2770 | |||
2771 | return $v_result; |
||
2772 | } |
||
2773 | } |
||
2774 | |||
2775 | // ----- Store the offset of the central dir |
||
2776 | $v_offset = @ftell($v_temp_zip->_zip_fd); |
||
2777 | |||
2778 | // ----- Re-Create the Central Dir files header |
||
2779 | for ($i=0; $i < count($v_header_list); $i++) { |
||
2780 | // ----- Create the file header |
||
2781 | $v_result=$v_temp_zip->_writeCentralFileHeader($v_header_list[$i]); |
||
2782 | if ($v_result != 1) { |
||
2783 | // ----- Clean |
||
2784 | $v_temp_zip->_closeFd(); |
||
2785 | $this->_closeFd(); |
||
2786 | @unlink($v_zip_temp_name); |
||
2787 | |||
2788 | return $v_result; |
||
2789 | } |
||
2790 | |||
2791 | // ----- Transform the header to a 'usable' info |
||
2792 | $v_temp_zip->_convertHeader2FileInfo($v_header_list[$i], |
||
2793 | $p_result_list[$i]); |
||
2794 | } |
||
2795 | |||
2796 | |||
2797 | // ----- Zip file comment |
||
2798 | $v_comment = ''; |
||
2799 | |||
2800 | // ----- Calculate the size of the central header |
||
2801 | $v_size = @ftell($v_temp_zip->_zip_fd)-$v_offset; |
||
2802 | |||
2803 | // ----- Create the central dir footer |
||
2804 | $v_result = $v_temp_zip->_writeCentralHeader(count($v_header_list), |
||
2805 | $v_size, $v_offset, |
||
2806 | $v_comment); |
||
2807 | View Code Duplication | if ($v_result != 1) { |
|
2808 | // ----- Clean |
||
2809 | unset($v_header_list); |
||
2810 | $v_temp_zip->_closeFd(); |
||
2811 | $this->_closeFd(); |
||
2812 | @unlink($v_zip_temp_name); |
||
2813 | |||
2814 | return $v_result; |
||
2815 | } |
||
2816 | |||
2817 | // ----- Close |
||
2818 | $v_temp_zip->_closeFd(); |
||
2819 | $this->_closeFd(); |
||
2820 | |||
2821 | // ----- Delete the zip file |
||
2822 | // TBC : I should test the result ... |
||
2823 | @unlink($this->_zipname); |
||
2824 | |||
2825 | // ----- Rename the temporary file |
||
2826 | // TBC : I should test the result ... |
||
2827 | //@rename($v_zip_temp_name, $this->_zipname); |
||
2828 | $this->_tool_Rename($v_zip_temp_name, $this->_zipname); |
||
2829 | |||
2830 | // ----- Destroy the temporary archive |
||
2831 | unset($v_temp_zip); |
||
2832 | } |
||
2833 | |||
2834 | // ----- Return |
||
2835 | return $v_result; |
||
2836 | } |
||
2837 | // --------------------------------------------------------------------------- |
||
2838 | |||
2839 | // --------------------------------------------------------------------------- |
||
2840 | // Function : _dirCheck() |
||
2841 | // Description : |
||
2842 | // Check if a directory exists, if not it creates it and all the parents directory |
||
2843 | // which may be useful. |
||
2844 | // Parameters : |
||
2845 | // $p_dir : Directory path to check. |
||
2846 | // Return Values : |
||
2847 | // 1 : OK |
||
2848 | // -1 : Unable to create directory |
||
2849 | // --------------------------------------------------------------------------- |
||
2850 | /** |
||
2851 | * Archive_Zip::_dirCheck() |
||
2852 | * |
||
2853 | * { Description } |
||
2854 | * |
||
2855 | * @param [type] $p_is_dir |
||
2856 | */ |
||
2857 | public function _dirCheck($p_dir, $p_is_dir=false) |
||
2858 | { |
||
2859 | $v_result = 1; |
||
2860 | |||
2861 | // ----- Remove the final '/' |
||
2862 | if ($p_is_dir && (substr($p_dir, -1) == '/')) { |
||
2863 | $p_dir = substr($p_dir, 0, strlen($p_dir)-1); |
||
2864 | } |
||
2865 | |||
2866 | // ----- Check the directory availability |
||
2867 | if (is_dir($p_dir) || ($p_dir == '')) { |
||
2868 | return 1; |
||
2869 | } |
||
2870 | |||
2871 | // ----- Extract parent directory |
||
2872 | $p_parent_dir = dirname($p_dir); |
||
2873 | |||
2874 | // ----- Just a check |
||
2875 | if ($p_parent_dir != $p_dir) { |
||
2876 | // ----- Look for parent directory |
||
2877 | if ($p_parent_dir != '') { |
||
2878 | if (($v_result = $this->_dirCheck($p_parent_dir)) != 1) { |
||
2879 | return $v_result; |
||
2880 | } |
||
2881 | } |
||
2882 | } |
||
2883 | |||
2884 | // ----- Create the directory |
||
2885 | if (!@mkdir($p_dir, 0777)) { |
||
2886 | $this->_errorLog(ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL, |
||
2887 | "Unable to create directory '$p_dir'"); |
||
2888 | return Archive_Zip::errorCode(); |
||
2889 | } |
||
2890 | |||
2891 | // ----- Return |
||
2892 | return $v_result; |
||
2893 | } |
||
2894 | // --------------------------------------------------------------------------- |
||
2895 | |||
2896 | // --------------------------------------------------------------------------- |
||
2897 | // Function : _merge() |
||
2898 | // Description : |
||
2899 | // If $p_archive_to_add does not exist, the function exit with a success result. |
||
2900 | // Parameters : |
||
2901 | // Return Values : |
||
2902 | // --------------------------------------------------------------------------- |
||
2903 | /** |
||
2904 | * Archive_Zip::_merge() |
||
2905 | * |
||
2906 | * { Description } |
||
2907 | * |
||
2908 | */ |
||
2909 | public function _merge(&$p_archive_to_add) |
||
2910 | { |
||
2911 | $v_result=1; |
||
2912 | |||
2913 | // ----- Look if the archive_to_add exists |
||
2914 | if (!is_file($p_archive_to_add->_zipname)) { |
||
2915 | // ----- Nothing to merge, so merge is a success |
||
2916 | return 1; |
||
2917 | } |
||
2918 | |||
2919 | // ----- Look if the archive exists |
||
2920 | if (!is_file($this->_zipname)) { |
||
2921 | // ----- Do a duplicate |
||
2922 | $v_result = $this->_duplicate($p_archive_to_add->_zipname); |
||
2923 | |||
2924 | return $v_result; |
||
2925 | } |
||
2926 | |||
2927 | // ----- Open the zip file |
||
2928 | if (($v_result=$this->_openFd('rb')) != 1) { |
||
2929 | return $v_result; |
||
2930 | } |
||
2931 | |||
2932 | // ----- Read the central directory informations |
||
2933 | $v_central_dir = array(); |
||
2934 | if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
||
2935 | $this->_closeFd(); |
||
2936 | return $v_result; |
||
2937 | } |
||
2938 | |||
2939 | // ----- Go to beginning of File |
||
2940 | @rewind($this->_zip_fd); |
||
2941 | |||
2942 | // ----- Open the archive_to_add file |
||
2943 | if (($v_result=$p_archive_to_add->_openFd('rb')) != 1) { |
||
2944 | $this->_closeFd(); |
||
2945 | return $v_result; |
||
2946 | } |
||
2947 | |||
2948 | // ----- Read the central directory informations |
||
2949 | $v_central_dir_to_add = array(); |
||
2950 | $v_result = $p_archive_to_add->_readEndCentralDir($v_central_dir_to_add); |
||
2951 | if ($v_result != 1) { |
||
2952 | $this->_closeFd(); |
||
2953 | $p_archive_to_add->_closeFd(); |
||
2954 | return $v_result; |
||
2955 | } |
||
2956 | |||
2957 | // ----- Go to beginning of File |
||
2958 | @rewind($p_archive_to_add->_zip_fd); |
||
2959 | |||
2960 | // ----- Creates a temporay file |
||
2961 | $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-').'.tmp'; |
||
2962 | |||
2963 | // ----- Open the temporary file in write mode |
||
2964 | View Code Duplication | if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) { |
|
2965 | $this->_closeFd(); |
||
2966 | $p_archive_to_add->_closeFd(); |
||
2967 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, |
||
2968 | 'Unable to open temporary file \'' |
||
2969 | .$v_zip_temp_name.'\' in binary write mode'); |
||
2970 | return Archive_Zip::errorCode(); |
||
2971 | } |
||
2972 | |||
2973 | // ----- Copy the files from the archive to the temporary file |
||
2974 | // TBC : Here I should better append the file and go back to erase the |
||
2975 | // central dir |
||
2976 | $v_size = $v_central_dir['offset']; |
||
2977 | while ($v_size != 0) { |
||
2978 | $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
2979 | ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
2980 | $v_buffer = fread($this->_zip_fd, $v_read_size); |
||
2981 | @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
||
2982 | $v_size -= $v_read_size; |
||
2983 | } |
||
2984 | |||
2985 | // ----- Copy the files from the archive_to_add into the temporary file |
||
2986 | $v_size = $v_central_dir_to_add['offset']; |
||
2987 | while ($v_size != 0) { |
||
2988 | $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
2989 | ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
2990 | $v_buffer = fread($p_archive_to_add->_zip_fd, $v_read_size); |
||
2991 | @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
||
2992 | $v_size -= $v_read_size; |
||
2993 | } |
||
2994 | |||
2995 | // ----- Store the offset of the central dir |
||
2996 | $v_offset = @ftell($v_zip_temp_fd); |
||
2997 | |||
2998 | // ----- Copy the block of file headers from the old archive |
||
2999 | $v_size = $v_central_dir['size']; |
||
3000 | View Code Duplication | while ($v_size != 0) { |
|
3001 | $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
3002 | ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
3003 | $v_buffer = @fread($this->_zip_fd, $v_read_size); |
||
3004 | @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
||
3005 | $v_size -= $v_read_size; |
||
3006 | } |
||
3007 | |||
3008 | // ----- Copy the block of file headers from the archive_to_add |
||
3009 | $v_size = $v_central_dir_to_add['size']; |
||
3010 | View Code Duplication | while ($v_size != 0) { |
|
3011 | $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
3012 | ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
3013 | $v_buffer = @fread($p_archive_to_add->_zip_fd, $v_read_size); |
||
3014 | @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
||
3015 | $v_size -= $v_read_size; |
||
3016 | } |
||
3017 | |||
3018 | // ----- Zip file comment |
||
3019 | // TBC : I should merge the two comments |
||
3020 | $v_comment = ''; |
||
3021 | |||
3022 | // ----- Calculate the size of the (new) central header |
||
3023 | $v_size = @ftell($v_zip_temp_fd)-$v_offset; |
||
3024 | |||
3025 | // ----- Swap the file descriptor |
||
3026 | // Here is a trick : I swap the temporary fd with the zip fd, in order to use |
||
3027 | // the following methods on the temporary fil and not the real archive fd |
||
3028 | $v_swap = $this->_zip_fd; |
||
3029 | $this->_zip_fd = $v_zip_temp_fd; |
||
3030 | $v_zip_temp_fd = $v_swap; |
||
3031 | |||
3032 | // ----- Create the central dir footer |
||
3033 | if (($v_result = $this->_writeCentralHeader($v_central_dir['entries'] |
||
3034 | +$v_central_dir_to_add['entries'], |
||
3035 | $v_size, $v_offset, |
||
3036 | $v_comment)) != 1) { |
||
3037 | $this->_closeFd(); |
||
3038 | $p_archive_to_add->_closeFd(); |
||
3039 | @fclose($v_zip_temp_fd); |
||
3040 | $this->_zip_fd = null; |
||
3041 | |||
3042 | // ----- Reset the file list |
||
3043 | unset($v_header_list); |
||
3044 | |||
3045 | // ----- Return |
||
3046 | return $v_result; |
||
3047 | } |
||
3048 | |||
3049 | // ----- Swap back the file descriptor |
||
3050 | $v_swap = $this->_zip_fd; |
||
3051 | $this->_zip_fd = $v_zip_temp_fd; |
||
3052 | $v_zip_temp_fd = $v_swap; |
||
3053 | |||
3054 | // ----- Close |
||
3055 | $this->_closeFd(); |
||
3056 | $p_archive_to_add->_closeFd(); |
||
3057 | |||
3058 | // ----- Close the temporary file |
||
3059 | @fclose($v_zip_temp_fd); |
||
3060 | |||
3061 | // ----- Delete the zip file |
||
3062 | // TBC : I should test the result ... |
||
3063 | @unlink($this->_zipname); |
||
3064 | |||
3065 | // ----- Rename the temporary file |
||
3066 | // TBC : I should test the result ... |
||
3067 | //@rename($v_zip_temp_name, $this->_zipname); |
||
3068 | $this->_tool_Rename($v_zip_temp_name, $this->_zipname); |
||
3069 | |||
3070 | // ----- Return |
||
3071 | return $v_result; |
||
3072 | } |
||
3073 | // --------------------------------------------------------------------------- |
||
3074 | |||
3075 | // --------------------------------------------------------------------------- |
||
3076 | // Function : _duplicate() |
||
3077 | // Description : |
||
3078 | // Parameters : |
||
3079 | // Return Values : |
||
3080 | // --------------------------------------------------------------------------- |
||
3081 | /** |
||
3082 | * Archive_Zip::_duplicate() |
||
3083 | * |
||
3084 | * { Description } |
||
3085 | * |
||
3086 | */ |
||
3087 | public function _duplicate($p_archive_filename) |
||
3088 | { |
||
3089 | $v_result=1; |
||
3090 | |||
3091 | // ----- Look if the $p_archive_filename exists |
||
3092 | if (!is_file($p_archive_filename)) { |
||
3093 | |||
3094 | // ----- Nothing to duplicate, so duplicate is a success. |
||
3095 | $v_result = 1; |
||
3096 | |||
3097 | // ----- Return |
||
3098 | return $v_result; |
||
3099 | } |
||
3100 | |||
3101 | // ----- Open the zip file |
||
3102 | if (($v_result=$this->_openFd('wb')) != 1) { |
||
3103 | // ----- Return |
||
3104 | return $v_result; |
||
3105 | } |
||
3106 | |||
3107 | // ----- Open the temporary file in write mode |
||
3108 | View Code Duplication | if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) { |
|
3109 | $this->_closeFd(); |
||
3110 | $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, |
||
3111 | 'Unable to open archive file \'' |
||
3112 | .$p_archive_filename.'\' in binary write mode'); |
||
3113 | return Archive_Zip::errorCode(); |
||
3114 | } |
||
3115 | |||
3116 | // ----- Copy the files from the archive to the temporary file |
||
3117 | // TBC : Here I should better append the file and go back to erase the |
||
3118 | // central dir |
||
3119 | $v_size = filesize($p_archive_filename); |
||
3120 | while ($v_size != 0) { |
||
3121 | $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
3122 | ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
3123 | $v_buffer = fread($v_zip_temp_fd, $v_read_size); |
||
3124 | @fwrite($this->_zip_fd, $v_buffer, $v_read_size); |
||
3125 | $v_size -= $v_read_size; |
||
3126 | } |
||
3127 | |||
3128 | // ----- Close |
||
3129 | $this->_closeFd(); |
||
3130 | |||
3131 | // ----- Close the temporary file |
||
3132 | @fclose($v_zip_temp_fd); |
||
3133 | |||
3134 | return $v_result; |
||
3135 | } |
||
3136 | // --------------------------------------------------------------------------- |
||
3137 | |||
3138 | /** |
||
3139 | * Archive_Zip::_check_parameters() |
||
3140 | * |
||
3141 | * { Description } |
||
3142 | * |
||
3143 | * @param integer $p_error_code |
||
3144 | * @param string $p_error_string |
||
3145 | */ |
||
3146 | public function _check_parameters(&$p_params, $p_default) |
||
3147 | { |
||
3148 | |||
3149 | // ----- Check that param is an array |
||
3150 | if (!is_array($p_params)) { |
||
3151 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, |
||
3152 | 'Unsupported parameter, waiting for an array'); |
||
3153 | return Archive_Zip::errorCode(); |
||
3154 | } |
||
3155 | |||
3156 | // ----- Check that all the params are valid |
||
3157 | for (reset($p_params); list($v_key, $v_value) = each($p_params);) { |
||
3158 | if (!isset($p_default[$v_key])) { |
||
3159 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, |
||
3160 | 'Unsupported parameter with key \''.$v_key.'\''); |
||
3161 | |||
3162 | return Archive_Zip::errorCode(); |
||
3163 | } |
||
3164 | } |
||
3165 | |||
3166 | // ----- Set the default values |
||
3167 | for (reset($p_default); list($v_key, $v_value) = each($p_default);) { |
||
3168 | if (!isset($p_params[$v_key])) { |
||
3169 | $p_params[$v_key] = $p_default[$v_key]; |
||
3170 | } |
||
3171 | } |
||
3172 | |||
3173 | // ----- Check specific parameters |
||
3174 | $v_callback_list = array('callback_pre_add', 'callback_post_add', |
||
3175 | 'callback_pre_extract', 'callback_post_extract'); |
||
3176 | for ($i=0; $i < count($v_callback_list); $i++) { |
||
3177 | $v_key=$v_callback_list[$i]; |
||
3178 | if (isset($p_params[$v_key]) && ($p_params[$v_key] != '')) { |
||
3179 | if (!function_exists($p_params[$v_key])) { |
||
3180 | $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE, |
||
3181 | "Callback '".$p_params[$v_key] |
||
3182 | ."()' is not an existing function for " |
||
3183 | ."parameter '".$v_key."'"); |
||
3184 | return Archive_Zip::errorCode(); |
||
3185 | } |
||
3186 | } |
||
3187 | } |
||
3188 | |||
3189 | return 1; |
||
3190 | } |
||
3191 | // --------------------------------------------------------------------------- |
||
3192 | |||
3193 | // --------------------------------------------------------------------------- |
||
3194 | // Function : _errorLog() |
||
3195 | // Description : |
||
3196 | // Parameters : |
||
3197 | // --------------------------------------------------------------------------- |
||
3198 | /** |
||
3199 | * Archive_Zip::_errorLog() |
||
3200 | * |
||
3201 | * { Description } |
||
3202 | * |
||
3203 | * @param integer $p_error_code |
||
3204 | * @param string $p_error_string |
||
3205 | */ |
||
3206 | public function _errorLog($p_error_code=0, $p_error_string='') |
||
3207 | { |
||
3208 | $this->_error_code = $p_error_code; |
||
3209 | $this->_error_string = $p_error_string; |
||
3210 | } |
||
3211 | // --------------------------------------------------------------------------- |
||
3212 | |||
3213 | // --------------------------------------------------------------------------- |
||
3214 | // Function : _errorReset() |
||
3215 | // Description : |
||
3216 | // Parameters : |
||
3217 | // --------------------------------------------------------------------------- |
||
3218 | /** |
||
3219 | * Archive_Zip::_errorReset() |
||
3220 | * |
||
3221 | * { Description } |
||
3222 | * |
||
3223 | */ |
||
3224 | public function _errorReset() |
||
3225 | { |
||
3226 | $this->_error_code = 1; |
||
3227 | $this->_error_string = ''; |
||
3228 | } |
||
3229 | // --------------------------------------------------------------------------- |
||
3230 | |||
3231 | // --------------------------------------------------------------------------- |
||
3232 | // Function : $this->_tool_PathReduction() |
||
3233 | // Description : |
||
3234 | // Parameters : |
||
3235 | // Return Values : |
||
3236 | // --------------------------------------------------------------------------- |
||
3237 | /** |
||
3238 | * _tool_PathReduction() |
||
3239 | * |
||
3240 | * { Description } |
||
3241 | * |
||
3242 | */ |
||
3243 | public function _tool_PathReduction($p_dir) |
||
3244 | { |
||
3245 | $v_result = ''; |
||
3246 | |||
3247 | // ----- Look for not empty path |
||
3248 | if ($p_dir != '') { |
||
3249 | // ----- Explode path by directory names |
||
3250 | $v_list = explode('/', $p_dir); |
||
3251 | |||
3252 | // ----- Study directories from last to first |
||
3253 | for ($i= count($v_list) - 1; $i >= 0; $i--) { |
||
3254 | // ----- Look for current path |
||
3255 | if ($v_list[$i] == '.') { |
||
3256 | // ----- Ignore this directory |
||
3257 | // Should be the first $i=0, but no check is done |
||
3258 | } elseif ($v_list[$i] == '..') { |
||
3259 | // ----- Ignore it and ignore the $i-1 |
||
3260 | $i--; |
||
3261 | } elseif (($v_list[$i] == '') && ($i != (count($v_list) - 1)) && ($i != 0)) { |
||
3262 | // ----- Ignore only the double '//' in path, |
||
3263 | // but not the first and last '/' |
||
3264 | } else { |
||
3265 | $v_result = $v_list[$i].($i!=(count($v_list) - 1)? '/' . $v_result: ''); |
||
3266 | } |
||
3267 | } |
||
3268 | } |
||
3269 | |||
3270 | // ----- Return |
||
3271 | return $v_result; |
||
3272 | } |
||
3273 | // --------------------------------------------------------------------------- |
||
3274 | |||
3275 | // --------------------------------------------------------------------------- |
||
3276 | // Function : $this->_tool_PathInclusion() |
||
3277 | // Description : |
||
3278 | // This function indicates if the path $p_path is under the $p_dir tree. Or, |
||
3279 | // said in an other way, if the file or sub-dir $p_path is inside the dir |
||
3280 | // $p_dir. |
||
3281 | // The function indicates also if the path is exactly the same as the dir. |
||
3282 | // This function supports path with duplicated '/' like '//', but does not |
||
3283 | // support '.' or '..' statements. |
||
3284 | // Parameters : |
||
3285 | // Return Values : |
||
3286 | // 0 if $p_path is not inside directory $p_dir |
||
3287 | // 1 if $p_path is inside directory $p_dir |
||
3288 | // 2 if $p_path is exactly the same as $p_dir |
||
3289 | // --------------------------------------------------------------------------- |
||
3290 | /** |
||
3291 | * _tool_PathInclusion() |
||
3292 | * |
||
3293 | * { Description } |
||
3294 | * |
||
3295 | */ |
||
3296 | public function _tool_PathInclusion($p_dir, $p_path) |
||
3297 | { |
||
3298 | $v_result = 1; |
||
3299 | |||
3300 | // ----- Explode dir and path by directory separator |
||
3301 | $v_list_dir = explode('/', $p_dir); |
||
3302 | $v_list_dir_size = count($v_list_dir); |
||
3303 | $v_list_path = explode('/', $p_path); |
||
3304 | $v_list_path_size = count($v_list_path); |
||
3305 | |||
3306 | // ----- Study directories paths |
||
3307 | $i = 0; |
||
3308 | $j = 0; |
||
3309 | while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && $v_result) { |
||
3310 | |||
3311 | // ----- Look for empty dir (path reduction) |
||
3312 | if ($v_list_dir[$i] == '') { |
||
3313 | $i++; |
||
3314 | continue; |
||
3315 | } |
||
3316 | if ($v_list_path[$j] == '') { |
||
3317 | $j++; |
||
3318 | continue; |
||
3319 | } |
||
3320 | |||
3321 | // ----- Compare the items |
||
3322 | if (($v_list_dir[$i] != $v_list_path[$j]) |
||
3323 | && ($v_list_dir[$i] != '') |
||
3324 | && ($v_list_path[$j] != '')) { |
||
3325 | $v_result = 0; |
||
3326 | } |
||
3327 | |||
3328 | // ----- Next items |
||
3329 | $i++; |
||
3330 | $j++; |
||
3331 | } |
||
3332 | |||
3333 | // ----- Look if everything seems to be the same |
||
3334 | if ($v_result) { |
||
3335 | // ----- Skip all the empty items |
||
3336 | while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) { |
||
3337 | $j++; |
||
3338 | } |
||
3339 | while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) { |
||
3340 | $i++; |
||
3341 | } |
||
3342 | |||
3343 | if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { |
||
3344 | // ----- There are exactly the same |
||
3345 | $v_result = 2; |
||
3346 | } elseif ($i < $v_list_dir_size) { |
||
3347 | // ----- The path is shorter than the dir |
||
3348 | $v_result = 0; |
||
3349 | } |
||
3350 | } |
||
3351 | |||
3352 | // ----- Return |
||
3353 | return $v_result; |
||
3354 | } |
||
3355 | // --------------------------------------------------------------------------- |
||
3356 | |||
3357 | // --------------------------------------------------------------------------- |
||
3358 | // Function : $this->_tool_CopyBlock() |
||
3359 | // Description : |
||
3360 | // Parameters : |
||
3361 | // $p_mode : read/write compression mode |
||
3362 | // 0 : src & dest normal |
||
3363 | // 1 : src gzip, dest normal |
||
3364 | // 2 : src normal, dest gzip |
||
3365 | // 3 : src & dest gzip |
||
3366 | // Return Values : |
||
3367 | // --------------------------------------------------------------------------- |
||
3368 | /** |
||
3369 | * _tool_CopyBlock() |
||
3370 | * |
||
3371 | * { Description } |
||
3372 | * |
||
3373 | * @param integer $p_mode |
||
3374 | */ |
||
3375 | public function _tool_CopyBlock($p_src, $p_dest, $p_size, $p_mode=0) |
||
3376 | { |
||
3377 | $v_result = 1; |
||
3378 | |||
3379 | if ($p_mode==0) { |
||
3380 | while ($p_size != 0) { |
||
3381 | $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
3382 | ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
3383 | $v_buffer = @fread($p_src, $v_read_size); |
||
3384 | @fwrite($p_dest, $v_buffer, $v_read_size); |
||
0 ignored issues
–
show
|
|||
3385 | $p_size -= $v_read_size; |
||
3386 | } |
||
3387 | View Code Duplication | } elseif ($p_mode==1) { |
|
3388 | while ($p_size != 0) { |
||
3389 | $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
3390 | ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
3391 | $v_buffer = @gzread($p_src, $v_read_size); |
||
3392 | @fwrite($p_dest, $v_buffer, $v_read_size); |
||
3393 | $p_size -= $v_read_size; |
||
3394 | } |
||
3395 | } elseif ($p_mode==2) { |
||
3396 | while ($p_size != 0) { |
||
3397 | $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
3398 | ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
3399 | $v_buffer = @fread($p_src, $v_read_size); |
||
3400 | @gzwrite($p_dest, $v_buffer, $v_read_size); |
||
3401 | $p_size -= $v_read_size; |
||
3402 | } |
||
3403 | View Code Duplication | } elseif ($p_mode==3) { |
|
3404 | while ($p_size != 0) { |
||
3405 | $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE |
||
3406 | ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
||
3407 | $v_buffer = @gzread($p_src, $v_read_size); |
||
3408 | @gzwrite($p_dest, $v_buffer, $v_read_size); |
||
3409 | $p_size -= $v_read_size; |
||
3410 | } |
||
3411 | } |
||
3412 | |||
3413 | // ----- Return |
||
3414 | return $v_result; |
||
3415 | } |
||
3416 | // --------------------------------------------------------------------------- |
||
3417 | |||
3418 | // --------------------------------------------------------------------------- |
||
3419 | // Function : $this->_tool_Rename() |
||
3420 | // Description : |
||
3421 | // This function tries to do a simple rename() function. If it fails, it |
||
3422 | // tries to copy the $p_src file in a new $p_dest file and then unlink the |
||
3423 | // first one. |
||
3424 | // Parameters : |
||
3425 | // $p_src : Old filename |
||
3426 | // $p_dest : New filename |
||
3427 | // Return Values : |
||
3428 | // 1 on success, 0 on failure. |
||
3429 | // --------------------------------------------------------------------------- |
||
3430 | /** |
||
3431 | * _tool_Rename() |
||
3432 | * |
||
3433 | * { Description } |
||
3434 | * |
||
3435 | */ |
||
3436 | public function _tool_Rename($p_src, $p_dest) |
||
3437 | { |
||
3438 | $v_result = 1; |
||
3439 | |||
3440 | // ----- Try to rename the files |
||
3441 | if (!@rename($p_src, $p_dest)) { |
||
3442 | |||
3443 | // ----- Try to copy & unlink the src |
||
3444 | if (!@copy($p_src, $p_dest)) { |
||
3445 | $v_result = 0; |
||
3446 | } elseif (!@unlink($p_src)) { |
||
3447 | $v_result = 0; |
||
3448 | } |
||
3449 | } |
||
3450 | |||
3451 | // ----- Return |
||
3452 | return $v_result; |
||
3453 | } |
||
3454 | // --------------------------------------------------------------------------- |
||
3455 | |||
3456 | // --------------------------------------------------------------------------- |
||
3457 | // Function : $this->_tool_TranslateWinPath() |
||
3458 | // Description : |
||
3459 | // Translate windows path by replacing '\' by '/' and optionally removing |
||
3460 | // drive letter. |
||
3461 | // Parameters : |
||
3462 | // $p_path : path to translate. |
||
3463 | // $p_remove_disk_letter : true | false |
||
3464 | // Return Values : |
||
3465 | // The path translated. |
||
3466 | // --------------------------------------------------------------------------- |
||
3467 | /** |
||
3468 | * _tool_TranslateWinPath() |
||
3469 | * |
||
3470 | * { Description } |
||
3471 | * |
||
3472 | * @param [type] $p_remove_disk_letter |
||
3473 | */ |
||
3474 | public function _tool_TranslateWinPath($p_path, $p_remove_disk_letter=true) |
||
3475 | { |
||
3476 | if (stristr(php_uname(), 'windows')) { |
||
3477 | // ----- Look for potential disk letter |
||
3478 | if ($p_remove_disk_letter |
||
3479 | && (($v_position = strpos($p_path, ':')) != false)) { |
||
3480 | $p_path = substr($p_path, $v_position+1); |
||
3481 | } |
||
3482 | // ----- Change potential windows directory separator |
||
3483 | if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) { |
||
3484 | $p_path = strtr($p_path, '\\', '/'); |
||
3485 | } |
||
3486 | } |
||
3487 | return $p_path; |
||
3488 | } |
||
3489 | // --------------------------------------------------------------------------- |
||
3490 | } |
||
3491 | // End of class |
||
3492 | |||
3493 |
If you suppress an error, we recommend checking for the error condition explicitly: