PluginProbe
WP Database Backup – Unlimited Database & Files Backup by Backup for WP / 6.11
WP Database Backup – Unlimited Database & Files Backup by Backup for WP v6.11
7.13 7.12 trunk 1.1 2.1.1 5.9 6.0 6.1 6.10 6.11 6.12 6.12.1 6.2 6.3 6.4 6.5 6.5.1 6.6 6.7 6.8 6.9 7.0 7.0.1 7.1 7.10 All 34 releases
wp-database-backup / includes / admin / lib / class-pclzip.php

class-pclzip.php in WP Database Backup – Unlimited Database & Files Backup by Backup for WP 6.11, at includes/admin/lib/class-pclzip.php

5,652 lines 195.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // --------------------------------------------------------------------------------
3 // PhpConcept Library - Zip Module 2.8.2
4 // --------------------------------------------------------------------------------
5 // License GNU/LGPL - Vincent Blavet - August 2009
6 // http://www.phpconcept.net
7 // --------------------------------------------------------------------------------
8 //
9 // Presentation :
10 // PclZip is a PHP library that manage ZIP archives.
11 // So far tests show that archives generated by PclZip are readable by
12 // WinZip application and other tools.
13 //
14 // Description :
15 // See readme.txt and http://www.phpconcept.net
16 //
17 // Warning :
18 // This library and the associated files are non commercial, non professional
19 // work.
20 // It should not have unexpected results. However if any damage is caused by
21 // this software the author can not be responsible.
22 // The use of this software is at the risk of the user.
23 //
24 // --------------------------------------------------------------------------------
25 // $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
26 // --------------------------------------------------------------------------------
27
28 // ----- Constants
29 if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
30 define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
31 }
32
33 // ----- File list separator
34 // In version 1.x of PclZip, the separator for file list is a space
35 // (which is not a very smart choice, specifically for windows paths !).
36 // A better separator should be a comma (,). This constant gives you the
37 // abilty to change that.
38 // However notice that changing this value, may have impact on existing
39 // scripts, using space separated filenames.
40 // Recommanded values for compatibility with older versions :
41 //define( 'PCLZIP_SEPARATOR', ' ' );
42 // Recommanded values for smart separation of filenames.
43 if (!defined('PCLZIP_SEPARATOR')) {
44 define( 'PCLZIP_SEPARATOR', ',' );
45 }
46
47 // ----- Error configuration
48 // 0 : PclZip Class integrated error handling
49 // 1 : PclError external library error handling. By enabling this
50 // you must ensure that you have included PclError library.
51 // [2,...] : reserved for futur use
52 if (!defined('PCLZIP_ERROR_EXTERNAL')) {
53 define( 'PCLZIP_ERROR_EXTERNAL', 0 );
54 }
55
56 // ----- Optional static temporary directory
57 // By default temporary files are generated in the script current
58 // path.
59 // If defined :
60 // - MUST BE terminated by a '/'.
61 // - MUST be a valid, already created directory
62 // Samples :
63 // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
64 // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
65 if (!defined('PCLZIP_TEMPORARY_DIR')) {
66 define( 'PCLZIP_TEMPORARY_DIR', '' );
67 }
68
69 // ----- Optional threshold ratio for use of temporary files
70 // Pclzip sense the size of the file to add/extract and decide to
71 // use or not temporary file. The algorythm is looking for
72 // memory_limit of PHP and apply a ratio.
73 // threshold = memory_limit * ratio.
74 // Recommended values are under 0.5. Default 0.47.
75 // Samples :
76 // define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 );
77 if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) {
78 define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 );
79 }
80
81 // --------------------------------------------------------------------------------
82 // ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
83 // --------------------------------------------------------------------------------
84
85 // ----- Global variables
86 $g_pclzip_version = "2.8.2";
87
88 // ----- Error codes
89 // -1 : Unable to open file in binary write mode
90 // -2 : Unable to open file in binary read mode
91 // -3 : Invalid parameters
92 // -4 : File does not exist
93 // -5 : Filename is too long (max. 255)
94 // -6 : Not a valid zip file
95 // -7 : Invalid extracted file size
96 // -8 : Unable to create directory
97 // -9 : Invalid archive extension
98 // -10 : Invalid archive format
99 // -11 : Unable to delete file (unlink)
100 // -12 : Unable to rename file (rename)
101 // -13 : Invalid header checksum
102 // -14 : Invalid archive size
103 define( 'PCLZIP_ERR_USER_ABORTED', 2 );
104 define( 'PCLZIP_ERR_NO_ERROR', 0 );
105 define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
106 define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
107 define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
108 define( 'PCLZIP_ERR_MISSING_FILE', -4 );
109 define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
110 define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
111 define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
112 define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
113 define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
114 define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
115 define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
116 define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
117 define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
118 define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
119 define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
120 define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
121 define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
122 define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
123 define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
124 define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
125 define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
126
127 // ----- Options values
128 define( 'PCLZIP_OPT_PATH', 77001 );
129 define( 'PCLZIP_OPT_ADD_PATH', 77002 );
130 define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
131 define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
132 define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
133 define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
134 define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
135 define( 'PCLZIP_OPT_BY_NAME', 77008 );
136 define( 'PCLZIP_OPT_BY_INDEX', 77009 );
137 define( 'PCLZIP_OPT_BY_EREG', 77010 );
138 define( 'PCLZIP_OPT_BY_PREG', 77011 );
139 define( 'PCLZIP_OPT_COMMENT', 77012 );
140 define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
141 define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
142 define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
143 define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
144 define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
145 // Having big trouble with crypt. Need to multiply 2 long int
146 // which is not correctly supported by PHP ...
147 //define( 'PCLZIP_OPT_CRYPT', 77018 );
148 define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
149 define( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 );
150 define( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias
151 define( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 );
152 define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
153 define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
154 define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
155
156 // ----- File description attributes
157 define( 'PCLZIP_ATT_FILE_NAME', 79001 );
158 define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
159 define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
160 define( 'PCLZIP_ATT_FILE_MTIME', 79004 );
161 define( 'PCLZIP_ATT_FILE_CONTENT', 79005 );
162 define( 'PCLZIP_ATT_FILE_COMMENT', 79006 );
163
164 // ----- Call backs values
165 define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
166 define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
167 define( 'PCLZIP_CB_PRE_ADD', 78003 );
168 define( 'PCLZIP_CB_POST_ADD', 78004 );
169
170 // --------------------------------------------------------------------------------
171 // Class : PclZip
172 // Description :
173 // PclZip is the class that represent a Zip archive.
174 // The public methods allow the manipulation of the archive.
175 // Attributes :
176 // Attributes must not be accessed directly.
177 // Methods :
178 // PclZip() : Object creator
179 // create() : Creates the Zip archive
180 // listContent() : List the content of the Zip archive
181 // extract() : Extract the content of the archive
182 // properties() : List the properties of the archive
183 // --------------------------------------------------------------------------------
184 class PclZip
185 {
186 // ----- Filename of the zip file
187 var $zipname = '';
188
189 // ----- File descriptor of the zip file
190 var $zip_fd = 0;
191
192 // ----- Internal error handling
193 var $error_code = 1;
194 var $error_string = '';
195
196 // ----- Current status of the magic_quotes_runtime
197 // This value store the php configuration for magic_quotes
198 // The class can then disable the magic_quotes and reset it after
199 var $magic_quotes_status;
200
201 // --------------------------------------------------------------------------------
202 // Function : PclZip()
203 // Description :
204 // Creates a PclZip object and set the name of the associated Zip archive
205 // filename.
206 // Note that no real action is taken, if the archive does not exist it is not
207 // created. Use create() for that.
208 // --------------------------------------------------------------------------------
209 function PclZip($p_zipname)
210 {
211
212 // ----- Tests the zlib
213 if (!function_exists('gzopen'))
214 {
215 wp_die(esc_html__('Abort','wpdbbkp').basename(__FILE__).esc_html__(' : Missing zlib extensions','wpdbbkp'));
216 }
217
218 // ----- Set the attributes
219 $this->zipname = $p_zipname;
220 $this->zip_fd = 0;
221 $this->magic_quotes_status = -1;
222
223 // ----- Return
224 return;
225 }
226 // --------------------------------------------------------------------------------
227
228 // --------------------------------------------------------------------------------
229 // Function :
230 // create($p_filelist, $p_add_dir="", $p_remove_dir="")
231 // create($p_filelist, $p_option, $p_option_value, ...)
232 // Description :
233 // This method supports two different synopsis. The first one is historical.
234 // This method creates a Zip Archive. The Zip file is created in the
235 // filesystem. The files and directories indicated in $p_filelist
236 // are added in the archive. See the parameters description for the
237 // supported format of $p_filelist.
238 // When a directory is in the list, the directory and its content is added
239 // in the archive.
240 // In this synopsis, the function takes an optional variable list of
241 // options. See bellow the supported options.
242 // Parameters :
243 // $p_filelist : An array containing file or directory names, or
244 // a string containing one filename or one directory name, or
245 // a string containing a list of filenames and/or directory
246 // names separated by spaces.
247 // $p_add_dir : A path to add before the real path of the archived file,
248 // in order to have it memorized in the archive.
249 // $p_remove_dir : A path to remove from the real path of the file to archive,
250 // in order to have a shorter path memorized in the archive.
251 // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
252 // is removed first, before $p_add_dir is added.
253 // Options :
254 // PCLZIP_OPT_ADD_PATH :
255 // PCLZIP_OPT_REMOVE_PATH :
256 // PCLZIP_OPT_REMOVE_ALL_PATH :
257 // PCLZIP_OPT_COMMENT :
258 // PCLZIP_CB_PRE_ADD :
259 // PCLZIP_CB_POST_ADD :
260 // Return Values :
261 // 0 on failure,
262 // The list of the added files, with a status of the add action.
263 // (see PclZip::listContent() for list entry format)
264 // --------------------------------------------------------------------------------
265 function create($p_filelist)
266 {
267 $v_result=1;
268
269 // ----- Reset the error handler
270 $this->privErrorReset();
271
272 // ----- Set default values
273 $v_options = array();
274 $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
275
276 // ----- Look for variable options arguments
277 $v_size = func_num_args();
278
279 // ----- Look for arguments
280 if ($v_size > 1) {
281 // ----- Get the arguments
282 $v_arg_list = func_get_args();
283
284 // ----- Remove from the options list the first argument
285 array_shift($v_arg_list);
286 $v_size--;
287
288 // ----- Look for first arg
289 if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
290
291 // ----- Parse the options
292 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
293 array (PCLZIP_OPT_REMOVE_PATH => 'optional',
294 PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
295 PCLZIP_OPT_ADD_PATH => 'optional',
296 PCLZIP_CB_PRE_ADD => 'optional',
297 PCLZIP_CB_POST_ADD => 'optional',
298 PCLZIP_OPT_NO_COMPRESSION => 'optional',
299 PCLZIP_OPT_COMMENT => 'optional',
300 PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
301 PCLZIP_OPT_TEMP_FILE_ON => 'optional',
302 PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
303 //, PCLZIP_OPT_CRYPT => 'optional'
304 ));
305 if ($v_result != 1) {
306 return 0;
307 }
308 }
309
310 // ----- Look for 2 args
311 // Here we need to support the first historic synopsis of the
312 // method.
313 else {
314
315 // ----- Get the first argument
316 $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
317
318 // ----- Look for the optional second argument
319 if ($v_size == 2) {
320 $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
321 }
322 else if ($v_size > 2) {
323 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
324 "Invalid number / type of arguments");
325 return 0;
326 }
327 }
328 }
329
330 // ----- Look for default option values
331 $this->privOptionDefaultThreshold($v_options);
332
333 // ----- Init
334 $v_string_list = array();
335 $v_att_list = array();
336 $v_filedescr_list = array();
337 $p_result_list = array();
338
339 // ----- Look if the $p_filelist is really an array
340 if (is_array($p_filelist)) {
341
342 // ----- Look if the first element is also an array
343 // This will mean that this is a file description entry
344 if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
345 $v_att_list = $p_filelist;
346 }
347
348 // ----- The list is a list of string names
349 else {
350 $v_string_list = $p_filelist;
351 }
352 }
353
354 // ----- Look if the $p_filelist is a string
355 else if (is_string($p_filelist)) {
356 // ----- Create a list from the string
357 $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
358 }
359
360 // ----- Invalid variable type for $p_filelist
361 else {
362 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
363 return 0;
364 }
365
366 // ----- Reformat the string list
367 if (sizeof($v_string_list) != 0) {
368 foreach ($v_string_list as $v_string) {
369 if ($v_string != '') {
370 $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
371 }
372 else {
373 }
374 }
375 }
376
377 // ----- For each file in the list check the attributes
378 $v_supported_attributes
379 = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
380 ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
381 ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
382 ,PCLZIP_ATT_FILE_MTIME => 'optional'
383 ,PCLZIP_ATT_FILE_CONTENT => 'optional'
384 ,PCLZIP_ATT_FILE_COMMENT => 'optional'
385 );
386 foreach ($v_att_list as $v_entry) {
387 $v_result = $this->privFileDescrParseAtt($v_entry,
388 $v_filedescr_list[],
389 $v_options,
390 $v_supported_attributes);
391 if ($v_result != 1) {
392 return 0;
393 }
394 }
395
396 // ----- Expand the filelist (expand directories)
397 $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
398 if ($v_result != 1) {
399 return 0;
400 }
401
402 // ----- Call the create fct
403 $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
404 if ($v_result != 1) {
405 return 0;
406 }
407
408 // ----- Return
409 return $p_result_list;
410 }
411 // --------------------------------------------------------------------------------
412
413 // --------------------------------------------------------------------------------
414 // Function :
415 // add($p_filelist, $p_add_dir="", $p_remove_dir="")
416 // add($p_filelist, $p_option, $p_option_value, ...)
417 // Description :
418 // This method supports two synopsis. The first one is historical.
419 // This methods add the list of files in an existing archive.
420 // If a file with the same name already exists, it is added at the end of the
421 // archive, the first one is still present.
422 // If the archive does not exist, it is created.
423 // Parameters :
424 // $p_filelist : An array containing file or directory names, or
425 // a string containing one filename or one directory name, or
426 // a string containing a list of filenames and/or directory
427 // names separated by spaces.
428 // $p_add_dir : A path to add before the real path of the archived file,
429 // in order to have it memorized in the archive.
430 // $p_remove_dir : A path to remove from the real path of the file to archive,
431 // in order to have a shorter path memorized in the archive.
432 // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
433 // is removed first, before $p_add_dir is added.
434 // Options :
435 // PCLZIP_OPT_ADD_PATH :
436 // PCLZIP_OPT_REMOVE_PATH :
437 // PCLZIP_OPT_REMOVE_ALL_PATH :
438 // PCLZIP_OPT_COMMENT :
439 // PCLZIP_OPT_ADD_COMMENT :
440 // PCLZIP_OPT_PREPEND_COMMENT :
441 // PCLZIP_CB_PRE_ADD :
442 // PCLZIP_CB_POST_ADD :
443 // Return Values :
444 // 0 on failure,
445 // The list of the added files, with a status of the add action.
446 // (see PclZip::listContent() for list entry format)
447 // --------------------------------------------------------------------------------
448 function add($p_filelist)
449 {
450 $v_result=1;
451
452 // ----- Reset the error handler
453 $this->privErrorReset();
454
455 // ----- Set default values
456 $v_options = array();
457 $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
458
459 // ----- Look for variable options arguments
460 $v_size = func_num_args();
461
462 // ----- Look for arguments
463 if ($v_size > 1) {
464 // ----- Get the arguments
465 $v_arg_list = func_get_args();
466
467 // ----- Remove form the options list the first argument
468 array_shift($v_arg_list);
469 $v_size--;
470
471 // ----- Look for first arg
472 if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
473
474 // ----- Parse the options
475 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
476 array (PCLZIP_OPT_REMOVE_PATH => 'optional',
477 PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
478 PCLZIP_OPT_ADD_PATH => 'optional',
479 PCLZIP_CB_PRE_ADD => 'optional',
480 PCLZIP_CB_POST_ADD => 'optional',
481 PCLZIP_OPT_NO_COMPRESSION => 'optional',
482 PCLZIP_OPT_COMMENT => 'optional',
483 PCLZIP_OPT_ADD_COMMENT => 'optional',
484 PCLZIP_OPT_PREPEND_COMMENT => 'optional',
485 PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
486 PCLZIP_OPT_TEMP_FILE_ON => 'optional',
487 PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
488 //, PCLZIP_OPT_CRYPT => 'optional'
489 ));
490 if ($v_result != 1) {
491 return 0;
492 }
493 }
494
495 // ----- Look for 2 args
496 // Here we need to support the first historic synopsis of the
497 // method.
498 else {
499
500 // ----- Get the first argument
501 $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
502
503 // ----- Look for the optional second argument
504 if ($v_size == 2) {
505 $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
506 }
507 else if ($v_size > 2) {
508 // ----- Error log
509 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
510
511 // ----- Return
512 return 0;
513 }
514 }
515 }
516
517 // ----- Look for default option values
518 $this->privOptionDefaultThreshold($v_options);
519
520 // ----- Init
521 $v_string_list = array();
522 $v_att_list = array();
523 $v_filedescr_list = array();
524 $p_result_list = array();
525
526 // ----- Look if the $p_filelist is really an array
527 if (is_array($p_filelist)) {
528
529 // ----- Look if the first element is also an array
530 // This will mean that this is a file description entry
531 if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
532 $v_att_list = $p_filelist;
533 }
534
535 // ----- The list is a list of string names
536 else {
537 $v_string_list = $p_filelist;
538 }
539 }
540
541 // ----- Look if the $p_filelist is a string
542 else if (is_string($p_filelist)) {
543 // ----- Create a list from the string
544 $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
545 }
546
547 // ----- Invalid variable type for $p_filelist
548 else {
549 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
550 return 0;
551 }
552
553 // ----- Reformat the string list
554 if (sizeof($v_string_list) != 0) {
555 foreach ($v_string_list as $v_string) {
556 $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
557 }
558 }
559
560 // ----- For each file in the list check the attributes
561 $v_supported_attributes
562 = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
563 ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
564 ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
565 ,PCLZIP_ATT_FILE_MTIME => 'optional'
566 ,PCLZIP_ATT_FILE_CONTENT => 'optional'
567 ,PCLZIP_ATT_FILE_COMMENT => 'optional'
568 );
569 foreach ($v_att_list as $v_entry) {
570 $v_result = $this->privFileDescrParseAtt($v_entry,
571 $v_filedescr_list[],
572 $v_options,
573 $v_supported_attributes);
574 if ($v_result != 1) {
575 return 0;
576 }
577 }
578
579 // ----- Expand the filelist (expand directories)
580 $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
581 if ($v_result != 1) {
582 return 0;
583 }
584
585 // ----- Call the create fct
586 $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
587 if ($v_result != 1) {
588 return 0;
589 }
590
591 // ----- Return
592 return $p_result_list;
593 }
594 // --------------------------------------------------------------------------------
595
596 // --------------------------------------------------------------------------------
597 // Function : listContent()
598 // Description :
599 // This public method, gives the list of the files and directories, with their
600 // properties.
601 // The properties of each entries in the list are (used also in other functions) :
602 // filename : Name of the file. For a create or add action it is the filename
603 // given by the user. For an extract function it is the filename
604 // of the extracted file.
605 // stored_filename : Name of the file / directory stored in the archive.
606 // size : Size of the stored file.
607 // compressed_size : Size of the file's data compressed in the archive
608 // (without the headers overhead)
609 // mtime : Last known modification date of the file (UNIX timestamp)
610 // comment : Comment associated with the file
611 // folder : true | false
612 // index : index of the file in the archive
613 // status : status of the action (depending of the action) :
614 // Values are :
615 // ok : OK !
616 // filtered : the file / dir is not extracted (filtered by user)
617 // already_a_directory : the file can not be extracted because a
618 // directory with the same name already exists
619 // write_protected : the file can not be extracted because a file
620 // with the same name already exists and is
621 // write protected
622 // newer_exist : the file was not extracted because a newer file exists
623 // path_creation_fail : the file is not extracted because the folder
624 // does not exist and can not be created
625 // write_error : the file was not extracted because there was a
626 // error while writing the file
627 // read_error : the file was not extracted because there was a error
628 // while reading the file
629 // invalid_header : the file was not extracted because of an archive
630 // format error (bad file header)
631 // Note that each time a method can continue operating when there
632 // is an action error on a file, the error is only logged in the file status.
633 // Return Values :
634 // 0 on an unrecoverable failure,
635 // The list of the files in the archive.
636 // --------------------------------------------------------------------------------
637 function listContent()
638 {
639 $v_result=1;
640
641 // ----- Reset the error handler
642 $this->privErrorReset();
643
644 // ----- Check archive
645 if (!$this->privCheckFormat()) {
646 return(0);
647 }
648
649 // ----- Call the extracting fct
650 $p_list = array();
651 if (($v_result = $this->privList($p_list)) != 1)
652 {
653 unset($p_list);
654 return(0);
655 }
656
657 // ----- Return
658 return $p_list;
659 }
660 // --------------------------------------------------------------------------------
661
662 // --------------------------------------------------------------------------------
663 // Function :
664 // extract($p_path="./", $p_remove_path="")
665 // extract([$p_option, $p_option_value, ...])
666 // Description :
667 // This method supports two synopsis. The first one is historical.
668 // This method extract all the files / directories from the archive to the
669 // folder indicated in $p_path.
670 // If you want to ignore the 'root' part of path of the memorized files
671 // you can indicate this in the optional $p_remove_path parameter.
672 // By default, if a newer file with the same name already exists, the
673 // file is not extracted.
674 //
675 // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
676 // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
677 // at the end of the path value of PCLZIP_OPT_PATH.
678 // Parameters :
679 // $p_path : Path where the files and directories are to be extracted
680 // $p_remove_path : First part ('root' part) of the memorized path
681 // (if any similar) to remove while extracting.
682 // Options :
683 // PCLZIP_OPT_PATH :
684 // PCLZIP_OPT_ADD_PATH :
685 // PCLZIP_OPT_REMOVE_PATH :
686 // PCLZIP_OPT_REMOVE_ALL_PATH :
687 // PCLZIP_CB_PRE_EXTRACT :
688 // PCLZIP_CB_POST_EXTRACT :
689 // Return Values :
690 // 0 or a negative value on failure,
691 // The list of the extracted files, with a status of the action.
692 // (see PclZip::listContent() for list entry format)
693 // --------------------------------------------------------------------------------
694 function extract()
695 {
696 $v_result=1;
697
698 // ----- Reset the error handler
699 $this->privErrorReset();
700
701 // ----- Check archive
702 if (!$this->privCheckFormat()) {
703 return(0);
704 }
705
706 // ----- Set default values
707 $v_options = array();
708 // $v_path = "./";
709 $v_path = '';
710 $v_remove_path = "";
711 $v_remove_all_path = false;
712
713 // ----- Look for variable options arguments
714 $v_size = func_num_args();
715
716 // ----- Default values for option
717 $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
718
719 // ----- Look for arguments
720 if ($v_size > 0) {
721 // ----- Get the arguments
722 $v_arg_list = func_get_args();
723
724 // ----- Look for first arg
725 if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
726
727 // ----- Parse the options
728 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
729 array (PCLZIP_OPT_PATH => 'optional',
730 PCLZIP_OPT_REMOVE_PATH => 'optional',
731 PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
732 PCLZIP_OPT_ADD_PATH => 'optional',
733 PCLZIP_CB_PRE_EXTRACT => 'optional',
734 PCLZIP_CB_POST_EXTRACT => 'optional',
735 PCLZIP_OPT_SET_CHMOD => 'optional',
736 PCLZIP_OPT_BY_NAME => 'optional',
737 PCLZIP_OPT_BY_EREG => 'optional',
738 PCLZIP_OPT_BY_PREG => 'optional',
739 PCLZIP_OPT_BY_INDEX => 'optional',
740 PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
741 PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
742 PCLZIP_OPT_REPLACE_NEWER => 'optional'
743 ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
744 ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
745 PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
746 PCLZIP_OPT_TEMP_FILE_ON => 'optional',
747 PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
748 ));
749 if ($v_result != 1) {
750 return 0;
751 }
752
753 // ----- Set the arguments
754 if (isset($v_options[PCLZIP_OPT_PATH])) {
755 $v_path = $v_options[PCLZIP_OPT_PATH];
756 }
757 if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
758 $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
759 }
760 if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
761 $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
762 }
763 if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
764 // ----- Check for '/' in last path char
765 if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
766 $v_path .= '/';
767 }
768 $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
769 }
770 }
771
772 // ----- Look for 2 args
773 // Here we need to support the first historic synopsis of the
774 // method.
775 else {
776
777 // ----- Get the first argument
778 $v_path = $v_arg_list[0];
779
780 // ----- Look for the optional second argument
781 if ($v_size == 2) {
782 $v_remove_path = $v_arg_list[1];
783 }
784 else if ($v_size > 2) {
785 // ----- Error log
786 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
787
788 // ----- Return
789 return 0;
790 }
791 }
792 }
793
794 // ----- Look for default option values
795 $this->privOptionDefaultThreshold($v_options);
796
797 // ----- Trace
798
799 // ----- Call the extracting fct
800 $p_list = array();
801 $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
802 $v_remove_all_path, $v_options);
803 if ($v_result < 1) {
804 unset($p_list);
805 return(0);
806 }
807
808 // ----- Return
809 return $p_list;
810 }
811 // --------------------------------------------------------------------------------
812
813
814 // --------------------------------------------------------------------------------
815 // Function :
816 // extractByIndex($p_index, $p_path="./", $p_remove_path="")
817 // extractByIndex($p_index, [$p_option, $p_option_value, ...])
818 // Description :
819 // This method supports two synopsis. The first one is historical.
820 // This method is doing a partial extract of the archive.
821 // The extracted files or folders are identified by their index in the
822 // archive (from 0 to n).
823 // Note that if the index identify a folder, only the folder entry is
824 // extracted, not all the files included in the archive.
825 // Parameters :
826 // $p_index : A single index (integer) or a string of indexes of files to
827 // extract. The form of the string is "0,4-6,8-12" with only numbers
828 // and '-' for range or ',' to separate ranges. No spaces or ';'
829 // are allowed.
830 // $p_path : Path where the files and directories are to be extracted
831 // $p_remove_path : First part ('root' part) of the memorized path
832 // (if any similar) to remove while extracting.
833 // Options :
834 // PCLZIP_OPT_PATH :
835 // PCLZIP_OPT_ADD_PATH :
836 // PCLZIP_OPT_REMOVE_PATH :
837 // PCLZIP_OPT_REMOVE_ALL_PATH :
838 // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
839 // not as files.
840 // The resulting content is in a new field 'content' in the file
841 // structure.
842 // This option must be used alone (any other options are ignored).
843 // PCLZIP_CB_PRE_EXTRACT :
844 // PCLZIP_CB_POST_EXTRACT :
845 // Return Values :
846 // 0 on failure,
847 // The list of the extracted files, with a status of the action.
848 // (see PclZip::listContent() for list entry format)
849 // --------------------------------------------------------------------------------
850 //function extractByIndex($p_index, options...)
851 function extractByIndex($p_index)
852 {
853 $v_result=1;
854
855 // ----- Reset the error handler
856 $this->privErrorReset();
857
858 // ----- Check archive
859 if (!$this->privCheckFormat()) {
860 return(0);
861 }
862
863 // ----- Set default values
864 $v_options = array();
865 // $v_path = "./";
866 $v_path = '';
867 $v_remove_path = "";
868 $v_remove_all_path = false;
869
870 // ----- Look for variable options arguments
871 $v_size = func_num_args();
872
873 // ----- Default values for option
874 $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
875
876 // ----- Look for arguments
877 if ($v_size > 1) {
878 // ----- Get the arguments
879 $v_arg_list = func_get_args();
880
881 // ----- Remove form the options list the first argument
882 array_shift($v_arg_list);
883 $v_size--;
884
885 // ----- Look for first arg
886 if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
887
888 // ----- Parse the options
889 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
890 array (PCLZIP_OPT_PATH => 'optional',
891 PCLZIP_OPT_REMOVE_PATH => 'optional',
892 PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
893 PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
894 PCLZIP_OPT_ADD_PATH => 'optional',
895 PCLZIP_CB_PRE_EXTRACT => 'optional',
896 PCLZIP_CB_POST_EXTRACT => 'optional',
897 PCLZIP_OPT_SET_CHMOD => 'optional',
898 PCLZIP_OPT_REPLACE_NEWER => 'optional'
899 ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
900 ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
901 PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
902 PCLZIP_OPT_TEMP_FILE_ON => 'optional',
903 PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
904 ));
905 if ($v_result != 1) {
906 return 0;
907 }
908
909 // ----- Set the arguments
910 if (isset($v_options[PCLZIP_OPT_PATH])) {
911 $v_path = $v_options[PCLZIP_OPT_PATH];
912 }
913 if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
914 $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
915 }
916 if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
917 $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
918 }
919 if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
920 // ----- Check for '/' in last path char
921 if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
922 $v_path .= '/';
923 }
924 $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
925 }
926 if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
927 $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
928 }
929 else {
930 }
931 }
932
933 // ----- Look for 2 args
934 // Here we need to support the first historic synopsis of the
935 // method.
936 else {
937
938 // ----- Get the first argument
939 $v_path = $v_arg_list[0];
940
941 // ----- Look for the optional second argument
942 if ($v_size == 2) {
943 $v_remove_path = $v_arg_list[1];
944 }
945 else if ($v_size > 2) {
946 // ----- Error log
947 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
948
949 // ----- Return
950 return 0;
951 }
952 }
953 }
954
955 // ----- Trace
956
957 // ----- Trick
958 // Here I want to reuse extractByRule(), so I need to parse the $p_index
959 // with privParseOptions()
960 $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
961 $v_options_trick = array();
962 $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
963 array (PCLZIP_OPT_BY_INDEX => 'optional' ));
964 if ($v_result != 1) {
965 return 0;
966 }
967 $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
968
969 // ----- Look for default option values
970 $this->privOptionDefaultThreshold($v_options);
971
972 // ----- Call the extracting fct
973 if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
974 return(0);
975 }
976
977 // ----- Return
978 return $p_list;
979 }
980 // --------------------------------------------------------------------------------
981
982 // --------------------------------------------------------------------------------
983 // Function :
984 // delete([$p_option, $p_option_value, ...])
985 // Description :
986 // This method removes files from the archive.
987 // If no parameters are given, then all the archive is emptied.
988 // Parameters :
989 // None or optional arguments.
990 // Options :
991 // PCLZIP_OPT_BY_INDEX :
992 // PCLZIP_OPT_BY_NAME :
993 // PCLZIP_OPT_BY_EREG :
994 // PCLZIP_OPT_BY_PREG :
995 // Return Values :
996 // 0 on failure,
997 // The list of the files which are still present in the archive.
998 // (see PclZip::listContent() for list entry format)
999 // --------------------------------------------------------------------------------
1000 function delete()
1001 {
1002 $v_result=1;
1003
1004 // ----- Reset the error handler
1005 $this->privErrorReset();
1006
1007 // ----- Check archive
1008 if (!$this->privCheckFormat()) {
1009 return(0);
1010 }
1011
1012 // ----- Set default values
1013 $v_options = array();
1014
1015 // ----- Look for variable options arguments
1016 $v_size = func_num_args();
1017
1018 // ----- Look for arguments
1019 if ($v_size > 0) {
1020 // ----- Get the arguments
1021 $v_arg_list = func_get_args();
1022
1023 // ----- Parse the options
1024 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
1025 array (PCLZIP_OPT_BY_NAME => 'optional',
1026 PCLZIP_OPT_BY_EREG => 'optional',
1027 PCLZIP_OPT_BY_PREG => 'optional',
1028 PCLZIP_OPT_BY_INDEX => 'optional' ));
1029 if ($v_result != 1) {
1030 return 0;
1031 }
1032 }
1033
1034 // ----- Magic quotes trick
1035 $this->privDisableMagicQuotes();
1036
1037 // ----- Call the delete fct
1038 $v_list = array();
1039 if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
1040 $this->privSwapBackMagicQuotes();
1041 unset($v_list);
1042 return(0);
1043 }
1044
1045 // ----- Magic quotes trick
1046 $this->privSwapBackMagicQuotes();
1047
1048 // ----- Return
1049 return $v_list;
1050 }
1051 // --------------------------------------------------------------------------------
1052
1053 // --------------------------------------------------------------------------------
1054 // Function : deleteByIndex()
1055 // Description :
1056 // ***** Deprecated *****
1057 // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
1058 // --------------------------------------------------------------------------------
1059 function deleteByIndex($p_index)
1060 {
1061
1062 $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
1063
1064 // ----- Return
1065 return $p_list;
1066 }
1067 // --------------------------------------------------------------------------------
1068
1069 // --------------------------------------------------------------------------------
1070 // Function : properties()
1071 // Description :
1072 // This method gives the properties of the archive.
1073 // The properties are :
1074 // nb : Number of files in the archive
1075 // comment : Comment associated with the archive file
1076 // status : not_exist, ok
1077 // Parameters :
1078 // None
1079 // Return Values :
1080 // 0 on failure,
1081 // An array with the archive properties.
1082 // --------------------------------------------------------------------------------
1083 function properties()
1084 {
1085
1086 // ----- Reset the error handler
1087 $this->privErrorReset();
1088
1089 // ----- Magic quotes trick
1090 $this->privDisableMagicQuotes();
1091
1092 // ----- Check archive
1093 if (!$this->privCheckFormat()) {
1094 $this->privSwapBackMagicQuotes();
1095 return(0);
1096 }
1097
1098 // ----- Default properties
1099 $v_prop = array();
1100 $v_prop['comment'] = '';
1101 $v_prop['nb'] = 0;
1102 $v_prop['status'] = 'not_exist';
1103
1104 // ----- Look if file exists
1105 if (@is_file($this->zipname))
1106 {
1107 // ----- Open the zip file
1108 if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
1109 {
1110 $this->privSwapBackMagicQuotes();
1111
1112 // ----- Error log
1113 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
1114
1115 // ----- Return
1116 return 0;
1117 }
1118
1119 // ----- Read the central directory informations
1120 $v_central_dir = array();
1121 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
1122 {
1123 $this->privSwapBackMagicQuotes();
1124 return 0;
1125 }
1126
1127 // ----- Close the zip file
1128 $this->privCloseFd();
1129
1130 // ----- Set the user attributes
1131 $v_prop['comment'] = $v_central_dir['comment'];
1132 $v_prop['nb'] = $v_central_dir['entries'];
1133 $v_prop['status'] = 'ok';
1134 }
1135
1136 // ----- Magic quotes trick
1137 $this->privSwapBackMagicQuotes();
1138
1139 // ----- Return
1140 return $v_prop;
1141 }
1142 // --------------------------------------------------------------------------------
1143
1144 // --------------------------------------------------------------------------------
1145 // Function : duplicate()
1146 // Description :
1147 // This method creates an archive by copying the content of an other one. If
1148 // the archive already exist, it is replaced by the new one without any warning.
1149 // Parameters :
1150 // $p_archive : The filename of a valid archive, or
1151 // a valid PclZip object.
1152 // Return Values :
1153 // 1 on success.
1154 // 0 or a negative value on error (error code).
1155 // --------------------------------------------------------------------------------
1156 function duplicate($p_archive)
1157 {
1158 $v_result = 1;
1159
1160 // ----- Reset the error handler
1161 $this->privErrorReset();
1162
1163 // ----- Look if the $p_archive is a PclZip object
1164 if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
1165 {
1166
1167 // ----- Duplicate the archive
1168 $v_result = $this->privDuplicate($p_archive->zipname);
1169 }
1170
1171 // ----- Look if the $p_archive is a string (so a filename)
1172 else if (is_string($p_archive))
1173 {
1174
1175 // ----- Check that $p_archive is a valid zip file
1176 // TBC : Should also check the archive format
1177 if (!is_file($p_archive)) {
1178 // ----- Error log
1179 PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
1180 $v_result = PCLZIP_ERR_MISSING_FILE;
1181 }
1182 else {
1183 // ----- Duplicate the archive
1184 $v_result = $this->privDuplicate($p_archive);
1185 }
1186 }
1187
1188 // ----- Invalid variable
1189 else
1190 {
1191 // ----- Error log
1192 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1193 $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1194 }
1195
1196 // ----- Return
1197 return $v_result;
1198 }
1199 // --------------------------------------------------------------------------------
1200
1201 // --------------------------------------------------------------------------------
1202 // Function : merge()
1203 // Description :
1204 // This method merge the $p_archive_to_add archive at the end of the current
1205 // one ($this).
1206 // If the archive ($this) does not exist, the merge becomes a duplicate.
1207 // If the $p_archive_to_add archive does not exist, the merge is a success.
1208 // Parameters :
1209 // $p_archive_to_add : It can be directly the filename of a valid zip archive,
1210 // or a PclZip object archive.
1211 // Return Values :
1212 // 1 on success,
1213 // 0 or negative values on error (see below).
1214 // --------------------------------------------------------------------------------
1215 function merge($p_archive_to_add)
1216 {
1217 $v_result = 1;
1218
1219 // ----- Reset the error handler
1220 $this->privErrorReset();
1221
1222 // ----- Check archive
1223 if (!$this->privCheckFormat()) {
1224 return(0);
1225 }
1226
1227 // ----- Look if the $p_archive_to_add is a PclZip object
1228 if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
1229 {
1230
1231 // ----- Merge the archive
1232 $v_result = $this->privMerge($p_archive_to_add);
1233 }
1234
1235 // ----- Look if the $p_archive_to_add is a string (so a filename)
1236 else if (is_string($p_archive_to_add))
1237 {
1238
1239 // ----- Create a temporary archive
1240 $v_object_archive = new PclZip($p_archive_to_add);
1241
1242 // ----- Merge the archive
1243 $v_result = $this->privMerge($v_object_archive);
1244 }
1245
1246 // ----- Invalid variable
1247 else
1248 {
1249 // ----- Error log
1250 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1251 $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1252 }
1253
1254 // ----- Return
1255 return $v_result;
1256 }
1257 // --------------------------------------------------------------------------------
1258
1259
1260
1261 // --------------------------------------------------------------------------------
1262 // Function : errorCode()
1263 // Description :
1264 // Parameters :
1265 // --------------------------------------------------------------------------------
1266 function errorCode()
1267 {
1268 if (PCLZIP_ERROR_EXTERNAL == 1) {
1269 return(PclErrorCode());
1270 }
1271 else {
1272 return($this->error_code);
1273 }
1274 }
1275 // --------------------------------------------------------------------------------
1276
1277 // --------------------------------------------------------------------------------
1278 // Function : errorName()
1279 // Description :
1280 // Parameters :
1281 // --------------------------------------------------------------------------------
1282 function errorName($p_with_code=false)
1283 {
1284 $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
1285 PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
1286 PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
1287 PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
1288 PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
1289 PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
1290 PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
1291 PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
1292 PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
1293 PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
1294 PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
1295 PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
1296 PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
1297 PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
1298 PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1299 PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
1300 PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
1301 PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
1302 PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
1303 ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
1304 ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
1305 );
1306
1307 if (isset($v_name[$this->error_code])) {
1308 $v_value = $v_name[$this->error_code];
1309 }
1310 else {
1311 $v_value = 'NoName';
1312 }
1313
1314 if ($p_with_code) {
1315 return($v_value.' ('.$this->error_code.')');
1316 }
1317 else {
1318 return($v_value);
1319 }
1320 }
1321 // --------------------------------------------------------------------------------
1322
1323 // --------------------------------------------------------------------------------
1324 // Function : errorInfo()
1325 // Description :
1326 // Parameters :
1327 // --------------------------------------------------------------------------------
1328 function errorInfo($p_full=false)
1329 {
1330 if (PCLZIP_ERROR_EXTERNAL == 1) {
1331 return(PclErrorString());
1332 }
1333 else {
1334 if ($p_full) {
1335 return($this->errorName(true)." : ".$this->error_string);
1336 }
1337 else {
1338 return($this->error_string." [code ".$this->error_code."]");
1339 }
1340 }
1341 }
1342 // --------------------------------------------------------------------------------
1343
1344
1345 // --------------------------------------------------------------------------------
1346 // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1347 // ***** *****
1348 // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
1349 // --------------------------------------------------------------------------------
1350
1351
1352
1353 // --------------------------------------------------------------------------------
1354 // Function : privCheckFormat()
1355 // Description :
1356 // This method check that the archive exists and is a valid zip archive.
1357 // Several level of check exists. (futur)
1358 // Parameters :
1359 // $p_level : Level of check. Default 0.
1360 // 0 : Check the first bytes (magic codes) (default value))
1361 // 1 : 0 + Check the central directory (futur)
1362 // 2 : 1 + Check each file header (futur)
1363 // Return Values :
1364 // true on success,
1365 // false on error, the error code is set.
1366 // --------------------------------------------------------------------------------
1367 function privCheckFormat($p_level=0)
1368 {
1369 $v_result = true;
1370
1371 // ----- Reset the file system cache
1372 clearstatcache();
1373
1374 // ----- Reset the error handler
1375 $this->privErrorReset();
1376
1377 // ----- Look if the file exits
1378 if (!is_file($this->zipname)) {
1379 // ----- Error log
1380 PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
1381 return(false);
1382 }
1383
1384 // ----- Check that the file is readeable
1385 if (!is_readable($this->zipname)) {
1386 // ----- Error log
1387 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
1388 return(false);
1389 }
1390
1391 // ----- Check the magic code
1392 // TBC
1393
1394 // ----- Check the central header
1395 // TBC
1396
1397 // ----- Check each file header
1398 // TBC
1399
1400 // ----- Return
1401 return $v_result;
1402 }
1403 // --------------------------------------------------------------------------------
1404
1405 // --------------------------------------------------------------------------------
1406 // Function : privParseOptions()
1407 // Description :
1408 // This internal methods reads the variable list of arguments ($p_options_list,
1409 // $p_size) and generate an array with the options and values ($v_result_list).
1410 // $v_requested_options contains the options that can be present and those that
1411 // must be present.
1412 // $v_requested_options is an array, with the option value as key, and 'optional',
1413 // or 'mandatory' as value.
1414 // Parameters :
1415 // See above.
1416 // Return Values :
1417 // 1 on success.
1418 // 0 on failure.
1419 // --------------------------------------------------------------------------------
1420 function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
1421 {
1422 $v_result=1;
1423
1424 // ----- Read the options
1425 $i=0;
1426 while ($i<$p_size) {
1427
1428 // ----- Check if the option is supported
1429 if (!isset($v_requested_options[$p_options_list[$i]])) {
1430 // ----- Error log
1431 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1432
1433 // ----- Return
1434 return PclZip::errorCode();
1435 }
1436
1437 // ----- Look for next option
1438 switch ($p_options_list[$i]) {
1439 // ----- Look for options that request a path value
1440 case PCLZIP_OPT_PATH :
1441 case PCLZIP_OPT_REMOVE_PATH :
1442 case PCLZIP_OPT_ADD_PATH :
1443 // ----- Check the number of parameters
1444 if (($i+1) >= $p_size) {
1445 // ----- Error log
1446 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1447
1448 // ----- Return
1449 return PclZip::errorCode();
1450 }
1451
1452 // ----- Get the value
1453 $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1454 $i++;
1455 break;
1456
1457 case PCLZIP_OPT_TEMP_FILE_THRESHOLD :
1458 // ----- Check the number of parameters
1459 if (($i+1) >= $p_size) {
1460 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1461 return PclZip::errorCode();
1462 }
1463
1464 // ----- Check for incompatible options
1465 if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1466 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1467 return PclZip::errorCode();
1468 }
1469
1470 // ----- Check the value
1471 $v_value = $p_options_list[$i+1];
1472 if ((!is_integer($v_value)) || ($v_value<0)) {
1473 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1474 return PclZip::errorCode();
1475 }
1476
1477 // ----- Get the value (and convert it in bytes)
1478 $v_result_list[$p_options_list[$i]] = $v_value*1048576;
1479 $i++;
1480 break;
1481
1482 case PCLZIP_OPT_TEMP_FILE_ON :
1483 // ----- Check for incompatible options
1484 if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1485 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1486 return PclZip::errorCode();
1487 }
1488
1489 $v_result_list[$p_options_list[$i]] = true;
1490 break;
1491
1492 case PCLZIP_OPT_TEMP_FILE_OFF :
1493 // ----- Check for incompatible options
1494 if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
1495 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
1496 return PclZip::errorCode();
1497 }
1498 // ----- Check for incompatible options
1499 if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1500 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
1501 return PclZip::errorCode();
1502 }
1503
1504 $v_result_list[$p_options_list[$i]] = true;
1505 break;
1506
1507 case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
1508 // ----- Check the number of parameters
1509 if (($i+1) >= $p_size) {
1510 // ----- Error log
1511 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1512
1513 // ----- Return
1514 return PclZip::errorCode();
1515 }
1516
1517 // ----- Get the value
1518 if ( is_string($p_options_list[$i+1])
1519 && ($p_options_list[$i+1] != '')) {
1520 $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1521 $i++;
1522 }
1523 else {
1524 }
1525 break;
1526
1527 // ----- Look for options that request an array of string for value
1528 case PCLZIP_OPT_BY_NAME :
1529 // ----- Check the number of parameters
1530 if (($i+1) >= $p_size) {
1531 // ----- Error log
1532 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1533
1534 // ----- Return
1535 return PclZip::errorCode();
1536 }
1537
1538 // ----- Get the value
1539 if (is_string($p_options_list[$i+1])) {
1540 $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1541 }
1542 else if (is_array($p_options_list[$i+1])) {
1543 $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1544 }
1545 else {
1546 // ----- Error log
1547 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1548
1549 // ----- Return
1550 return PclZip::errorCode();
1551 }
1552 $i++;
1553 break;
1554
1555 // ----- Look for options that request an EREG or PREG expression
1556 case PCLZIP_OPT_BY_EREG :
1557 // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
1558 // to PCLZIP_OPT_BY_PREG
1559 $p_options_list[$i] = PCLZIP_OPT_BY_PREG;
1560 case PCLZIP_OPT_BY_PREG :
1561 //case PCLZIP_OPT_CRYPT :
1562 // ----- Check the number of parameters
1563 if (($i+1) >= $p_size) {
1564 // ----- Error log
1565 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1566
1567 // ----- Return
1568 return PclZip::errorCode();
1569 }
1570
1571 // ----- Get the value
1572 if (is_string($p_options_list[$i+1])) {
1573 $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1574 }
1575 else {
1576 // ----- Error log
1577 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1578
1579 // ----- Return
1580 return PclZip::errorCode();
1581 }
1582 $i++;
1583 break;
1584
1585 // ----- Look for options that takes a string
1586 case PCLZIP_OPT_COMMENT :
1587 case PCLZIP_OPT_ADD_COMMENT :
1588 case PCLZIP_OPT_PREPEND_COMMENT :
1589 // ----- Check the number of parameters
1590 if (($i+1) >= $p_size) {
1591 // ----- Error log
1592 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
1593 "Missing parameter value for option '"
1594 .PclZipUtilOptionText($p_options_list[$i])
1595 ."'");
1596
1597 // ----- Return
1598 return PclZip::errorCode();
1599 }
1600
1601 // ----- Get the value
1602 if (is_string($p_options_list[$i+1])) {
1603 $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1604 }
1605 else {
1606 // ----- Error log
1607 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
1608 "Wrong parameter value for option '"
1609 .PclZipUtilOptionText($p_options_list[$i])
1610 ."'");
1611
1612 // ----- Return
1613 return PclZip::errorCode();
1614 }
1615 $i++;
1616 break;
1617
1618 // ----- Look for options that request an array of index
1619 case PCLZIP_OPT_BY_INDEX :
1620 // ----- Check the number of parameters
1621 if (($i+1) >= $p_size) {
1622 // ----- Error log
1623 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1624
1625 // ----- Return
1626 return PclZip::errorCode();
1627 }
1628
1629 // ----- Get the value
1630 $v_work_list = array();
1631 if (is_string($p_options_list[$i+1])) {
1632
1633 // ----- Remove spaces
1634 $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
1635
1636 // ----- Parse items
1637 $v_work_list = explode(",", $p_options_list[$i+1]);
1638 }
1639 else if (is_integer($p_options_list[$i+1])) {
1640 $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1641 }
1642 else if (is_array($p_options_list[$i+1])) {
1643 $v_work_list = $p_options_list[$i+1];
1644 }
1645 else {
1646 // ----- Error log
1647 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1648
1649 // ----- Return
1650 return PclZip::errorCode();
1651 }
1652
1653 // ----- Reduce the index list
1654 // each index item in the list must be a couple with a start and
1655 // an end value : [0,3], [5-5], [8-10], ...
1656 // ----- Check the format of each item
1657 $v_sort_flag=false;
1658 $v_sort_value=0;
1659 for ($j=0; $j<sizeof($v_work_list); $j++) {
1660 // ----- Explode the item
1661 $v_item_list = explode("-", $v_work_list[$j]);
1662 $v_size_item_list = sizeof($v_item_list);
1663
1664 // ----- TBC : Here we might check that each item is a
1665 // real integer ...
1666
1667 // ----- Look for single value
1668 if ($v_size_item_list == 1) {
1669 // ----- Set the option value
1670 $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1671 $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1672 }
1673 elseif ($v_size_item_list == 2) {
1674 // ----- Set the option value
1675 $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1676 $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1677 }
1678 else {
1679 // ----- Error log
1680 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1681
1682 // ----- Return
1683 return PclZip::errorCode();
1684 }
1685
1686
1687 // ----- Look for list sort
1688 if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1689 $v_sort_flag=true;
1690
1691 // ----- TBC : An automatic sort should be writen ...
1692 // ----- Error log
1693 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1694
1695 // ----- Return
1696 return PclZip::errorCode();
1697 }
1698 $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1699 }
1700
1701 // ----- Sort the items
1702 if ($v_sort_flag) {
1703 // TBC : To Be Completed
1704 }
1705
1706 // ----- Next option
1707 $i++;
1708 break;
1709
1710 // ----- Look for options that request no value
1711 case PCLZIP_OPT_REMOVE_ALL_PATH :
1712 case PCLZIP_OPT_EXTRACT_AS_STRING :
1713 case PCLZIP_OPT_NO_COMPRESSION :
1714 case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
1715 case PCLZIP_OPT_REPLACE_NEWER :
1716 case PCLZIP_OPT_STOP_ON_ERROR :
1717 $v_result_list[$p_options_list[$i]] = true;
1718 break;
1719
1720 // ----- Look for options that request an octal value
1721 case PCLZIP_OPT_SET_CHMOD :
1722 // ----- Check the number of parameters
1723 if (($i+1) >= $p_size) {
1724 // ----- Error log
1725 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1726
1727 // ----- Return
1728 return PclZip::errorCode();
1729 }
1730
1731 // ----- Get the value
1732 $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1733 $i++;
1734 break;
1735
1736 // ----- Look for options that request a call-back
1737 case PCLZIP_CB_PRE_EXTRACT :
1738 case PCLZIP_CB_POST_EXTRACT :
1739 case PCLZIP_CB_PRE_ADD :
1740 case PCLZIP_CB_POST_ADD :
1741 // ----- Check the number of parameters
1742 if (($i+1) >= $p_size) {
1743 // ----- Error log
1744 PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1745
1746 // ----- Return
1747 return PclZip::errorCode();
1748 }
1749
1750 // ----- Get the value
1751 $v_function_name = $p_options_list[$i+1];
1752
1753 // ----- Check that the value is a valid existing function
1754 if (!function_exists($v_function_name)) {
1755 // ----- Error log
1756 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1757
1758 // ----- Return
1759 return PclZip::errorCode();
1760 }
1761
1762 // ----- Set the attribute
1763 $v_result_list[$p_options_list[$i]] = $v_function_name;
1764 $i++;
1765 break;
1766
1767 default :
1768 // ----- Error log
1769 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1770 "Unknown parameter '"
1771 .$p_options_list[$i]."'");
1772
1773 // ----- Return
1774 return PclZip::errorCode();
1775 }
1776
1777 // ----- Next options
1778 $i++;
1779 }
1780
1781 // ----- Look for mandatory options
1782 if ($v_requested_options !== false) {
1783 for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1784 // ----- Look for mandatory option
1785 if ($v_requested_options[$key] == 'mandatory') {
1786 // ----- Look if present
1787 if (!isset($v_result_list[$key])) {
1788 // ----- Error log
1789 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1790
1791 // ----- Return
1792 return PclZip::errorCode();
1793 }
1794 }
1795 }
1796 }
1797
1798 // ----- Look for default values
1799 if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1800
1801 }
1802
1803 // ----- Return
1804 return $v_result;
1805 }
1806 // --------------------------------------------------------------------------------
1807
1808 // --------------------------------------------------------------------------------
1809 // Function : privOptionDefaultThreshold()
1810 // Description :
1811 // Parameters :
1812 // Return Values :
1813 // --------------------------------------------------------------------------------
1814 function privOptionDefaultThreshold(&$p_options)
1815 {
1816 $v_result=1;
1817
1818 if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
1819 || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) {
1820 return $v_result;
1821 }
1822
1823 // ----- Get 'memory_limit' configuration value
1824 $v_memory_limit = ini_get('memory_limit');
1825 $v_memory_limit = trim($v_memory_limit);
1826 $last = strtolower(substr($v_memory_limit, -1));
1827
1828 if($last == 'g')
1829 //$v_memory_limit = $v_memory_limit*1024*1024*1024;
1830 $v_memory_limit = $v_memory_limit*1073741824;
1831 if($last == 'm')
1832 //$v_memory_limit = $v_memory_limit*1024*1024;
1833 $v_memory_limit = $v_memory_limit*1048576;
1834 if($last == 'k')
1835 $v_memory_limit = $v_memory_limit*1024;
1836
1837 $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO);
1838
1839
1840 // ----- Sanity check : No threshold if value lower than 1M
1841 if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
1842 unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
1843 }
1844
1845 // ----- Return
1846 return $v_result;
1847 }
1848 // --------------------------------------------------------------------------------
1849
1850 // --------------------------------------------------------------------------------
1851 // Function : privFileDescrParseAtt()
1852 // Description :
1853 // Parameters :
1854 // Return Values :
1855 // 1 on success.
1856 // 0 on failure.
1857 // --------------------------------------------------------------------------------
1858 function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
1859 {
1860 $v_result=1;
1861
1862 // ----- For each file in the list check the attributes
1863 foreach ($p_file_list as $v_key => $v_value) {
1864
1865 // ----- Check if the option is supported
1866 if (!isset($v_requested_options[$v_key])) {
1867 // ----- Error log
1868 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
1869
1870 // ----- Return
1871 return PclZip::errorCode();
1872 }
1873
1874 // ----- Look for attribute
1875 switch ($v_key) {
1876 case PCLZIP_ATT_FILE_NAME :
1877 if (!is_string($v_value)) {
1878 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1879 return PclZip::errorCode();
1880 }
1881
1882 $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
1883
1884 if ($p_filedescr['filename'] == '') {
1885 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
1886 return PclZip::errorCode();
1887 }
1888
1889 break;
1890
1891 case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
1892 if (!is_string($v_value)) {
1893 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1894 return PclZip::errorCode();
1895 }
1896
1897 $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
1898
1899 if ($p_filedescr['new_short_name'] == '') {
1900 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
1901 return PclZip::errorCode();
1902 }
1903 break;
1904
1905 case PCLZIP_ATT_FILE_NEW_FULL_NAME :
1906 if (!is_string($v_value)) {
1907 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1908 return PclZip::errorCode();
1909 }
1910
1911 $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
1912
1913 if ($p_filedescr['new_full_name'] == '') {
1914 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
1915 return PclZip::errorCode();
1916 }
1917 break;
1918
1919 // ----- Look for options that takes a string
1920 case PCLZIP_ATT_FILE_COMMENT :
1921 if (!is_string($v_value)) {
1922 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1923 return PclZip::errorCode();
1924 }
1925
1926 $p_filedescr['comment'] = $v_value;
1927 break;
1928
1929 case PCLZIP_ATT_FILE_MTIME :
1930 if (!is_integer($v_value)) {
1931 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'");
1932 return PclZip::errorCode();
1933 }
1934
1935 $p_filedescr['mtime'] = $v_value;
1936 break;
1937
1938 case PCLZIP_ATT_FILE_CONTENT :
1939 $p_filedescr['content'] = $v_value;
1940 break;
1941
1942 default :
1943 // ----- Error log
1944 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1945 "Unknown parameter '".$v_key."'");
1946
1947 // ----- Return
1948 return PclZip::errorCode();
1949 }
1950
1951 // ----- Look for mandatory options
1952 if ($v_requested_options !== false) {
1953 for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1954 // ----- Look for mandatory option
1955 if ($v_requested_options[$key] == 'mandatory') {
1956 // ----- Look if present
1957 if (!isset($p_file_list[$key])) {
1958 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1959 return PclZip::errorCode();
1960 }
1961 }
1962 }
1963 }
1964
1965 // end foreach
1966 }
1967
1968 // ----- Return
1969 return $v_result;
1970 }
1971 // --------------------------------------------------------------------------------
1972
1973 // --------------------------------------------------------------------------------
1974 // Function : privFileDescrExpand()
1975 // Description :
1976 // This method look for each item of the list to see if its a file, a folder
1977 // or a string to be added as file. For any other type of files (link, other)
1978 // just ignore the item.
1979 // Then prepare the information that will be stored for that file.
1980 // When its a folder, expand the folder with all the files that are in that
1981 // folder (recursively).
1982 // Parameters :
1983 // Return Values :
1984 // 1 on success.
1985 // 0 on failure.
1986 // --------------------------------------------------------------------------------
1987 function privFileDescrExpand(&$p_filedescr_list, &$p_options)
1988 {
1989 $v_result=1;
1990
1991 // ----- Create a result list
1992 $v_result_list = array();
1993
1994 // ----- Look each entry
1995 for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
1996
1997 // ----- Get filedescr
1998 $v_descr = $p_filedescr_list[$i];
1999
2000 // ----- Reduce the filename
2001 $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
2002 $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
2003
2004 // ----- Look for real file or folder
2005 if (file_exists($v_descr['filename'])) {
2006 if (@is_file($v_descr['filename'])) {
2007 $v_descr['type'] = 'file';
2008 }
2009 else if (@is_dir($v_descr['filename'])) {
2010 $v_descr['type'] = 'folder';
2011 }
2012 else if (@is_link($v_descr['filename'])) {
2013 // skip
2014 continue;
2015 }
2016 else {
2017 // skip
2018 continue;
2019 }
2020 }
2021
2022 // ----- Look for string added as file
2023 else if (isset($v_descr['content'])) {
2024 $v_descr['type'] = 'virtual_file';
2025 }
2026
2027 // ----- Missing file
2028 else {
2029 // ----- Error log
2030 PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
2031
2032 // ----- Return
2033 return PclZip::errorCode();
2034 }
2035
2036 // ----- Calculate the stored filename
2037 $this->privCalculateStoredFilename($v_descr, $p_options);
2038
2039 // ----- Add the descriptor in result list
2040 $v_result_list[sizeof($v_result_list)] = $v_descr;
2041
2042 // ----- Look for folder
2043 if ($v_descr['type'] == 'folder') {
2044 // ----- List of items in folder
2045 $v_dirlist_descr = array();
2046 $v_dirlist_nb = 0;
2047 if ($v_folder_handler = @opendir($v_descr['filename'])) {
2048 while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
2049
2050 // ----- Skip '.' and '..'
2051 $wp_all_backup_exclude_dir=get_option('wp_all_backup_exclude_dir');
2052 if(empty($wp_all_backup_exclude_dir))
2053 {
2054 $excludes = WPALLBK_BACKUPS_DIR;
2055 }else{
2056 $excludes = WPALLBK_BACKUPS_DIR.'|'.$wp_all_backup_exclude_dir;
2057 }
2058
2059 // Excludes
2060 if ( preg_match( '(' . $excludes . ')',$v_item_handler) ){
2061 continue;
2062 }
2063 if (($v_item_handler == '.') || ($v_item_handler == '..') || ($v_item_handler == WPALLBK_BACKUPS_DIR)) {
2064 continue;
2065 }
2066
2067 // ----- Compose the full filename
2068 $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
2069
2070 // ----- Look for different stored filename
2071 // Because the name of the folder was changed, the name of the
2072 // files/sub-folders also change
2073 if (($v_descr['stored_filename'] != $v_descr['filename'])
2074 && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
2075 if ($v_descr['stored_filename'] != '') {
2076 $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
2077 }
2078 else {
2079 $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
2080 }
2081 }
2082
2083 $v_dirlist_nb++;
2084 }
2085
2086 @closedir($v_folder_handler);
2087 }
2088 else {
2089 // TBC : unable to open folder in read mode
2090 }
2091
2092 // ----- Expand each element of the list
2093 if ($v_dirlist_nb != 0) {
2094 // ----- Expand
2095 if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
2096 return $v_result;
2097 }
2098
2099 // ----- Concat the resulting list
2100 $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
2101 }
2102 else {
2103 }
2104
2105 // ----- Free local array
2106 unset($v_dirlist_descr);
2107 }
2108 }
2109
2110 // ----- Get the result list
2111 $p_filedescr_list = $v_result_list;
2112
2113 // ----- Return
2114 return $v_result;
2115 }
2116 // --------------------------------------------------------------------------------
2117
2118 // --------------------------------------------------------------------------------
2119 // Function : privCreate()
2120 // Description :
2121 // Parameters :
2122 // Return Values :
2123 // --------------------------------------------------------------------------------
2124 function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
2125 {
2126 $v_result=1;
2127 $v_list_detail = array();
2128
2129 // ----- Magic quotes trick
2130 $this->privDisableMagicQuotes();
2131
2132 // ----- Open the file in write mode
2133 if (($v_result = $this->privOpenFd('wb')) != 1)
2134 {
2135 // ----- Return
2136 return $v_result;
2137 }
2138
2139 // ----- Add the list of files
2140 $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
2141
2142 // ----- Close
2143 $this->privCloseFd();
2144
2145 // ----- Magic quotes trick
2146 $this->privSwapBackMagicQuotes();
2147
2148 // ----- Return
2149 return $v_result;
2150 }
2151 // --------------------------------------------------------------------------------
2152
2153 // --------------------------------------------------------------------------------
2154 // Function : privAdd()
2155 // Description :
2156 // Parameters :
2157 // Return Values :
2158 // --------------------------------------------------------------------------------
2159 function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
2160 {
2161 $v_result=1;
2162 $v_list_detail = array();
2163
2164 // ----- Look if the archive exists or is empty
2165 if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
2166 {
2167
2168 // ----- Do a create
2169 $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
2170
2171 // ----- Return
2172 return $v_result;
2173 }
2174 // ----- Magic quotes trick
2175 $this->privDisableMagicQuotes();
2176
2177 // ----- Open the zip file
2178 if (($v_result=$this->privOpenFd('rb')) != 1)
2179 {
2180 // ----- Magic quotes trick
2181 $this->privSwapBackMagicQuotes();
2182
2183 // ----- Return
2184 return $v_result;
2185 }
2186
2187 // ----- Read the central directory informations
2188 $v_central_dir = array();
2189 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
2190 {
2191 $this->privCloseFd();
2192 $this->privSwapBackMagicQuotes();
2193 return $v_result;
2194 }
2195
2196 // ----- Go to beginning of File
2197 @rewind($this->zip_fd);
2198
2199 // ----- Creates a temporay file
2200 $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
2201
2202 // ----- Open the temporary file in write mode
2203 if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
2204 {
2205 $this->privCloseFd();
2206 $this->privSwapBackMagicQuotes();
2207
2208 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
2209
2210 // ----- Return
2211 return PclZip::errorCode();
2212 }
2213
2214 // ----- Copy the files from the archive to the temporary file
2215 // TBC : Here I should better append the file and go back to erase the central dir
2216 $v_size = $v_central_dir['offset'];
2217 while ($v_size != 0)
2218 {
2219 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2220 $v_buffer = fread($this->zip_fd, $v_read_size);
2221 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
2222 $v_size -= $v_read_size;
2223 }
2224
2225 // ----- Swap the file descriptor
2226 // Here is a trick : I swap the temporary fd with the zip fd, in order to use
2227 // the following methods on the temporary fil and not the real archive
2228 $v_swap = $this->zip_fd;
2229 $this->zip_fd = $v_zip_temp_fd;
2230 $v_zip_temp_fd = $v_swap;
2231
2232 // ----- Add the files
2233 $v_header_list = array();
2234 if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2235 {
2236 fclose($v_zip_temp_fd);
2237 $this->privCloseFd();
2238 @unlink($v_zip_temp_name);
2239 $this->privSwapBackMagicQuotes();
2240
2241 // ----- Return
2242 return $v_result;
2243 }
2244
2245 // ----- Store the offset of the central dir
2246 $v_offset = @ftell($this->zip_fd);
2247
2248 // ----- Copy the block of file headers from the old archive
2249 $v_size = $v_central_dir['size'];
2250 while ($v_size != 0)
2251 {
2252 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2253 $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
2254 @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2255 $v_size -= $v_read_size;
2256 }
2257
2258 // ----- Create the Central Dir files header
2259 for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
2260 {
2261 // ----- Create the file header
2262 if ($v_header_list[$i]['status'] == 'ok') {
2263 if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2264 fclose($v_zip_temp_fd);
2265 $this->privCloseFd();
2266 @unlink($v_zip_temp_name);
2267 $this->privSwapBackMagicQuotes();
2268
2269 // ----- Return
2270 return $v_result;
2271 }
2272 $v_count++;
2273 }
2274
2275 // ----- Transform the header to a 'usable' info
2276 $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2277 }
2278
2279 // ----- Zip file comment
2280 $v_comment = $v_central_dir['comment'];
2281 if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2282 $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2283 }
2284 if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
2285 $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
2286 }
2287 if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
2288 $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
2289 }
2290
2291 // ----- Calculate the size of the central header
2292 $v_size = @ftell($this->zip_fd)-$v_offset;
2293
2294 // ----- Create the central dir footer
2295 if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
2296 {
2297 // ----- Reset the file list
2298 unset($v_header_list);
2299 $this->privSwapBackMagicQuotes();
2300
2301 // ----- Return
2302 return $v_result;
2303 }
2304
2305 // ----- Swap back the file descriptor
2306 $v_swap = $this->zip_fd;
2307 $this->zip_fd = $v_zip_temp_fd;
2308 $v_zip_temp_fd = $v_swap;
2309
2310 // ----- Close
2311 $this->privCloseFd();
2312
2313 // ----- Close the temporary file
2314 @fclose($v_zip_temp_fd);
2315
2316 // ----- Magic quotes trick
2317 $this->privSwapBackMagicQuotes();
2318
2319 // ----- Delete the zip file
2320 // TBC : I should test the result ...
2321 @unlink($this->zipname);
2322
2323 // ----- Rename the temporary file
2324 // TBC : I should test the result ...
2325 //@rename($v_zip_temp_name, $this->zipname);
2326 PclZipUtilRename($v_zip_temp_name, $this->zipname);
2327
2328 // ----- Return
2329 return $v_result;
2330 }
2331 // --------------------------------------------------------------------------------
2332
2333 // --------------------------------------------------------------------------------
2334 // Function : privOpenFd()
2335 // Description :
2336 // Parameters :
2337 // --------------------------------------------------------------------------------
2338 function privOpenFd($p_mode)
2339 {
2340 $v_result=1;
2341
2342 // ----- Look if already open
2343 if ($this->zip_fd != 0)
2344 {
2345 // ----- Error log
2346 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
2347
2348 // ----- Return
2349 return PclZip::errorCode();
2350 }
2351
2352 // ----- Open the zip file
2353 if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
2354 {
2355 // ----- Error log
2356 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
2357
2358 // ----- Return
2359 return PclZip::errorCode();
2360 }
2361
2362 // ----- Return
2363 return $v_result;
2364 }
2365 // --------------------------------------------------------------------------------
2366
2367 // --------------------------------------------------------------------------------
2368 // Function : privCloseFd()
2369 // Description :
2370 // Parameters :
2371 // --------------------------------------------------------------------------------
2372 function privCloseFd()
2373 {
2374 $v_result=1;
2375
2376 if ($this->zip_fd != 0)
2377 @fclose($this->zip_fd);
2378 $this->zip_fd = 0;
2379
2380 // ----- Return
2381 return $v_result;
2382 }
2383 // --------------------------------------------------------------------------------
2384
2385 // --------------------------------------------------------------------------------
2386 // Function : privAddList()
2387 // Description :
2388 // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2389 // different from the real path of the file. This is usefull if you want to have PclTar
2390 // running in any directory, and memorize relative path from an other directory.
2391 // Parameters :
2392 // $p_list : An array containing the file or directory names to add in the tar
2393 // $p_result_list : list of added files with their properties (specially the status field)
2394 // $p_add_dir : Path to add in the filename path archived
2395 // $p_remove_dir : Path to remove in the filename path archived
2396 // Return Values :
2397 // --------------------------------------------------------------------------------
2398 // function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2399 function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
2400 {
2401 $v_result=1;
2402
2403 // ----- Add the files
2404 $v_header_list = array();
2405 if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2406 {
2407 // ----- Return
2408 return $v_result;
2409 }
2410
2411 // ----- Store the offset of the central dir
2412 $v_offset = @ftell($this->zip_fd);
2413
2414 // ----- Create the Central Dir files header
2415 for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
2416 {
2417 // ----- Create the file header
2418 if ($v_header_list[$i]['status'] == 'ok') {
2419 if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2420 // ----- Return
2421 return $v_result;
2422 }
2423 $v_count++;
2424 }
2425
2426 // ----- Transform the header to a 'usable' info
2427 $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2428 }
2429
2430 // ----- Zip file comment
2431 $v_comment = '';
2432 if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2433 $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2434 }
2435
2436 // ----- Calculate the size of the central header
2437 $v_size = @ftell($this->zip_fd)-$v_offset;
2438
2439 // ----- Create the central dir footer
2440 if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
2441 {
2442 // ----- Reset the file list
2443 unset($v_header_list);
2444
2445 // ----- Return
2446 return $v_result;
2447 }
2448
2449 // ----- Return
2450 return $v_result;
2451 }
2452 // --------------------------------------------------------------------------------
2453
2454 // --------------------------------------------------------------------------------
2455 // Function : privAddFileList()
2456 // Description :
2457 // Parameters :
2458 // $p_filedescr_list : An array containing the file description
2459 // or directory names to add in the zip
2460 // $p_result_list : list of added files with their properties (specially the status field)
2461 // Return Values :
2462 // --------------------------------------------------------------------------------
2463 function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
2464 {
2465 $v_result=1;
2466 $v_header = array();
2467
2468 // ----- Recuperate the current number of elt in list
2469 $v_nb = sizeof($p_result_list);
2470
2471 // ----- Loop on the files
2472 for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
2473 // ----- Format the filename
2474 $p_filedescr_list[$j]['filename']
2475 = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
2476
2477
2478 // ----- Skip empty file names
2479 // TBC : Can this be possible ? not checked in DescrParseAtt ?
2480 if ($p_filedescr_list[$j]['filename'] == "") {
2481 continue;
2482 }
2483
2484 // ----- Check the filename
2485 if ( ($p_filedescr_list[$j]['type'] != 'virtual_file')
2486 && (!file_exists($p_filedescr_list[$j]['filename']))) {
2487 PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
2488 return PclZip::errorCode();
2489 }
2490
2491 // ----- Look if it is a file or a dir with no all path remove option
2492 // or a dir with all its path removed
2493 // if ( (is_file($p_filedescr_list[$j]['filename']))
2494 // || ( is_dir($p_filedescr_list[$j]['filename'])
2495 if ( ($p_filedescr_list[$j]['type'] == 'file')
2496 || ($p_filedescr_list[$j]['type'] == 'virtual_file')
2497 || ( ($p_filedescr_list[$j]['type'] == 'folder')
2498 && ( !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
2499 || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
2500 ) {
2501
2502 // ----- Add the file
2503 $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
2504 $p_options);
2505 if ($v_result != 1) {
2506 return $v_result;
2507 }
2508
2509 // ----- Store the file infos
2510 $p_result_list[$v_nb++] = $v_header;
2511 }
2512 }
2513
2514 // ----- Return
2515 return $v_result;
2516 }
2517 // --------------------------------------------------------------------------------
2518
2519 // --------------------------------------------------------------------------------
2520 // Function : privAddFile()
2521 // Description :
2522 // Parameters :
2523 // Return Values :
2524 // --------------------------------------------------------------------------------
2525 function privAddFile($p_filedescr, &$p_header, &$p_options)
2526 {
2527 $v_result=1;
2528
2529 // ----- Working variable
2530 $p_filename = $p_filedescr['filename'];
2531
2532 // TBC : Already done in the fileAtt check ... ?
2533 if ($p_filename == "") {
2534 // ----- Error log
2535 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
2536
2537 // ----- Return
2538 return PclZip::errorCode();
2539 }
2540
2541
2542 // ----- Set the file properties
2543 clearstatcache();
2544 $p_header['version'] = 20;
2545 $p_header['version_extracted'] = 10;
2546 $p_header['flag'] = 0;
2547 $p_header['compression'] = 0;
2548 $p_header['crc'] = 0;
2549 $p_header['compressed_size'] = 0;
2550 $p_header['filename_len'] = strlen($p_filename);
2551 $p_header['extra_len'] = 0;
2552 $p_header['disk'] = 0;
2553 $p_header['internal'] = 0;
2554 $p_header['offset'] = 0;
2555 $p_header['filename'] = $p_filename;
2556 // TBC : Removed $p_header['stored_filename'] = $v_stored_filename;
2557 $p_header['stored_filename'] = $p_filedescr['stored_filename'];
2558 $p_header['extra'] = '';
2559 $p_header['status'] = 'ok';
2560 $p_header['index'] = -1;
2561
2562 // ----- Look for regular file
2563 if ($p_filedescr['type']=='file') {
2564 $p_header['external'] = 0x00000000;
2565 $p_header['size'] = filesize($p_filename);
2566 }
2567
2568 // ----- Look for regular folder
2569 else if ($p_filedescr['type']=='folder') {
2570 $p_header['external'] = 0x00000010;
2571 $p_header['mtime'] = filemtime($p_filename);
2572 $p_header['size'] = filesize($p_filename);
2573 }
2574
2575 // ----- Look for virtual file
2576 else if ($p_filedescr['type'] == 'virtual_file') {
2577 $p_header['external'] = 0x00000000;
2578 $p_header['size'] = strlen($p_filedescr['content']);
2579 }
2580
2581
2582 // ----- Look for filetime
2583 if (isset($p_filedescr['mtime'])) {
2584 $p_header['mtime'] = $p_filedescr['mtime'];
2585 }
2586 else if ($p_filedescr['type'] == 'virtual_file') {
2587 $p_header['mtime'] = time();
2588 }
2589 else {
2590 $p_header['mtime'] = filemtime($p_filename);
2591 }
2592
2593 // ------ Look for file comment
2594 if (isset($p_filedescr['comment'])) {
2595 $p_header['comment_len'] = strlen($p_filedescr['comment']);
2596 $p_header['comment'] = $p_filedescr['comment'];
2597 }
2598 else {
2599 $p_header['comment_len'] = 0;
2600 $p_header['comment'] = '';
2601 }
2602
2603 // ----- Look for pre-add callback
2604 if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
2605
2606 // ----- Generate a local information
2607 $v_local_header = array();
2608 $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2609
2610 // ----- Call the callback
2611 // Here I do not use call_user_func() because I need to send a reference to the
2612 // header.
2613 $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
2614 if ($v_result == 0) {
2615 // ----- Change the file status
2616 $p_header['status'] = "skipped";
2617 $v_result = 1;
2618 }
2619
2620 // ----- Update the informations
2621 // Only some fields can be modified
2622 if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2623 $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
2624 }
2625 }
2626
2627 // ----- Look for empty stored filename
2628 if ($p_header['stored_filename'] == "") {
2629 $p_header['status'] = "filtered";
2630 }
2631
2632 // ----- Check the path length
2633 if (strlen($p_header['stored_filename']) > 0xFF) {
2634 $p_header['status'] = 'filename_too_long';
2635 }
2636
2637 // ----- Look if no error, or file not skipped
2638 if ($p_header['status'] == 'ok') {
2639
2640 // ----- Look for a file
2641 if ($p_filedescr['type'] == 'file') {
2642 // ----- Look for using temporary file to zip
2643 if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
2644 && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
2645 || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
2646 && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) {
2647 $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
2648 if ($v_result < PCLZIP_ERR_NO_ERROR) {
2649 return $v_result;
2650 }
2651 }
2652
2653 // ----- Use "in memory" zip algo
2654 else {
2655
2656 // ----- Open the source file
2657 if (($v_file = @fopen($p_filename, "rb")) == 0) {
2658 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2659 return PclZip::errorCode();
2660 }
2661
2662 // ----- Read the file content
2663 $v_content = @fread($v_file, $p_header['size']);
2664
2665 // ----- Close the file
2666 @fclose($v_file);
2667
2668 // ----- Calculate the CRC
2669 $p_header['crc'] = @crc32($v_content);
2670
2671 // ----- Look for no compression
2672 if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2673 // ----- Set header parameters
2674 $p_header['compressed_size'] = $p_header['size'];
2675 $p_header['compression'] = 0;
2676 }
2677
2678 // ----- Look for normal compression
2679 else {
2680 // ----- Compress the content
2681 $v_content = @gzdeflate($v_content);
2682
2683 // ----- Set header parameters
2684 $p_header['compressed_size'] = strlen($v_content);
2685 $p_header['compression'] = 8;
2686 }
2687
2688 // ----- Call the header generation
2689 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2690 @fclose($v_file);
2691 return $v_result;
2692 }
2693
2694 // ----- Write the compressed (or not) content
2695 @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2696
2697 }
2698
2699 }
2700
2701 // ----- Look for a virtual file (a file from string)
2702 else if ($p_filedescr['type'] == 'virtual_file') {
2703
2704 $v_content = $p_filedescr['content'];
2705
2706 // ----- Calculate the CRC
2707 $p_header['crc'] = @crc32($v_content);
2708
2709 // ----- Look for no compression
2710 if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2711 // ----- Set header parameters
2712 $p_header['compressed_size'] = $p_header['size'];
2713 $p_header['compression'] = 0;
2714 }
2715
2716 // ----- Look for normal compression
2717 else {
2718 // ----- Compress the content
2719 $v_content = @gzdeflate($v_content);
2720
2721 // ----- Set header parameters
2722 $p_header['compressed_size'] = strlen($v_content);
2723 $p_header['compression'] = 8;
2724 }
2725
2726 // ----- Call the header generation
2727 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2728 return $v_result;
2729 }
2730
2731 // ----- Write the compressed (or not) content
2732 @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2733 }
2734
2735 // ----- Look for a directory
2736 else if ($p_filedescr['type'] == 'folder') {
2737 // ----- Look for directory last '/'
2738 if (@substr($p_header['stored_filename'], -1) != '/') {
2739 $p_header['stored_filename'] .= '/';
2740 }
2741
2742 // ----- Set the file properties
2743 $p_header['size'] = 0;
2744 //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
2745 $p_header['external'] = 0x00000010; // Value for a folder : to be checked
2746
2747 // ----- Call the header generation
2748 if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
2749 {
2750 return $v_result;
2751 }
2752 }
2753 }
2754
2755 // ----- Look for post-add callback
2756 if (isset($p_options[PCLZIP_CB_POST_ADD])) {
2757
2758 // ----- Generate a local information
2759 $v_local_header = array();
2760 $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2761
2762 // ----- Call the callback
2763 // Here I do not use call_user_func() because I need to send a reference to the
2764 // header.
2765 $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header);
2766 if ($v_result == 0) {
2767 // ----- Ignored
2768 $v_result = 1;
2769 }
2770
2771 // ----- Update the informations
2772 // Nothing can be modified
2773 }
2774
2775 // ----- Return
2776 return $v_result;
2777 }
2778 // --------------------------------------------------------------------------------
2779
2780 // --------------------------------------------------------------------------------
2781 // Function : privAddFileUsingTempFile()
2782 // Description :
2783 // Parameters :
2784 // Return Values :
2785 // --------------------------------------------------------------------------------
2786 function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
2787 {
2788 $v_result=PCLZIP_ERR_NO_ERROR;
2789
2790 // ----- Working variable
2791 $p_filename = $p_filedescr['filename'];
2792
2793
2794 // ----- Open the source file
2795 if (($v_file = @fopen($p_filename, "rb")) == 0) {
2796 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2797 return PclZip::errorCode();
2798 }
2799
2800 // ----- Creates a compressed temporary file
2801 $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
2802 if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
2803 fclose($v_file);
2804 PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
2805 return PclZip::errorCode();
2806 }
2807
2808 // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2809 $v_size = filesize($p_filename);
2810 while ($v_size != 0) {
2811 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2812 $v_buffer = @fread($v_file, $v_read_size);
2813 //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2814 @gzputs($v_file_compressed, $v_buffer, $v_read_size);
2815 $v_size -= $v_read_size;
2816 }
2817
2818 // ----- Close the file
2819 @fclose($v_file);
2820 @gzclose($v_file_compressed);
2821
2822 // ----- Check the minimum file size
2823 if (filesize($v_gzip_temp_name) < 18) {
2824 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
2825 return PclZip::errorCode();
2826 }
2827
2828 // ----- Extract the compressed attributes
2829 if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
2830 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2831 return PclZip::errorCode();
2832 }
2833
2834 // ----- Read the gzip file header
2835 $v_binary_data = @fread($v_file_compressed, 10);
2836 $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
2837
2838 // ----- Check some parameters
2839 $v_data_header['os'] = bin2hex($v_data_header['os']);
2840
2841 // ----- Read the gzip file footer
2842 @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8);
2843 $v_binary_data = @fread($v_file_compressed, 8);
2844 $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);
2845
2846 // ----- Set the attributes
2847 $p_header['compression'] = ord($v_data_header['cm']);
2848 //$p_header['mtime'] = $v_data_header['mtime'];
2849 $p_header['crc'] = $v_data_footer['crc'];
2850 $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18;
2851
2852 // ----- Close the file
2853 @fclose($v_file_compressed);
2854
2855 // ----- Call the header generation
2856 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2857 return $v_result;
2858 }
2859
2860 // ----- Add the compressed data
2861 if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0)
2862 {
2863 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2864 return PclZip::errorCode();
2865 }
2866
2867 // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2868 fseek($v_file_compressed, 10);
2869 $v_size = $p_header['compressed_size'];
2870 while ($v_size != 0)
2871 {
2872 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2873 $v_buffer = @fread($v_file_compressed, $v_read_size);
2874 //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2875 @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2876 $v_size -= $v_read_size;
2877 }
2878
2879 // ----- Close the file
2880 @fclose($v_file_compressed);
2881
2882 // ----- Unlink the temporary file
2883 @unlink($v_gzip_temp_name);
2884
2885 // ----- Return
2886 return $v_result;
2887 }
2888 // --------------------------------------------------------------------------------
2889
2890 // --------------------------------------------------------------------------------
2891 // Function : privCalculateStoredFilename()
2892 // Description :
2893 // Based on file descriptor properties and global options, this method
2894 // calculate the filename that will be stored in the archive.
2895 // Parameters :
2896 // Return Values :
2897 // --------------------------------------------------------------------------------
2898 function privCalculateStoredFilename(&$p_filedescr, &$p_options)
2899 {
2900 $v_result=1;
2901
2902 // ----- Working variables
2903 $p_filename = $p_filedescr['filename'];
2904 if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
2905 $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH];
2906 }
2907 else {
2908 $p_add_dir = '';
2909 }
2910 if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) {
2911 $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH];
2912 }
2913 else {
2914 $p_remove_dir = '';
2915 }
2916 if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
2917 $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
2918 }
2919 else {
2920 $p_remove_all_dir = 0;
2921 }
2922
2923
2924 // ----- Look for full name change
2925 if (isset($p_filedescr['new_full_name'])) {
2926 // ----- Remove drive letter if any
2927 $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
2928 }
2929
2930 // ----- Look for path and/or short name change
2931 else {
2932
2933 // ----- Look for short name change
2934 // Its when we cahnge just the filename but not the path
2935 if (isset($p_filedescr['new_short_name'])) {
2936 $v_path_info = pathinfo($p_filename);
2937 $v_dir = '';
2938 if ($v_path_info['dirname'] != '') {
2939 $v_dir = $v_path_info['dirname'].'/';
2940 }
2941 $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
2942 }
2943 else {
2944 // ----- Calculate the stored filename
2945 $v_stored_filename = $p_filename;
2946 }
2947
2948 // ----- Look for all path to remove
2949 if ($p_remove_all_dir) {
2950 $v_stored_filename = basename($p_filename);
2951 }
2952 // ----- Look for partial path remove
2953 else if ($p_remove_dir != "") {
2954 if (substr($p_remove_dir, -1) != '/')
2955 $p_remove_dir .= "/";
2956
2957 if ( (substr($p_filename, 0, 2) == "./")
2958 || (substr($p_remove_dir, 0, 2) == "./")) {
2959
2960 if ( (substr($p_filename, 0, 2) == "./")
2961 && (substr($p_remove_dir, 0, 2) != "./")) {
2962 $p_remove_dir = "./".$p_remove_dir;
2963 }
2964 if ( (substr($p_filename, 0, 2) != "./")
2965 && (substr($p_remove_dir, 0, 2) == "./")) {
2966 $p_remove_dir = substr($p_remove_dir, 2);
2967 }
2968 }
2969
2970 $v_compare = PclZipUtilPathInclusion($p_remove_dir,
2971 $v_stored_filename);
2972 if ($v_compare > 0) {
2973 if ($v_compare == 2) {
2974 $v_stored_filename = "";
2975 }
2976 else {
2977 $v_stored_filename = substr($v_stored_filename,
2978 strlen($p_remove_dir));
2979 }
2980 }
2981 }
2982
2983 // ----- Remove drive letter if any
2984 $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename);
2985
2986 // ----- Look for path to add
2987 if ($p_add_dir != "") {
2988 if (substr($p_add_dir, -1) == "/")
2989 $v_stored_filename = $p_add_dir.$v_stored_filename;
2990 else
2991 $v_stored_filename = $p_add_dir."/".$v_stored_filename;
2992 }
2993 }
2994
2995 // ----- Filename (reduce the path of stored name)
2996 $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
2997 $p_filedescr['stored_filename'] = $v_stored_filename;
2998
2999 // ----- Return
3000 return $v_result;
3001 }
3002 // --------------------------------------------------------------------------------
3003
3004 // --------------------------------------------------------------------------------
3005 // Function : privWriteFileHeader()
3006 // Description :
3007 // Parameters :
3008 // Return Values :
3009 // --------------------------------------------------------------------------------
3010 function privWriteFileHeader(&$p_header)
3011 {
3012 $v_result=1;
3013
3014 // ----- Store the offset position of the file
3015 $p_header['offset'] = ftell($this->zip_fd);
3016
3017 // ----- Transform UNIX mtime to DOS format mdate/mtime
3018 $v_date = getdate($p_header['mtime']);
3019 $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3020 $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3021
3022 // ----- Packed data
3023 $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
3024 $p_header['version_extracted'], $p_header['flag'],
3025 $p_header['compression'], $v_mtime, $v_mdate,
3026 $p_header['crc'], $p_header['compressed_size'],
3027 $p_header['size'],
3028 strlen($p_header['stored_filename']),
3029 $p_header['extra_len']);
3030
3031 // ----- Write the first 148 bytes of the header in the archive
3032 fputs($this->zip_fd, $v_binary_data, 30);
3033
3034 // ----- Write the variable fields
3035 if (strlen($p_header['stored_filename']) != 0)
3036 {
3037 fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3038 }
3039 if ($p_header['extra_len'] != 0)
3040 {
3041 fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3042 }
3043
3044 // ----- Return
3045 return $v_result;
3046 }
3047 // --------------------------------------------------------------------------------
3048
3049 // --------------------------------------------------------------------------------
3050 // Function : privWriteCentralFileHeader()
3051 // Description :
3052 // Parameters :
3053 // Return Values :
3054 // --------------------------------------------------------------------------------
3055 function privWriteCentralFileHeader(&$p_header)
3056 {
3057 $v_result=1;
3058
3059 // TBC
3060 //for(reset($p_header); $key = key($p_header); next($p_header)) {
3061 //}
3062
3063 // ----- Transform UNIX mtime to DOS format mdate/mtime
3064 $v_date = getdate($p_header['mtime']);
3065 $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3066 $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3067
3068
3069 // ----- Packed data
3070 $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
3071 $p_header['version'], $p_header['version_extracted'],
3072 $p_header['flag'], $p_header['compression'],
3073 $v_mtime, $v_mdate, $p_header['crc'],
3074 $p_header['compressed_size'], $p_header['size'],
3075 strlen($p_header['stored_filename']),
3076 $p_header['extra_len'], $p_header['comment_len'],
3077 $p_header['disk'], $p_header['internal'],
3078 $p_header['external'], $p_header['offset']);
3079
3080 // ----- Write the 42 bytes of the header in the zip file
3081 fputs($this->zip_fd, $v_binary_data, 46);
3082
3083 // ----- Write the variable fields
3084 if (strlen($p_header['stored_filename']) != 0)
3085 {
3086 fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3087 }
3088 if ($p_header['extra_len'] != 0)
3089 {
3090 fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3091 }
3092 if ($p_header['comment_len'] != 0)
3093 {
3094 fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
3095 }
3096
3097 // ----- Return
3098 return $v_result;
3099 }
3100 // --------------------------------------------------------------------------------
3101
3102 // --------------------------------------------------------------------------------
3103 // Function : privWriteCentralHeader()
3104 // Description :
3105 // Parameters :
3106 // Return Values :
3107 // --------------------------------------------------------------------------------
3108 function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
3109 {
3110 $v_result=1;
3111
3112 // ----- Packed data
3113 $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
3114 $p_nb_entries, $p_size,
3115 $p_offset, strlen($p_comment));
3116
3117 // ----- Write the 22 bytes of the header in the zip file
3118 fputs($this->zip_fd, $v_binary_data, 22);
3119
3120 // ----- Write the variable fields
3121 if (strlen($p_comment) != 0)
3122 {
3123 fputs($this->zip_fd, $p_comment, strlen($p_comment));
3124 }
3125
3126 // ----- Return
3127 return $v_result;
3128 }
3129 // --------------------------------------------------------------------------------
3130
3131 // --------------------------------------------------------------------------------
3132 // Function : privList()
3133 // Description :
3134 // Parameters :
3135 // Return Values :
3136 // --------------------------------------------------------------------------------
3137 function privList(&$p_list)
3138 {
3139 $v_result=1;
3140
3141 // ----- Magic quotes trick
3142 $this->privDisableMagicQuotes();
3143
3144 // ----- Open the zip file
3145 if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
3146 {
3147 // ----- Magic quotes trick
3148 $this->privSwapBackMagicQuotes();
3149
3150 // ----- Error log
3151 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
3152
3153 // ----- Return
3154 return PclZip::errorCode();
3155 }
3156
3157 // ----- Read the central directory informations
3158 $v_central_dir = array();
3159 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3160 {
3161 $this->privSwapBackMagicQuotes();
3162 return $v_result;
3163 }
3164
3165 // ----- Go to beginning of Central Dir
3166 @rewind($this->zip_fd);
3167 if (@fseek($this->zip_fd, $v_central_dir['offset']))
3168 {
3169 $this->privSwapBackMagicQuotes();
3170
3171 // ----- Error log
3172 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3173
3174 // ----- Return
3175 return PclZip::errorCode();
3176 }
3177
3178 // ----- Read each entry
3179 for ($i=0; $i<$v_central_dir['entries']; $i++)
3180 {
3181 // ----- Read the file header
3182 if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3183 {
3184 $this->privSwapBackMagicQuotes();
3185 return $v_result;
3186 }
3187 $v_header['index'] = $i;
3188
3189 // ----- Get the only interesting attributes
3190 $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
3191 unset($v_header);
3192 }
3193
3194 // ----- Close the zip file
3195 $this->privCloseFd();
3196
3197 // ----- Magic quotes trick
3198 $this->privSwapBackMagicQuotes();
3199
3200 // ----- Return
3201 return $v_result;
3202 }
3203 // --------------------------------------------------------------------------------
3204
3205 // --------------------------------------------------------------------------------
3206 // Function : privConvertHeader2FileInfo()
3207 // Description :
3208 // This function takes the file informations from the central directory
3209 // entries and extract the interesting parameters that will be given back.
3210 // The resulting file infos are set in the array $p_info
3211 // $p_info['filename'] : Filename with full path. Given by user (add),
3212 // extracted in the filesystem (extract).
3213 // $p_info['stored_filename'] : Stored filename in the archive.
3214 // $p_info['size'] = Size of the file.
3215 // $p_info['compressed_size'] = Compressed size of the file.
3216 // $p_info['mtime'] = Last modification date of the file.
3217 // $p_info['comment'] = Comment associated with the file.
3218 // $p_info['folder'] = true/false : indicates if the entry is a folder or not.
3219 // $p_info['status'] = status of the action on the file.
3220 // $p_info['crc'] = CRC of the file content.
3221 // Parameters :
3222 // Return Values :
3223 // --------------------------------------------------------------------------------
3224 function privConvertHeader2FileInfo($p_header, &$p_info)
3225 {
3226 $v_result=1;
3227
3228 // ----- Get the interesting attributes
3229 $v_temp_path = PclZipUtilPathReduction($p_header['filename']);
3230 $p_info['filename'] = $v_temp_path;
3231 $v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']);
3232 $p_info['stored_filename'] = $v_temp_path;
3233 $p_info['size'] = $p_header['size'];
3234 $p_info['compressed_size'] = $p_header['compressed_size'];
3235 $p_info['mtime'] = $p_header['mtime'];
3236 $p_info['comment'] = $p_header['comment'];
3237 $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
3238 $p_info['index'] = $p_header['index'];
3239 $p_info['status'] = $p_header['status'];
3240 $p_info['crc'] = $p_header['crc'];
3241
3242 // ----- Return
3243 return $v_result;
3244 }
3245 // --------------------------------------------------------------------------------
3246
3247 // --------------------------------------------------------------------------------
3248 // Function : privExtractByRule()
3249 // Description :
3250 // Extract a file or directory depending of rules (by index, by name, ...)
3251 // Parameters :
3252 // $p_file_list : An array where will be placed the properties of each
3253 // extracted file
3254 // $p_path : Path to add while writing the extracted files
3255 // $p_remove_path : Path to remove (from the file memorized path) while writing the
3256 // extracted files. If the path does not match the file path,
3257 // the file is extracted with its memorized path.
3258 // $p_remove_path does not apply to 'list' mode.
3259 // $p_path and $p_remove_path are commulative.
3260 // Return Values :
3261 // 1 on success,0 or less on error (see error code list)
3262 // --------------------------------------------------------------------------------
3263 function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3264 {
3265 $v_result=1;
3266
3267 // ----- Magic quotes trick
3268 $this->privDisableMagicQuotes();
3269
3270 // ----- Check the path
3271 if ( ($p_path == "")
3272 || ( (substr($p_path, 0, 1) != "/")
3273 && (substr($p_path, 0, 3) != "../")
3274 && (substr($p_path,1,2)!=":/")))
3275 $p_path = "./".$p_path;
3276
3277 // ----- Reduce the path last (and duplicated) '/'
3278 if (($p_path != "./") && ($p_path != "/"))
3279 {
3280 // ----- Look for the path end '/'
3281 while (substr($p_path, -1) == "/")
3282 {
3283 $p_path = substr($p_path, 0, strlen($p_path)-1);
3284 }
3285 }
3286
3287 // ----- Look for path to remove format (should end by /)
3288 if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
3289 {
3290 $p_remove_path .= '/';
3291 }
3292 $p_remove_path_size = strlen($p_remove_path);
3293
3294 // ----- Open the zip file
3295 if (($v_result = $this->privOpenFd('rb')) != 1)
3296 {
3297 $this->privSwapBackMagicQuotes();
3298 return $v_result;
3299 }
3300
3301 // ----- Read the central directory informations
3302 $v_central_dir = array();
3303 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3304 {
3305 // ----- Close the zip file
3306 $this->privCloseFd();
3307 $this->privSwapBackMagicQuotes();
3308
3309 return $v_result;
3310 }
3311
3312 // ----- Start at beginning of Central Dir
3313 $v_pos_entry = $v_central_dir['offset'];
3314
3315 // ----- Read each entry
3316 $j_start = 0;
3317 for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
3318 {
3319
3320 // ----- Read next Central dir entry
3321 @rewind($this->zip_fd);
3322 if (@fseek($this->zip_fd, $v_pos_entry))
3323 {
3324 // ----- Close the zip file
3325 $this->privCloseFd();
3326 $this->privSwapBackMagicQuotes();
3327
3328 // ----- Error log
3329 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3330
3331 // ----- Return
3332 return PclZip::errorCode();
3333 }
3334
3335 // ----- Read the file header
3336 $v_header = array();
3337 if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3338 {
3339 // ----- Close the zip file
3340 $this->privCloseFd();
3341 $this->privSwapBackMagicQuotes();
3342
3343 return $v_result;
3344 }
3345
3346 // ----- Store the index
3347 $v_header['index'] = $i;
3348
3349 // ----- Store the file position
3350 $v_pos_entry = ftell($this->zip_fd);
3351
3352 // ----- Look for the specific extract rules
3353 $v_extract = false;
3354
3355 // ----- Look for extract by name rule
3356 if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
3357 && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
3358
3359 // ----- Look if the filename is in the list
3360 for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
3361
3362 // ----- Look for a directory
3363 if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
3364
3365 // ----- Look if the directory is in the filename path
3366 if ( (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
3367 && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
3368 $v_extract = true;
3369 }
3370 }
3371 // ----- Look for a filename
3372 elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
3373 $v_extract = true;
3374 }
3375 }
3376 }
3377
3378 // ----- Look for extract by preg rule
3379 else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
3380 && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
3381
3382 if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
3383 $v_extract = true;
3384 }
3385 }
3386
3387 // ----- Look for extract by index rule
3388 else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
3389 && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
3390
3391 // ----- Look if the index is in the list
3392 for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
3393
3394 if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
3395 $v_extract = true;
3396 }
3397 if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
3398 $j_start = $j+1;
3399 }
3400
3401 if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
3402 break;
3403 }
3404 }
3405 }
3406
3407 // ----- Look for no rule, which means extract all the archive
3408 else {
3409 $v_extract = true;
3410 }
3411
3412 // ----- Check compression method
3413 if ( ($v_extract)
3414 && ( ($v_header['compression'] != 8)
3415 && ($v_header['compression'] != 0))) {
3416 $v_header['status'] = 'unsupported_compression';
3417
3418 // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3419 if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3420 && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3421
3422 $this->privSwapBackMagicQuotes();
3423
3424 PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
3425 "Filename '".$v_header['stored_filename']."' is "
3426 ."compressed by an unsupported compression "
3427 ."method (".$v_header['compression'].") ");
3428
3429 return PclZip::errorCode();
3430 }
3431 }
3432
3433 // ----- Check encrypted files
3434 if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
3435 $v_header['status'] = 'unsupported_encryption';
3436
3437 // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3438 if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3439 && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3440
3441 $this->privSwapBackMagicQuotes();
3442
3443 PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
3444 "Unsupported encryption for "
3445 ." filename '".$v_header['stored_filename']
3446 ."'");
3447
3448 return PclZip::errorCode();
3449 }
3450 }
3451
3452 // ----- Look for real extraction
3453 if (($v_extract) && ($v_header['status'] != 'ok')) {
3454 $v_result = $this->privConvertHeader2FileInfo($v_header,
3455 $p_file_list[$v_nb_extracted++]);
3456 if ($v_result != 1) {
3457 $this->privCloseFd();
3458 $this->privSwapBackMagicQuotes();
3459 return $v_result;
3460 }
3461
3462 $v_extract = false;
3463 }
3464
3465 // ----- Look for real extraction
3466 if ($v_extract)
3467 {
3468
3469 // ----- Go to the file position
3470 @rewind($this->zip_fd);
3471 if (@fseek($this->zip_fd, $v_header['offset']))
3472 {
3473 // ----- Close the zip file
3474 $this->privCloseFd();
3475
3476 $this->privSwapBackMagicQuotes();
3477
3478 // ----- Error log
3479 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3480
3481 // ----- Return
3482 return PclZip::errorCode();
3483 }
3484
3485 // ----- Look for extraction as string
3486 if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
3487
3488 $v_string = '';
3489
3490 // ----- Extracting the file
3491 $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options);
3492 if ($v_result1 < 1) {
3493 $this->privCloseFd();
3494 $this->privSwapBackMagicQuotes();
3495 return $v_result1;
3496 }
3497
3498 // ----- Get the only interesting attributes
3499 if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
3500 {
3501 // ----- Close the zip file
3502 $this->privCloseFd();
3503 $this->privSwapBackMagicQuotes();
3504
3505 return $v_result;
3506 }
3507
3508 // ----- Set the file content
3509 $p_file_list[$v_nb_extracted]['content'] = $v_string;
3510
3511 // ----- Next extracted file
3512 $v_nb_extracted++;
3513
3514 // ----- Look for user callback abort
3515 if ($v_result1 == 2) {
3516 break;
3517 }
3518 }
3519 // ----- Look for extraction in standard output
3520 elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
3521 && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
3522 // ----- Extracting the file in standard output
3523 $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
3524 if ($v_result1 < 1) {
3525 $this->privCloseFd();
3526 $this->privSwapBackMagicQuotes();
3527 return $v_result1;
3528 }
3529
3530 // ----- Get the only interesting attributes
3531 if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
3532 $this->privCloseFd();
3533 $this->privSwapBackMagicQuotes();
3534 return $v_result;
3535 }
3536
3537 // ----- Look for user callback abort
3538 if ($v_result1 == 2) {
3539 break;
3540 }
3541 }
3542 // ----- Look for normal extraction
3543 else {
3544 // ----- Extracting the file
3545 $v_result1 = $this->privExtractFile($v_header,
3546 $p_path, $p_remove_path,
3547 $p_remove_all_path,
3548 $p_options);
3549 if ($v_result1 < 1) {
3550 $this->privCloseFd();
3551 $this->privSwapBackMagicQuotes();
3552 return $v_result1;
3553 }
3554
3555 // ----- Get the only interesting attributes
3556 if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
3557 {
3558 // ----- Close the zip file
3559 $this->privCloseFd();
3560 $this->privSwapBackMagicQuotes();
3561
3562 return $v_result;
3563 }
3564
3565 // ----- Look for user callback abort
3566 if ($v_result1 == 2) {
3567 break;
3568 }
3569 }
3570 }
3571 }
3572
3573 // ----- Close the zip file
3574 $this->privCloseFd();
3575 $this->privSwapBackMagicQuotes();
3576
3577 // ----- Return
3578 return $v_result;
3579 }
3580 // --------------------------------------------------------------------------------
3581
3582 // --------------------------------------------------------------------------------
3583 // Function : privExtractFile()
3584 // Description :
3585 // Parameters :
3586 // Return Values :
3587 //
3588 // 1 : ... ?
3589 // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
3590 // --------------------------------------------------------------------------------
3591 function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3592 {
3593 $v_result=1;
3594
3595 // ----- Read the file header
3596 if (($v_result = $this->privReadFileHeader($v_header)) != 1)
3597 {
3598 // ----- Return
3599 return $v_result;
3600 }
3601
3602
3603 // ----- Check that the file header is coherent with $p_entry info
3604 if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
3605 // TBC
3606 }
3607
3608 // ----- Look for all path to remove
3609 if ($p_remove_all_path == true) {
3610 // ----- Look for folder entry that not need to be extracted
3611 if (($p_entry['external']&0x00000010)==0x00000010) {
3612
3613 $p_entry['status'] = "filtered";
3614
3615 return $v_result;
3616 }
3617
3618 // ----- Get the basename of the path
3619 $p_entry['filename'] = basename($p_entry['filename']);
3620 }
3621
3622 // ----- Look for path to remove
3623 else if ($p_remove_path != "")
3624 {
3625 if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
3626 {
3627
3628 // ----- Change the file status
3629 $p_entry['status'] = "filtered";
3630
3631 // ----- Return
3632 return $v_result;
3633 }
3634
3635 $p_remove_path_size = strlen($p_remove_path);
3636 if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
3637 {
3638
3639 // ----- Remove the path
3640 $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
3641
3642 }
3643 }
3644
3645 // ----- Add the path
3646 if ($p_path != '') {
3647 $p_entry['filename'] = $p_path."/".$p_entry['filename'];
3648 }
3649
3650 // ----- Check a base_dir_restriction
3651 if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
3652 $v_inclusion
3653 = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
3654 $p_entry['filename']);
3655 if ($v_inclusion == 0) {
3656
3657 PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
3658 "Filename '".$p_entry['filename']."' is "
3659 ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
3660
3661 return PclZip::errorCode();
3662 }
3663 }
3664
3665 // ----- Look for pre-extract callback
3666 if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
3667
3668 // ----- Generate a local information
3669 $v_local_header = array();
3670 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3671
3672 // ----- Call the callback
3673 // Here I do not use call_user_func() because I need to send a reference to the
3674 // header.
3675 $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
3676 if ($v_result == 0) {
3677 // ----- Change the file status
3678 $p_entry['status'] = "skipped";
3679 $v_result = 1;
3680 }
3681
3682 // ----- Look for abort result
3683 if ($v_result == 2) {
3684 // ----- This status is internal and will be changed in 'skipped'
3685 $p_entry['status'] = "aborted";
3686 $v_result = PCLZIP_ERR_USER_ABORTED;
3687 }
3688
3689 // ----- Update the informations
3690 // Only some fields can be modified
3691 $p_entry['filename'] = $v_local_header['filename'];
3692 }
3693
3694
3695 // ----- Look if extraction should be done
3696 if ($p_entry['status'] == 'ok') {
3697
3698 // ----- Look for specific actions while the file exist
3699 if (file_exists($p_entry['filename']))
3700 {
3701
3702 // ----- Look if file is a directory
3703 if (is_dir($p_entry['filename']))
3704 {
3705
3706 // ----- Change the file status
3707 $p_entry['status'] = "already_a_directory";
3708
3709 // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3710 // For historical reason first PclZip implementation does not stop
3711 // when this kind of error occurs.
3712 if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3713 && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3714
3715 PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
3716 "Filename '".$p_entry['filename']."' is "
3717 ."already used by an existing directory");
3718
3719 return PclZip::errorCode();
3720 }
3721 }
3722 // ----- Look if file is write protected
3723 else if (!is_writeable($p_entry['filename']))
3724 {
3725
3726 // ----- Change the file status
3727 $p_entry['status'] = "write_protected";
3728
3729 // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3730 // For historical reason first PclZip implementation does not stop
3731 // when this kind of error occurs.
3732 if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3733 && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3734
3735 PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
3736 "Filename '".$p_entry['filename']."' exists "
3737 ."and is write protected");
3738
3739 return PclZip::errorCode();
3740 }
3741 }
3742
3743 // ----- Look if the extracted file is older
3744 else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
3745 {
3746 // ----- Change the file status
3747 if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
3748 && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
3749 }
3750 else {
3751 $p_entry['status'] = "newer_exist";
3752
3753 // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3754 // For historical reason first PclZip implementation does not stop
3755 // when this kind of error occurs.
3756 if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3757 && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3758
3759 PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
3760 "Newer version of '".$p_entry['filename']."' exists "
3761 ."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
3762
3763 return PclZip::errorCode();
3764 }
3765 }
3766 }
3767 else {
3768 }
3769 }
3770
3771 // ----- Check the directory availability and create it if necessary
3772 else {
3773 if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
3774 $v_dir_to_check = $p_entry['filename'];
3775 else if (!strstr($p_entry['filename'], "/"))
3776 $v_dir_to_check = "";
3777 else
3778 $v_dir_to_check = dirname($p_entry['filename']);
3779
3780 if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
3781
3782 // ----- Change the file status
3783 $p_entry['status'] = "path_creation_fail";
3784
3785 // ----- Return
3786 //return $v_result;
3787 $v_result = 1;
3788 }
3789 }
3790 }
3791
3792 // ----- Look if extraction should be done
3793 if ($p_entry['status'] == 'ok') {
3794
3795 // ----- Do the extraction (if not a folder)
3796 if (!(($p_entry['external']&0x00000010)==0x00000010))
3797 {
3798 // ----- Look for not compressed file
3799 if ($p_entry['compression'] == 0) {
3800
3801 // ----- Opening destination file
3802 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
3803 {
3804
3805 // ----- Change the file status
3806 $p_entry['status'] = "write_error";
3807
3808 // ----- Return
3809 return $v_result;
3810 }
3811
3812
3813 // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3814 $v_size = $p_entry['compressed_size'];
3815 while ($v_size != 0)
3816 {
3817 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3818 $v_buffer = @fread($this->zip_fd, $v_read_size);
3819 @fwrite($v_dest_file, $v_buffer, $v_read_size);
3820 $v_size -= $v_read_size;
3821 }
3822
3823 // ----- Closing the destination file
3824 fclose($v_dest_file);
3825
3826 // ----- Change the file mtime
3827 touch($p_entry['filename'], $p_entry['mtime']);
3828
3829
3830 }
3831 else {
3832 // ----- TBC
3833 // Need to be finished
3834 if (($p_entry['flag'] & 1) == 1) {
3835 PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
3836 return PclZip::errorCode();
3837 }
3838
3839
3840 // ----- Look for using temporary file to unzip
3841 if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
3842 && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
3843 || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
3844 && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) {
3845 $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options);
3846 if ($v_result < PCLZIP_ERR_NO_ERROR) {
3847 return $v_result;
3848 }
3849 }
3850
3851 // ----- Look for extract in memory
3852 else {
3853
3854
3855 // ----- Read the compressed file in a buffer (one shot)
3856 $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3857
3858 // ----- Decompress the file
3859 $v_file_content = @gzinflate($v_buffer);
3860 unset($v_buffer);
3861 if ($v_file_content === FALSE) {
3862
3863 // ----- Change the file status
3864 // TBC
3865 $p_entry['status'] = "error";
3866
3867 return $v_result;
3868 }
3869
3870 // ----- Opening destination file
3871 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3872
3873 // ----- Change the file status
3874 $p_entry['status'] = "write_error";
3875
3876 return $v_result;
3877 }
3878
3879 // ----- Write the uncompressed data
3880 @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
3881 unset($v_file_content);
3882
3883 // ----- Closing the destination file
3884 @fclose($v_dest_file);
3885
3886 }
3887
3888 // ----- Change the file mtime
3889 @touch($p_entry['filename'], $p_entry['mtime']);
3890 }
3891
3892 // ----- Look for chmod option
3893 if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
3894
3895 // ----- Change the mode of the file
3896 @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
3897 }
3898
3899 }
3900 }
3901
3902 // ----- Change abort status
3903 if ($p_entry['status'] == "aborted") {
3904 $p_entry['status'] = "skipped";
3905 }
3906
3907 // ----- Look for post-extract callback
3908 elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
3909
3910 // ----- Generate a local information
3911 $v_local_header = array();
3912 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3913
3914 // ----- Call the callback
3915 // Here I do not use call_user_func() because I need to send a reference to the
3916 // header.
3917 $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
3918
3919 // ----- Look for abort result
3920 if ($v_result == 2) {
3921 $v_result = PCLZIP_ERR_USER_ABORTED;
3922 }
3923 }
3924
3925 // ----- Return
3926 return $v_result;
3927 }
3928 // --------------------------------------------------------------------------------
3929
3930 // --------------------------------------------------------------------------------
3931 // Function : privExtractFileUsingTempFile()
3932 // Description :
3933 // Parameters :
3934 // Return Values :
3935 // --------------------------------------------------------------------------------
3936 function privExtractFileUsingTempFile(&$p_entry, &$p_options)
3937 {
3938 $v_result=1;
3939
3940 // ----- Creates a temporary file
3941 $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
3942 if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
3943 fclose($v_dest_file);
3944 PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
3945 return PclZip::errorCode();
3946 }
3947
3948
3949 // ----- Write gz file format header
3950 $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
3951 @fwrite($v_dest_file, $v_binary_data, 10);
3952
3953 // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3954 $v_size = $p_entry['compressed_size'];
3955 while ($v_size != 0)
3956 {
3957 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3958 $v_buffer = @fread($this->zip_fd, $v_read_size);
3959 //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3960 @fwrite($v_dest_file, $v_buffer, $v_read_size);
3961 $v_size -= $v_read_size;
3962 }
3963
3964 // ----- Write gz file format footer
3965 $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']);
3966 @fwrite($v_dest_file, $v_binary_data, 8);
3967
3968 // ----- Close the temporary file
3969 @fclose($v_dest_file);
3970
3971 // ----- Opening destination file
3972 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3973 $p_entry['status'] = "write_error";
3974 return $v_result;
3975 }
3976
3977 // ----- Open the temporary gz file
3978 if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) {
3979 @fclose($v_dest_file);
3980 $p_entry['status'] = "read_error";
3981 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
3982 return PclZip::errorCode();
3983 }
3984
3985
3986 // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3987 $v_size = $p_entry['size'];
3988 while ($v_size != 0) {
3989 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3990 $v_buffer = @gzread($v_src_file, $v_read_size);
3991 //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3992 @fwrite($v_dest_file, $v_buffer, $v_read_size);
3993 $v_size -= $v_read_size;
3994 }
3995 @fclose($v_dest_file);
3996 @gzclose($v_src_file);
3997
3998 // ----- Delete the temporary file
3999 @unlink($v_gzip_temp_name);
4000
4001 // ----- Return
4002 return $v_result;
4003 }
4004 // --------------------------------------------------------------------------------
4005
4006 // --------------------------------------------------------------------------------
4007 // Function : privExtractFileInOutput()
4008 // Description :
4009 // Parameters :
4010 // Return Values :
4011 // --------------------------------------------------------------------------------
4012 function privExtractFileInOutput(&$p_entry, &$p_options)
4013 {
4014 $v_result=1;
4015
4016 // ----- Read the file header
4017 if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
4018 return $v_result;
4019 }
4020
4021
4022 // ----- Check that the file header is coherent with $p_entry info
4023 if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4024 // TBC
4025 }
4026
4027 // ----- Look for pre-extract callback
4028 if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4029
4030 // ----- Generate a local information
4031 $v_local_header = array();
4032 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4033
4034 // ----- Call the callback
4035 // Here I do not use call_user_func() because I need to send a reference to the
4036 // header.
4037 // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4038 $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4039 if ($v_result == 0) {
4040 // ----- Change the file status
4041 $p_entry['status'] = "skipped";
4042 $v_result = 1;
4043 }
4044
4045 // ----- Look for abort result
4046 if ($v_result == 2) {
4047 // ----- This status is internal and will be changed in 'skipped'
4048 $p_entry['status'] = "aborted";
4049 $v_result = PCLZIP_ERR_USER_ABORTED;
4050 }
4051
4052 // ----- Update the informations
4053 // Only some fields can be modified
4054 $p_entry['filename'] = $v_local_header['filename'];
4055 }
4056
4057 // ----- Trace
4058
4059 // ----- Look if extraction should be done
4060 if ($p_entry['status'] == 'ok') {
4061
4062 // ----- Do the extraction (if not a folder)
4063 if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4064 // ----- Look for not compressed file
4065 if ($p_entry['compressed_size'] == $p_entry['size']) {
4066
4067 // ----- Read the file in a buffer (one shot)
4068 $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4069
4070 // ----- Send the file to the output
4071 echo $v_buffer;
4072 unset($v_buffer);
4073 }
4074 else {
4075
4076 // ----- Read the compressed file in a buffer (one shot)
4077 $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4078
4079 // ----- Decompress the file
4080 $v_file_content = gzinflate($v_buffer);
4081 unset($v_buffer);
4082
4083 // ----- Send the file to the output
4084 echo $v_file_content;
4085 unset($v_file_content);
4086 }
4087 }
4088 }
4089
4090 // ----- Change abort status
4091 if ($p_entry['status'] == "aborted") {
4092 $p_entry['status'] = "skipped";
4093 }
4094
4095 // ----- Look for post-extract callback
4096 elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4097
4098 // ----- Generate a local information
4099 $v_local_header = array();
4100 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4101
4102 // ----- Call the callback
4103 // Here I do not use call_user_func() because I need to send a reference to the
4104 // header.
4105 $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4106
4107 // ----- Look for abort result
4108 if ($v_result == 2) {
4109 $v_result = PCLZIP_ERR_USER_ABORTED;
4110 }
4111 }
4112
4113 return $v_result;
4114 }
4115 // --------------------------------------------------------------------------------
4116
4117 // --------------------------------------------------------------------------------
4118 // Function : privExtractFileAsString()
4119 // Description :
4120 // Parameters :
4121 // Return Values :
4122 // --------------------------------------------------------------------------------
4123 function privExtractFileAsString(&$p_entry, &$p_string, &$p_options)
4124 {
4125 $v_result=1;
4126
4127 // ----- Read the file header
4128 $v_header = array();
4129 if (($v_result = $this->privReadFileHeader($v_header)) != 1)
4130 {
4131 // ----- Return
4132 return $v_result;
4133 }
4134
4135
4136 // ----- Check that the file header is coherent with $p_entry info
4137 if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4138 // TBC
4139 }
4140
4141 // ----- Look for pre-extract callback
4142 if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4143
4144 // ----- Generate a local information
4145 $v_local_header = array();
4146 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4147
4148 // ----- Call the callback
4149 // Here I do not use call_user_func() because I need to send a reference to the
4150 // header.
4151 $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4152 if ($v_result == 0) {
4153 // ----- Change the file status
4154 $p_entry['status'] = "skipped";
4155 $v_result = 1;
4156 }
4157
4158 // ----- Look for abort result
4159 if ($v_result == 2) {
4160 // ----- This status is internal and will be changed in 'skipped'
4161 $p_entry['status'] = "aborted";
4162 $v_result = PCLZIP_ERR_USER_ABORTED;
4163 }
4164
4165 // ----- Update the informations
4166 // Only some fields can be modified
4167 $p_entry['filename'] = $v_local_header['filename'];
4168 }
4169
4170
4171 // ----- Look if extraction should be done
4172 if ($p_entry['status'] == 'ok') {
4173
4174 // ----- Do the extraction (if not a folder)
4175 if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4176 // ----- Look for not compressed file
4177 // if ($p_entry['compressed_size'] == $p_entry['size'])
4178 if ($p_entry['compression'] == 0) {
4179
4180 // ----- Reading the file
4181 $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
4182 }
4183 else {
4184
4185 // ----- Reading the file
4186 $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
4187
4188 // ----- Decompress the file
4189 if (($p_string = @gzinflate($v_data)) === FALSE) {
4190 // TBC
4191 }
4192 }
4193
4194 // ----- Trace
4195 }
4196 else {
4197 // TBC : error : can not extract a folder in a string
4198 }
4199
4200 }
4201
4202 // ----- Change abort status
4203 if ($p_entry['status'] == "aborted") {
4204 $p_entry['status'] = "skipped";
4205 }
4206
4207 // ----- Look for post-extract callback
4208 elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4209
4210 // ----- Generate a local information
4211 $v_local_header = array();
4212 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4213
4214 // ----- Swap the content to header
4215 $v_local_header['content'] = $p_string;
4216 $p_string = '';
4217
4218 // ----- Call the callback
4219 // Here I do not use call_user_func() because I need to send a reference to the
4220 // header.
4221 $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4222
4223 // ----- Swap back the content to header
4224 $p_string = $v_local_header['content'];
4225 unset($v_local_header['content']);
4226
4227 // ----- Look for abort result
4228 if ($v_result == 2) {
4229 $v_result = PCLZIP_ERR_USER_ABORTED;
4230 }
4231 }
4232
4233 // ----- Return
4234 return $v_result;
4235 }
4236 // --------------------------------------------------------------------------------
4237
4238 // --------------------------------------------------------------------------------
4239 // Function : privReadFileHeader()
4240 // Description :
4241 // Parameters :
4242 // Return Values :
4243 // --------------------------------------------------------------------------------
4244 function privReadFileHeader(&$p_header)
4245 {
4246 $v_result=1;
4247
4248 // ----- Read the 4 bytes signature
4249 $v_binary_data = @fread($this->zip_fd, 4);
4250 $v_data = unpack('Vid', $v_binary_data);
4251
4252 // ----- Check signature
4253 if ($v_data['id'] != 0x04034b50)
4254 {
4255
4256 // ----- Error log
4257 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4258
4259 // ----- Return
4260 return PclZip::errorCode();
4261 }
4262
4263 // ----- Read the first 42 bytes of the header
4264 $v_binary_data = fread($this->zip_fd, 26);
4265
4266 // ----- Look for invalid block size
4267 if (strlen($v_binary_data) != 26)
4268 {
4269 $p_header['filename'] = "";
4270 $p_header['status'] = "invalid_header";
4271
4272 // ----- Error log
4273 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4274
4275 // ----- Return
4276 return PclZip::errorCode();
4277 }
4278
4279 // ----- Extract the values
4280 $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
4281
4282 // ----- Get filename
4283 $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
4284
4285 // ----- Get extra_fields
4286 if ($v_data['extra_len'] != 0) {
4287 $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
4288 }
4289 else {
4290 $p_header['extra'] = '';
4291 }
4292
4293 // ----- Extract properties
4294 $p_header['version_extracted'] = $v_data['version'];
4295 $p_header['compression'] = $v_data['compression'];
4296 $p_header['size'] = $v_data['size'];
4297 $p_header['compressed_size'] = $v_data['compressed_size'];
4298 $p_header['crc'] = $v_data['crc'];
4299 $p_header['flag'] = $v_data['flag'];
4300 $p_header['filename_len'] = $v_data['filename_len'];
4301
4302 // ----- Recuperate date in UNIX format
4303 $p_header['mdate'] = $v_data['mdate'];
4304 $p_header['mtime'] = $v_data['mtime'];
4305 if ($p_header['mdate'] && $p_header['mtime'])
4306 {
4307 // ----- Extract time
4308 $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4309 $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4310 $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4311
4312 // ----- Extract date
4313 $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4314 $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4315 $v_day = $p_header['mdate'] & 0x001F;
4316
4317 // ----- Get UNIX date format
4318 $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4319
4320 }
4321 else
4322 {
4323 $p_header['mtime'] = time();
4324 }
4325
4326 // TBC
4327 //for(reset($v_data); $key = key($v_data); next($v_data)) {
4328 //}
4329
4330 // ----- Set the stored filename
4331 $p_header['stored_filename'] = $p_header['filename'];
4332
4333 // ----- Set the status field
4334 $p_header['status'] = "ok";
4335
4336 // ----- Return
4337 return $v_result;
4338 }
4339 // --------------------------------------------------------------------------------
4340
4341 // --------------------------------------------------------------------------------
4342 // Function : privReadCentralFileHeader()
4343 // Description :
4344 // Parameters :
4345 // Return Values :
4346 // --------------------------------------------------------------------------------
4347 function privReadCentralFileHeader(&$p_header)
4348 {
4349 $v_result=1;
4350
4351 // ----- Read the 4 bytes signature
4352 $v_binary_data = @fread($this->zip_fd, 4);
4353 $v_data = unpack('Vid', $v_binary_data);
4354
4355 // ----- Check signature
4356 if ($v_data['id'] != 0x02014b50)
4357 {
4358
4359 // ----- Error log
4360 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4361
4362 // ----- Return
4363 return PclZip::errorCode();
4364 }
4365
4366 // ----- Read the first 42 bytes of the header
4367 $v_binary_data = fread($this->zip_fd, 42);
4368
4369 // ----- Look for invalid block size
4370 if (strlen($v_binary_data) != 42)
4371 {
4372 $p_header['filename'] = "";
4373 $p_header['status'] = "invalid_header";
4374
4375 // ----- Error log
4376 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4377
4378 // ----- Return
4379 return PclZip::errorCode();
4380 }
4381
4382 // ----- Extract the values
4383 $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);
4384
4385 // ----- Get filename
4386 if ($p_header['filename_len'] != 0)
4387 $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
4388 else
4389 $p_header['filename'] = '';
4390
4391 // ----- Get extra
4392 if ($p_header['extra_len'] != 0)
4393 $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
4394 else
4395 $p_header['extra'] = '';
4396
4397 // ----- Get comment
4398 if ($p_header['comment_len'] != 0)
4399 $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
4400 else
4401 $p_header['comment'] = '';
4402
4403 // ----- Extract properties
4404
4405 // ----- Recuperate date in UNIX format
4406 //if ($p_header['mdate'] && $p_header['mtime'])
4407 // TBC : bug : this was ignoring time with 0/0/0
4408 if (1)
4409 {
4410 // ----- Extract time
4411 $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4412 $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4413 $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4414
4415 // ----- Extract date
4416 $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4417 $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4418 $v_day = $p_header['mdate'] & 0x001F;
4419
4420 // ----- Get UNIX date format
4421 $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4422
4423 }
4424 else
4425 {
4426 $p_header['mtime'] = time();
4427 }
4428
4429 // ----- Set the stored filename
4430 $p_header['stored_filename'] = $p_header['filename'];
4431
4432 // ----- Set default status to ok
4433 $p_header['status'] = 'ok';
4434
4435 // ----- Look if it is a directory
4436 if (substr($p_header['filename'], -1) == '/') {
4437 //$p_header['external'] = 0x41FF0010;
4438 $p_header['external'] = 0x00000010;
4439 }
4440
4441
4442 // ----- Return
4443 return $v_result;
4444 }
4445 // --------------------------------------------------------------------------------
4446
4447 // --------------------------------------------------------------------------------
4448 // Function : privCheckFileHeaders()
4449 // Description :
4450 // Parameters :
4451 // Return Values :
4452 // 1 on success,
4453 // 0 on error;
4454 // --------------------------------------------------------------------------------
4455 function privCheckFileHeaders(&$p_local_header, &$p_central_header)
4456 {
4457 $v_result=1;
4458
4459 // ----- Check the static values
4460 // TBC
4461 if ($p_local_header['filename'] != $p_central_header['filename']) {
4462 }
4463 if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
4464 }
4465 if ($p_local_header['flag'] != $p_central_header['flag']) {
4466 }
4467 if ($p_local_header['compression'] != $p_central_header['compression']) {
4468 }
4469 if ($p_local_header['mtime'] != $p_central_header['mtime']) {
4470 }
4471 if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
4472 }
4473
4474 // ----- Look for flag bit 3
4475 if (($p_local_header['flag'] & 8) == 8) {
4476 $p_local_header['size'] = $p_central_header['size'];
4477 $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
4478 $p_local_header['crc'] = $p_central_header['crc'];
4479 }
4480
4481 // ----- Return
4482 return $v_result;
4483 }
4484 // --------------------------------------------------------------------------------
4485
4486 // --------------------------------------------------------------------------------
4487 // Function : privReadEndCentralDir()
4488 // Description :
4489 // Parameters :
4490 // Return Values :
4491 // --------------------------------------------------------------------------------
4492 function privReadEndCentralDir(&$p_central_dir)
4493 {
4494 $v_result=1;
4495
4496 // ----- Go to the end of the zip file
4497 $v_size = filesize($this->zipname);
4498 @fseek($this->zip_fd, $v_size);
4499 if (@ftell($this->zip_fd) != $v_size)
4500 {
4501 // ----- Error log
4502 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
4503
4504 // ----- Return
4505 return PclZip::errorCode();
4506 }
4507
4508 // ----- First try : look if this is an archive with no commentaries (most of the time)
4509 // in this case the end of central dir is at 22 bytes of the file end
4510 $v_found = 0;
4511 if ($v_size > 26) {
4512 @fseek($this->zip_fd, $v_size-22);
4513 if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
4514 {
4515 // ----- Error log
4516 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4517
4518 // ----- Return
4519 return PclZip::errorCode();
4520 }
4521
4522 // ----- Read for bytes
4523 $v_binary_data = @fread($this->zip_fd, 4);
4524 $v_data = @unpack('Vid', $v_binary_data);
4525
4526 // ----- Check signature
4527 if ($v_data['id'] == 0x06054b50) {
4528 $v_found = 1;
4529 }
4530
4531 $v_pos = ftell($this->zip_fd);
4532 }
4533
4534 // ----- Go back to the maximum possible size of the Central Dir End Record
4535 if (!$v_found) {
4536 $v_maximum_size = 65557; // 0xFFFF + 22;
4537 if ($v_maximum_size > $v_size)
4538 $v_maximum_size = $v_size;
4539 @fseek($this->zip_fd, $v_size-$v_maximum_size);
4540 if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
4541 {
4542 // ----- Error log
4543 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4544
4545 // ----- Return
4546 return PclZip::errorCode();
4547 }
4548
4549 // ----- Read byte per byte in order to find the signature
4550 $v_pos = ftell($this->zip_fd);
4551 $v_bytes = 0x00000000;
4552 while ($v_pos < $v_size)
4553 {
4554 // ----- Read a byte
4555 $v_byte = @fread($this->zip_fd, 1);
4556
4557 // ----- Add the byte
4558 //$v_bytes = ($v_bytes << 8) | Ord($v_byte);
4559 // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
4560 // Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
4561 $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
4562
4563 // ----- Compare the bytes
4564 if ($v_bytes == 0x504b0506)
4565 {
4566 $v_pos++;
4567 break;
4568 }
4569
4570 $v_pos++;
4571 }
4572
4573 // ----- Look if not found end of central dir
4574 if ($v_pos == $v_size)
4575 {
4576
4577 // ----- Error log
4578 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
4579
4580 // ----- Return
4581 return PclZip::errorCode();
4582 }
4583 }
4584
4585 // ----- Read the first 18 bytes of the header
4586 $v_binary_data = fread($this->zip_fd, 18);
4587
4588 // ----- Look for invalid block size
4589 if (strlen($v_binary_data) != 18)
4590 {
4591
4592 // ----- Error log
4593 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
4594
4595 // ----- Return
4596 return PclZip::errorCode();
4597 }
4598
4599 // ----- Extract the values
4600 $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
4601
4602 // ----- Check the global size
4603 if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
4604
4605 // ----- Removed in release 2.2 see readme file
4606 // The check of the file size is a little too strict.
4607 // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
4608 // While decrypted, zip has training 0 bytes
4609 if (0) {
4610 // ----- Error log
4611 PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
4612 'The central dir is not at the end of the archive.'
4613 .' Some trailing bytes exists after the archive.');
4614
4615 // ----- Return
4616 return PclZip::errorCode();
4617 }
4618 }
4619
4620 // ----- Get comment
4621 if ($v_data['comment_size'] != 0) {
4622 $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
4623 }
4624 else
4625 $p_central_dir['comment'] = '';
4626
4627 $p_central_dir['entries'] = $v_data['entries'];
4628 $p_central_dir['disk_entries'] = $v_data['disk_entries'];
4629 $p_central_dir['offset'] = $v_data['offset'];
4630 $p_central_dir['size'] = $v_data['size'];
4631 $p_central_dir['disk'] = $v_data['disk'];
4632 $p_central_dir['disk_start'] = $v_data['disk_start'];
4633
4634 // TBC
4635 //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
4636 //}
4637
4638 // ----- Return
4639 return $v_result;
4640 }
4641 // --------------------------------------------------------------------------------
4642
4643 // --------------------------------------------------------------------------------
4644 // Function : privDeleteByRule()
4645 // Description :
4646 // Parameters :
4647 // Return Values :
4648 // --------------------------------------------------------------------------------
4649 function privDeleteByRule(&$p_result_list, &$p_options)
4650 {
4651 $v_result=1;
4652 $v_list_detail = array();
4653
4654 // ----- Open the zip file
4655 if (($v_result=$this->privOpenFd('rb')) != 1)
4656 {
4657 // ----- Return
4658 return $v_result;
4659 }
4660
4661 // ----- Read the central directory informations
4662 $v_central_dir = array();
4663 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
4664 {
4665 $this->privCloseFd();
4666 return $v_result;
4667 }
4668
4669 // ----- Go to beginning of File
4670 @rewind($this->zip_fd);
4671
4672 // ----- Scan all the files
4673 // ----- Start at beginning of Central Dir
4674 $v_pos_entry = $v_central_dir['offset'];
4675 @rewind($this->zip_fd);
4676 if (@fseek($this->zip_fd, $v_pos_entry))
4677 {
4678 // ----- Close the zip file
4679 $this->privCloseFd();
4680
4681 // ----- Error log
4682 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4683
4684 // ----- Return
4685 return PclZip::errorCode();
4686 }
4687
4688 // ----- Read each entry
4689 $v_header_list = array();
4690 $j_start = 0;
4691 for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
4692 {
4693
4694 // ----- Read the file header
4695 $v_header_list[$v_nb_extracted] = array();
4696 if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
4697 {
4698 // ----- Close the zip file
4699 $this->privCloseFd();
4700
4701 return $v_result;
4702 }
4703
4704
4705 // ----- Store the index
4706 $v_header_list[$v_nb_extracted]['index'] = $i;
4707
4708 // ----- Look for the specific extract rules
4709 $v_found = false;
4710
4711 // ----- Look for extract by name rule
4712 if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
4713 && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
4714
4715 // ----- Look if the filename is in the list
4716 for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
4717
4718 // ----- Look for a directory
4719 if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
4720
4721 // ----- Look if the directory is in the filename path
4722 if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
4723 && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4724 $v_found = true;
4725 }
4726 elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
4727 && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4728 $v_found = true;
4729 }
4730 }
4731 // ----- Look for a filename
4732 elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
4733 $v_found = true;
4734 }
4735 }
4736 }
4737
4738 // ----- Look for extract by preg rule
4739 else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
4740 && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
4741
4742 if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4743 $v_found = true;
4744 }
4745 }
4746
4747 // ----- Look for extract by index rule
4748 else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
4749 && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
4750
4751 // ----- Look if the index is in the list
4752 for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
4753
4754 if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
4755 $v_found = true;
4756 }
4757 if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
4758 $j_start = $j+1;
4759 }
4760
4761 if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
4762 break;
4763 }
4764 }
4765 }
4766 else {
4767 $v_found = true;
4768 }
4769
4770 // ----- Look for deletion
4771 if ($v_found)
4772 {
4773 unset($v_header_list[$v_nb_extracted]);
4774 }
4775 else
4776 {
4777 $v_nb_extracted++;
4778 }
4779 }
4780
4781 // ----- Look if something need to be deleted
4782 if ($v_nb_extracted > 0) {
4783
4784 // ----- Creates a temporay file
4785 $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
4786
4787 // ----- Creates a temporary zip archive
4788 $v_temp_zip = new PclZip($v_zip_temp_name);
4789
4790 // ----- Open the temporary zip file in write mode
4791 if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
4792 $this->privCloseFd();
4793
4794 // ----- Return
4795 return $v_result;
4796 }
4797
4798 // ----- Look which file need to be kept
4799 for ($i=0; $i<sizeof($v_header_list); $i++) {
4800
4801 // ----- Calculate the position of the header
4802 @rewind($this->zip_fd);
4803 if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
4804 // ----- Close the zip file
4805 $this->privCloseFd();
4806 $v_temp_zip->privCloseFd();
4807 @unlink($v_zip_temp_name);
4808
4809 // ----- Error log
4810 PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4811
4812 // ----- Return
4813 return PclZip::errorCode();
4814 }
4815
4816 // ----- Read the file header
4817 $v_local_header = array();
4818 if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
4819 // ----- Close the zip file
4820 $this->privCloseFd();
4821 $v_temp_zip->privCloseFd();
4822 @unlink($v_zip_temp_name);
4823
4824 // ----- Return
4825 return $v_result;
4826 }
4827
4828 // ----- Check that local file header is same as central file header
4829 if ($this->privCheckFileHeaders($v_local_header,
4830 $v_header_list[$i]) != 1) {
4831 // TBC
4832 }
4833 unset($v_local_header);
4834
4835 // ----- Write the file header
4836 if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
4837 // ----- Close the zip file
4838 $this->privCloseFd();
4839 $v_temp_zip->privCloseFd();
4840 @unlink($v_zip_temp_name);
4841
4842 // ----- Return
4843 return $v_result;
4844 }
4845
4846 // ----- Read/write the data block
4847 if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
4848 // ----- Close the zip file
4849 $this->privCloseFd();
4850 $v_temp_zip->privCloseFd();
4851 @unlink($v_zip_temp_name);
4852
4853 // ----- Return
4854 return $v_result;
4855 }
4856 }
4857
4858 // ----- Store the offset of the central dir
4859 $v_offset = @ftell($v_temp_zip->zip_fd);
4860
4861 // ----- Re-Create the Central Dir files header
4862 for ($i=0; $i<sizeof($v_header_list); $i++) {
4863 // ----- Create the file header
4864 if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
4865 $v_temp_zip->privCloseFd();
4866 $this->privCloseFd();
4867 @unlink($v_zip_temp_name);
4868
4869 // ----- Return
4870 return $v_result;
4871 }
4872
4873 // ----- Transform the header to a 'usable' info
4874 $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
4875 }
4876
4877
4878 // ----- Zip file comment
4879 $v_comment = '';
4880 if (isset($p_options[PCLZIP_OPT_COMMENT])) {
4881 $v_comment = $p_options[PCLZIP_OPT_COMMENT];
4882 }
4883
4884 // ----- Calculate the size of the central header
4885 $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
4886
4887 // ----- Create the central dir footer
4888 if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
4889 // ----- Reset the file list
4890 unset($v_header_list);
4891 $v_temp_zip->privCloseFd();
4892 $this->privCloseFd();
4893 @unlink($v_zip_temp_name);
4894
4895 // ----- Return
4896 return $v_result;
4897 }
4898
4899 // ----- Close
4900 $v_temp_zip->privCloseFd();
4901 $this->privCloseFd();
4902
4903 // ----- Delete the zip file
4904 // TBC : I should test the result ...
4905 @unlink($this->zipname);
4906
4907 // ----- Rename the temporary file
4908 // TBC : I should test the result ...
4909 //@rename($v_zip_temp_name, $this->zipname);
4910 PclZipUtilRename($v_zip_temp_name, $this->zipname);
4911
4912 // ----- Destroy the temporary archive
4913 unset($v_temp_zip);
4914 }
4915
4916 // ----- Remove every files : reset the file
4917 else if ($v_central_dir['entries'] != 0) {
4918 $this->privCloseFd();
4919
4920 if (($v_result = $this->privOpenFd('wb')) != 1) {
4921 return $v_result;
4922 }
4923
4924 if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
4925 return $v_result;
4926 }
4927
4928 $this->privCloseFd();
4929 }
4930
4931 // ----- Return
4932 return $v_result;
4933 }
4934 // --------------------------------------------------------------------------------
4935
4936 // --------------------------------------------------------------------------------
4937 // Function : privDirCheck()
4938 // Description :
4939 // Check if a directory exists, if not it creates it and all the parents directory
4940 // which may be useful.
4941 // Parameters :
4942 // $p_dir : Directory path to check.
4943 // Return Values :
4944 // 1 : OK
4945 // -1 : Unable to create directory
4946 // --------------------------------------------------------------------------------
4947 function privDirCheck($p_dir, $p_is_dir=false)
4948 {
4949 $v_result = 1;
4950
4951
4952 // ----- Remove the final '/'
4953 if (($p_is_dir) && (substr($p_dir, -1)=='/'))
4954 {
4955 $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
4956 }
4957
4958 // ----- Check the directory availability
4959 if ((is_dir($p_dir)) || ($p_dir == ""))
4960 {
4961 return 1;
4962 }
4963
4964 // ----- Extract parent directory
4965 $p_parent_dir = dirname($p_dir);
4966
4967 // ----- Just a check
4968 if ($p_parent_dir != $p_dir)
4969 {
4970 // ----- Look for parent directory
4971 if ($p_parent_dir != "")
4972 {
4973 if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
4974 {
4975 return $v_result;
4976 }
4977 }
4978 }
4979
4980 // ----- Create the directory
4981 if (!@mkdir($p_dir, 0777))
4982 {
4983 // ----- Error log
4984 PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
4985
4986 // ----- Return
4987 return PclZip::errorCode();
4988 }
4989
4990 // ----- Return
4991 return $v_result;
4992 }
4993 // --------------------------------------------------------------------------------
4994
4995 // --------------------------------------------------------------------------------
4996 // Function : privMerge()
4997 // Description :
4998 // If $p_archive_to_add does not exist, the function exit with a success result.
4999 // Parameters :
5000 // Return Values :
5001 // --------------------------------------------------------------------------------
5002 function privMerge(&$p_archive_to_add)
5003 {
5004 $v_result=1;
5005
5006 // ----- Look if the archive_to_add exists
5007 if (!is_file($p_archive_to_add->zipname))
5008 {
5009
5010 // ----- Nothing to merge, so merge is a success
5011 $v_result = 1;
5012
5013 // ----- Return
5014 return $v_result;
5015 }
5016
5017 // ----- Look if the archive exists
5018 if (!is_file($this->zipname))
5019 {
5020
5021 // ----- Do a duplicate
5022 $v_result = $this->privDuplicate($p_archive_to_add->zipname);
5023
5024 // ----- Return
5025 return $v_result;
5026 }
5027
5028 // ----- Open the zip file
5029 if (($v_result=$this->privOpenFd('rb')) != 1)
5030 {
5031 // ----- Return
5032 return $v_result;
5033 }
5034
5035 // ----- Read the central directory informations
5036 $v_central_dir = array();
5037 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
5038 {
5039 $this->privCloseFd();
5040 return $v_result;
5041 }
5042
5043 // ----- Go to beginning of File
5044 @rewind($this->zip_fd);
5045
5046 // ----- Open the archive_to_add file
5047 if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
5048 {
5049 $this->privCloseFd();
5050
5051 // ----- Return
5052 return $v_result;
5053 }
5054
5055 // ----- Read the central directory informations
5056 $v_central_dir_to_add = array();
5057 if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
5058 {
5059 $this->privCloseFd();
5060 $p_archive_to_add->privCloseFd();
5061
5062 return $v_result;
5063 }
5064
5065 // ----- Go to beginning of File
5066 @rewind($p_archive_to_add->zip_fd);
5067
5068 // ----- Creates a temporay file
5069 $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
5070
5071 // ----- Open the temporary file in write mode
5072 if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
5073 {
5074 $this->privCloseFd();
5075 $p_archive_to_add->privCloseFd();
5076
5077 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
5078
5079 // ----- Return
5080 return PclZip::errorCode();
5081 }
5082
5083 // ----- Copy the files from the archive to the temporary file
5084 // TBC : Here I should better append the file and go back to erase the central dir
5085 $v_size = $v_central_dir['offset'];
5086 while ($v_size != 0)
5087 {
5088 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5089 $v_buffer = fread($this->zip_fd, $v_read_size);
5090 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5091 $v_size -= $v_read_size;
5092 }
5093
5094 // ----- Copy the files from the archive_to_add into the temporary file
5095 $v_size = $v_central_dir_to_add['offset'];
5096 while ($v_size != 0)
5097 {
5098 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5099 $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
5100 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5101 $v_size -= $v_read_size;
5102 }
5103
5104 // ----- Store the offset of the central dir
5105 $v_offset = @ftell($v_zip_temp_fd);
5106
5107 // ----- Copy the block of file headers from the old archive
5108 $v_size = $v_central_dir['size'];
5109 while ($v_size != 0)
5110 {
5111 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5112 $v_buffer = @fread($this->zip_fd, $v_read_size);
5113 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5114 $v_size -= $v_read_size;
5115 }
5116
5117 // ----- Copy the block of file headers from the archive_to_add
5118 $v_size = $v_central_dir_to_add['size'];
5119 while ($v_size != 0)
5120 {
5121 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5122 $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
5123 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5124 $v_size -= $v_read_size;
5125 }
5126
5127 // ----- Merge the file comments
5128 $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
5129
5130 // ----- Calculate the size of the (new) central header
5131 $v_size = @ftell($v_zip_temp_fd)-$v_offset;
5132
5133 // ----- Swap the file descriptor
5134 // Here is a trick : I swap the temporary fd with the zip fd, in order to use
5135 // the following methods on the temporary fil and not the real archive fd
5136 $v_swap = $this->zip_fd;
5137 $this->zip_fd = $v_zip_temp_fd;
5138 $v_zip_temp_fd = $v_swap;
5139
5140 // ----- Create the central dir footer
5141 if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
5142 {
5143 $this->privCloseFd();
5144 $p_archive_to_add->privCloseFd();
5145 @fclose($v_zip_temp_fd);
5146 $this->zip_fd = null;
5147
5148 // ----- Reset the file list
5149 unset($v_header_list);
5150
5151 // ----- Return
5152 return $v_result;
5153 }
5154
5155 // ----- Swap back the file descriptor
5156 $v_swap = $this->zip_fd;
5157 $this->zip_fd = $v_zip_temp_fd;
5158 $v_zip_temp_fd = $v_swap;
5159
5160 // ----- Close
5161 $this->privCloseFd();
5162 $p_archive_to_add->privCloseFd();
5163
5164 // ----- Close the temporary file
5165 @fclose($v_zip_temp_fd);
5166
5167 // ----- Delete the zip file
5168 // TBC : I should test the result ...
5169 @unlink($this->zipname);
5170
5171 // ----- Rename the temporary file
5172 // TBC : I should test the result ...
5173 //@rename($v_zip_temp_name, $this->zipname);
5174 PclZipUtilRename($v_zip_temp_name, $this->zipname);
5175
5176 // ----- Return
5177 return $v_result;
5178 }
5179 // --------------------------------------------------------------------------------
5180
5181 // --------------------------------------------------------------------------------
5182 // Function : privDuplicate()
5183 // Description :
5184 // Parameters :
5185 // Return Values :
5186 // --------------------------------------------------------------------------------
5187 function privDuplicate($p_archive_filename)
5188 {
5189 $v_result=1;
5190
5191 // ----- Look if the $p_archive_filename exists
5192 if (!is_file($p_archive_filename))
5193 {
5194
5195 // ----- Nothing to duplicate, so duplicate is a success.
5196 $v_result = 1;
5197
5198 // ----- Return
5199 return $v_result;
5200 }
5201
5202 // ----- Open the zip file
5203 if (($v_result=$this->privOpenFd('wb')) != 1)
5204 {
5205 // ----- Return
5206 return $v_result;
5207 }
5208
5209 // ----- Open the temporary file in write mode
5210 if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
5211 {
5212 $this->privCloseFd();
5213
5214 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
5215
5216 // ----- Return
5217 return PclZip::errorCode();
5218 }
5219
5220 // ----- Copy the files from the archive to the temporary file
5221 // TBC : Here I should better append the file and go back to erase the central dir
5222 $v_size = filesize($p_archive_filename);
5223 while ($v_size != 0)
5224 {
5225 $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5226 $v_buffer = fread($v_zip_temp_fd, $v_read_size);
5227 @fwrite($this->zip_fd, $v_buffer, $v_read_size);
5228 $v_size -= $v_read_size;
5229 }
5230
5231 // ----- Close
5232 $this->privCloseFd();
5233
5234 // ----- Close the temporary file
5235 @fclose($v_zip_temp_fd);
5236
5237 // ----- Return
5238 return $v_result;
5239 }
5240 // --------------------------------------------------------------------------------
5241
5242 // --------------------------------------------------------------------------------
5243 // Function : privErrorLog()
5244 // Description :
5245 // Parameters :
5246 // --------------------------------------------------------------------------------
5247 function privErrorLog($p_error_code=0, $p_error_string='')
5248 {
5249 if (PCLZIP_ERROR_EXTERNAL == 1) {
5250 PclError($p_error_code, $p_error_string);
5251 }
5252 else {
5253 $this->error_code = $p_error_code;
5254 $this->error_string = $p_error_string;
5255 }
5256 }
5257 // --------------------------------------------------------------------------------
5258
5259 // --------------------------------------------------------------------------------
5260 // Function : privErrorReset()
5261 // Description :
5262 // Parameters :
5263 // --------------------------------------------------------------------------------
5264 function privErrorReset()
5265 {
5266 if (PCLZIP_ERROR_EXTERNAL == 1) {
5267 PclErrorReset();
5268 }
5269 else {
5270 $this->error_code = 0;
5271 $this->error_string = '';
5272 }
5273 }
5274 // --------------------------------------------------------------------------------
5275
5276 // --------------------------------------------------------------------------------
5277 // Function : privDisableMagicQuotes()
5278 // Description :
5279 // Parameters :
5280 // Return Values :
5281 // --------------------------------------------------------------------------------
5282 function privDisableMagicQuotes()
5283 {
5284 $v_result=1;
5285
5286 // ----- Look if function exists
5287 if ( (!function_exists("get_magic_quotes_runtime"))
5288 || (!function_exists("set_magic_quotes_runtime"))) {
5289 return $v_result;
5290 }
5291
5292 // ----- Look if already done
5293 if ($this->magic_quotes_status != -1) {
5294 return $v_result;
5295 }
5296
5297 // ----- Get and memorize the magic_quote value
5298 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
5299 $this->magic_quotes_status = @get_magic_quotes_runtime();
5300
5301 // ----- Disable magic_quotes
5302 if ($this->magic_quotes_status == 1) {
5303 @set_magic_quotes_runtime(0);
5304 }
5305 }
5306 // ----- Return
5307 return $v_result;
5308 }
5309 // --------------------------------------------------------------------------------
5310
5311 // --------------------------------------------------------------------------------
5312 // Function : privSwapBackMagicQuotes()
5313 // Description :
5314 // Parameters :
5315 // Return Values :
5316 // --------------------------------------------------------------------------------
5317 function privSwapBackMagicQuotes()
5318 {
5319 $v_result=1;
5320
5321 // ----- Look if function exists
5322 if ( (!function_exists("get_magic_quotes_runtime"))
5323 || (!function_exists("set_magic_quotes_runtime"))) {
5324 return $v_result;
5325 }
5326
5327 // ----- Look if something to do
5328 if ($this->magic_quotes_status != -1) {
5329 return $v_result;
5330 }
5331
5332 // ----- Swap back magic_quotes
5333 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
5334 if ($this->magic_quotes_status == 1) {
5335 @set_magic_quotes_runtime($this->magic_quotes_status);
5336 }
5337 }
5338 // ----- Return
5339 return $v_result;
5340 }
5341 // --------------------------------------------------------------------------------
5342
5343 }
5344 // End of class
5345 // --------------------------------------------------------------------------------
5346
5347 // --------------------------------------------------------------------------------
5348 // Function : PclZipUtilPathReduction()
5349 // Description :
5350 // Parameters :
5351 // Return Values :
5352 // --------------------------------------------------------------------------------
5353 function PclZipUtilPathReduction($p_dir)
5354 {
5355 $v_result = "";
5356
5357 // ----- Look for not empty path
5358 if ($p_dir != "") {
5359 // ----- Explode path by directory names
5360 $v_list = explode("/", $p_dir);
5361
5362 // ----- Study directories from last to first
5363 $v_skip = 0;
5364 for ($i=sizeof($v_list)-1; $i>=0; $i--) {
5365 // ----- Look for current path
5366 if ($v_list[$i] == ".") {
5367 // ----- Ignore this directory
5368 // Should be the first $i=0, but no check is done
5369 }
5370 else if ($v_list[$i] == "..") {
5371 $v_skip++;
5372 }
5373 else if ($v_list[$i] == "") {
5374 // ----- First '/' i.e. root slash
5375 if ($i == 0) {
5376 $v_result = "/".$v_result;
5377 if ($v_skip > 0) {
5378 // ----- It is an invalid path, so the path is not modified
5379 // TBC
5380 $v_result = $p_dir;
5381 $v_skip = 0;
5382 }
5383 }
5384 // ----- Last '/' i.e. indicates a directory
5385 else if ($i == (sizeof($v_list)-1)) {
5386 $v_result = $v_list[$i];
5387 }
5388 // ----- Double '/' inside the path
5389 else {
5390 // ----- Ignore only the double '//' in path,
5391 // but not the first and last '/'
5392 }
5393 }
5394 else {
5395 // ----- Look for item to skip
5396 if ($v_skip > 0) {
5397 $v_skip--;
5398 }
5399 else {
5400 $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
5401 }
5402 }
5403 }
5404
5405 // ----- Look for skip
5406 if ($v_skip > 0) {
5407 while ($v_skip > 0) {
5408 $v_result = '../'.$v_result;
5409 $v_skip--;
5410 }
5411 }
5412 }
5413
5414 // ----- Return
5415 return $v_result;
5416 }
5417 // --------------------------------------------------------------------------------
5418
5419 // --------------------------------------------------------------------------------
5420 // Function : PclZipUtilPathInclusion()
5421 // Description :
5422 // This function indicates if the path $p_path is under the $p_dir tree. Or,
5423 // said in an other way, if the file or sub-dir $p_path is inside the dir
5424 // $p_dir.
5425 // The function indicates also if the path is exactly the same as the dir.
5426 // This function supports path with duplicated '/' like '//', but does not
5427 // support '.' or '..' statements.
5428 // Parameters :
5429 // Return Values :
5430 // 0 if $p_path is not inside directory $p_dir
5431 // 1 if $p_path is inside directory $p_dir
5432 // 2 if $p_path is exactly the same as $p_dir
5433 // --------------------------------------------------------------------------------
5434 function PclZipUtilPathInclusion($p_dir, $p_path)
5435 {
5436 $v_result = 1;
5437
5438 // ----- Look for path beginning by ./
5439 if ( ($p_dir == '.')
5440 || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
5441 $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
5442 }
5443 if ( ($p_path == '.')
5444 || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
5445 $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
5446 }
5447
5448 // ----- Explode dir and path by directory separator
5449 $v_list_dir = explode("/", $p_dir);
5450 $v_list_dir_size = sizeof($v_list_dir);
5451 $v_list_path = explode("/", $p_path);
5452 $v_list_path_size = sizeof($v_list_path);
5453
5454 // ----- Study directories paths
5455 $i = 0;
5456 $j = 0;
5457 while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
5458
5459 // ----- Look for empty dir (path reduction)
5460 if ($v_list_dir[$i] == '') {
5461 $i++;
5462 continue;
5463 }
5464 if ($v_list_path[$j] == '') {
5465 $j++;
5466 continue;
5467 }
5468
5469 // ----- Compare the items
5470 if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
5471 $v_result = 0;
5472 }
5473
5474 // ----- Next items
5475 $i++;
5476 $j++;
5477 }
5478
5479 // ----- Look if everything seems to be the same
5480 if ($v_result) {
5481 // ----- Skip all the empty items
5482 while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
5483 while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
5484
5485 if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
5486 // ----- There are exactly the same
5487 $v_result = 2;
5488 }
5489 else if ($i < $v_list_dir_size) {
5490 // ----- The path is shorter than the dir
5491 $v_result = 0;
5492 }
5493 }
5494
5495 // ----- Return
5496 return $v_result;
5497 }
5498 // --------------------------------------------------------------------------------
5499
5500 // --------------------------------------------------------------------------------
5501 // Function : PclZipUtilCopyBlock()
5502 // Description :
5503 // Parameters :
5504 // $p_mode : read/write compression mode
5505 // 0 : src & dest normal
5506 // 1 : src gzip, dest normal
5507 // 2 : src normal, dest gzip
5508 // 3 : src & dest gzip
5509 // Return Values :
5510 // --------------------------------------------------------------------------------
5511 function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
5512 {
5513 $v_result = 1;
5514
5515 if ($p_mode==0)
5516 {
5517 while ($p_size != 0)
5518 {
5519 $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5520 $v_buffer = @fread($p_src, $v_read_size);
5521 @fwrite($p_dest, $v_buffer, $v_read_size);
5522 $p_size -= $v_read_size;
5523 }
5524 }
5525 else if ($p_mode==1)
5526 {
5527 while ($p_size != 0)
5528 {
5529 $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5530 $v_buffer = @gzread($p_src, $v_read_size);
5531 @fwrite($p_dest, $v_buffer, $v_read_size);
5532 $p_size -= $v_read_size;
5533 }
5534 }
5535 else if ($p_mode==2)
5536 {
5537 while ($p_size != 0)
5538 {
5539 $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5540 $v_buffer = @fread($p_src, $v_read_size);
5541 @gzwrite($p_dest, $v_buffer, $v_read_size);
5542 $p_size -= $v_read_size;
5543 }
5544 }
5545 else if ($p_mode==3)
5546 {
5547 while ($p_size != 0)
5548 {
5549 $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5550 $v_buffer = @gzread($p_src, $v_read_size);
5551 @gzwrite($p_dest, $v_buffer, $v_read_size);
5552 $p_size -= $v_read_size;
5553 }
5554 }
5555
5556 // ----- Return
5557 return $v_result;
5558 }
5559 // --------------------------------------------------------------------------------
5560
5561 // --------------------------------------------------------------------------------
5562 // Function : PclZipUtilRename()
5563 // Description :
5564 // This function tries to do a simple rename() function. If it fails, it
5565 // tries to copy the $p_src file in a new $p_dest file and then unlink the
5566 // first one.
5567 // Parameters :
5568 // $p_src : Old filename
5569 // $p_dest : New filename
5570 // Return Values :
5571 // 1 on success, 0 on failure.
5572 // --------------------------------------------------------------------------------
5573 function PclZipUtilRename($p_src, $p_dest)
5574 {
5575 $v_result = 1;
5576
5577 // ----- Try to rename the files
5578 if (!@rename($p_src, $p_dest)) {
5579
5580 // ----- Try to copy & unlink the src
5581 if (!@copy($p_src, $p_dest)) {
5582 $v_result = 0;
5583 }
5584 else if (!@unlink($p_src)) {
5585 $v_result = 0;
5586 }
5587 }
5588
5589 // ----- Return
5590 return $v_result;
5591 }
5592 // --------------------------------------------------------------------------------
5593
5594 // --------------------------------------------------------------------------------
5595 // Function : PclZipUtilOptionText()
5596 // Description :
5597 // Translate option value in text. Mainly for debug purpose.
5598 // Parameters :
5599 // $p_option : the option value.
5600 // Return Values :
5601 // The option text value.
5602 // --------------------------------------------------------------------------------
5603 function PclZipUtilOptionText($p_option)
5604 {
5605
5606 $v_list = get_defined_constants();
5607 for (reset($v_list); $v_key = key($v_list); next($v_list)) {
5608 $v_prefix = substr($v_key, 0, 10);
5609 if (( ($v_prefix == 'PCLZIP_OPT')
5610 || ($v_prefix == 'PCLZIP_CB_')
5611 || ($v_prefix == 'PCLZIP_ATT'))
5612 && ($v_list[$v_key] == $p_option)) {
5613 return $v_key;
5614 }
5615 }
5616
5617 $v_result = 'Unknown';
5618
5619 return $v_result;
5620 }
5621 // --------------------------------------------------------------------------------
5622
5623 // --------------------------------------------------------------------------------
5624 // Function : PclZipUtilTranslateWinPath()
5625 // Description :
5626 // Translate windows path by replacing '\' by '/' and optionally removing
5627 // drive letter.
5628 // Parameters :
5629 // $p_path : path to translate.
5630 // $p_remove_disk_letter : true | false
5631 // Return Values :
5632 // The path translated.
5633 // --------------------------------------------------------------------------------
5634 function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
5635 {
5636 if (stristr(php_uname(), 'windows')) {
5637 // ----- Look for potential disk letter
5638 if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
5639 $p_path = substr($p_path, $v_position+1);
5640 }
5641 // ----- Change potential windows directory separator
5642 if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
5643 $p_path = strtr($p_path, '\\', '/');
5644 }
5645 }
5646 return $p_path;
5647 }
5648 // --------------------------------------------------------------------------------
5649
5650
5651 ?>
5652