Merge branch 'MDL-52336-master' of git://github.com/marinaglancy/moodle
[moodle.git] / lib / phpexcel / PHPExcel / Shared / PCLZip / pclzip.lib.php
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 // --------------------------------------------------------------------------------
28 // ----- Constants
29 if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
30     define('PCLZIP_READ_BLOCK_SIZE', 2048);
31 }
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 }
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 }
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 }
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 }
81 // --------------------------------------------------------------------------------
82 // ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
83 // --------------------------------------------------------------------------------
85 // ----- Global variables
86 $g_pclzip_version = "2.8.2";
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);
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
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);
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 /* For futur use
170 define('PCLZIP_CB_PRE_LIST', 78005);
171 define('PCLZIP_CB_POST_LIST', 78006);
172 define('PCLZIP_CB_PRE_DELETE', 78007);
173 define('PCLZIP_CB_POST_DELETE', 78008);
174 */
176 // --------------------------------------------------------------------------------
177 // Class : PclZip
178 // Description :
179 //     PclZip is the class that represent a Zip archive.
180 //     The public methods allow the manipulation of the archive.
181 // Attributes :
182 //     Attributes must not be accessed directly.
183 // Methods :
184 //     PclZip() : Object creator
185 //     create() : Creates the Zip archive
186 //     listContent() : List the content of the Zip archive
187 //     extract() : Extract the content of the archive
188 //     properties() : List the properties of the archive
189 // --------------------------------------------------------------------------------
190 class PclZip
192     // ----- Filename of the zip file
193     public $zipname = '';
195     // ----- File descriptor of the zip file
196     public $zip_fd = 0;
198     // ----- Internal error handling
199     public $error_code = 1;
200     public $error_string = '';
202     // ----- Current status of the magic_quotes_runtime
203     // This value store the php configuration for magic_quotes
204     // The class can then disable the magic_quotes and reset it after
205     public $magic_quotes_status;
207     // --------------------------------------------------------------------------------
208     // Function : PclZip()
209     // Description :
210     //     Creates a PclZip object and set the name of the associated Zip archive
211     //     filename.
212     //     Note that no real action is taken, if the archive does not exist it is not
213     //     created. Use create() for that.
214     // --------------------------------------------------------------------------------
215     public function __construct($p_zipname)
216     {
218         // ----- Tests the zlib
219         if (!function_exists('gzopen')) {
220             die('Abort '.basename(__FILE__).' : Missing zlib extensions');
221         }
223         // ----- Set the attributes
224         $this->zipname = $p_zipname;
225         $this->zip_fd = 0;
226         $this->magic_quotes_status = -1;
228         // ----- Return
229         return;
230     }
231     // --------------------------------------------------------------------------------
233     // --------------------------------------------------------------------------------
234     // Function :
235     //     create($p_filelist, $p_add_dir="", $p_remove_dir="")
236     //     create($p_filelist, $p_option, $p_option_value, ...)
237     // Description :
238     //     This method supports two different synopsis. The first one is historical.
239     //     This method creates a Zip Archive. The Zip file is created in the
240     //     filesystem. The files and directories indicated in $p_filelist
241     //     are added in the archive. See the parameters description for the
242     //     supported format of $p_filelist.
243     //     When a directory is in the list, the directory and its content is added
244     //     in the archive.
245     //     In this synopsis, the function takes an optional variable list of
246     //     options. See bellow the supported options.
247     // Parameters :
248     //     $p_filelist : An array containing file or directory names, or
249     //                                 a string containing one filename or one directory name, or
250     //                                 a string containing a list of filenames and/or directory
251     //                                 names separated by spaces.
252     //     $p_add_dir : A path to add before the real path of the archived file,
253     //                                in order to have it memorized in the archive.
254     //     $p_remove_dir : A path to remove from the real path of the file to archive,
255     //                                     in order to have a shorter path memorized in the archive.
256     //                                     When $p_add_dir and $p_remove_dir are set, $p_remove_dir
257     //                                     is removed first, before $p_add_dir is added.
258     // Options :
259     //     PCLZIP_OPT_ADD_PATH :
260     //     PCLZIP_OPT_REMOVE_PATH :
261     //     PCLZIP_OPT_REMOVE_ALL_PATH :
262     //     PCLZIP_OPT_COMMENT :
263     //     PCLZIP_CB_PRE_ADD :
264     //     PCLZIP_CB_POST_ADD :
265     // Return Values :
266     //     0 on failure,
267     //     The list of the added files, with a status of the add action.
268     //     (see PclZip::listContent() for list entry format)
269     // --------------------------------------------------------------------------------
270     public function create($p_filelist)
271     {
272         $v_result=1;
274         // ----- Reset the error handler
275         $this->privErrorReset();
277         // ----- Set default values
278         $v_options = array();
279         $v_options[PCLZIP_OPT_NO_COMPRESSION] = false;
281         // ----- Look for variable options arguments
282         $v_size = func_num_args();
284         // ----- Look for arguments
285         if ($v_size > 1) {
286             // ----- Get the arguments
287             $v_arg_list = func_get_args();
289             // ----- Remove from the options list the first argument
290             array_shift($v_arg_list);
291             $v_size--;
293             // ----- Look for first arg
294             if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
295                 // ----- Parse the options
296                 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (
297                     PCLZIP_OPT_REMOVE_PATH => 'optional',
298                     PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
299                     PCLZIP_OPT_ADD_PATH => 'optional',
300                     PCLZIP_CB_PRE_ADD => 'optional',
301                     PCLZIP_CB_POST_ADD => 'optional',
302                     PCLZIP_OPT_NO_COMPRESSION => 'optional',
303                     PCLZIP_OPT_COMMENT => 'optional',
304                     PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
305                     PCLZIP_OPT_TEMP_FILE_ON => 'optional',
306                     PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
307                     //, PCLZIP_OPT_CRYPT => 'optional'
308                 ));
309                 if ($v_result != 1) {
310                     return 0;
311                 }
312             } else {
313                 // ----- Look for 2 args
314                 // Here we need to support the first historic synopsis of the
315                 // method.
316                 // ----- Get the first argument
317                 $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
319                 // ----- Look for the optional second argument
320                 if ($v_size == 2) {
321                     $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
322                 } elseif ($v_size > 2) {
323                     PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
324                     return 0;
325                 }
326             }
327         }
329         // ----- Look for default option values
330         $this->privOptionDefaultThreshold($v_options);
332         // ----- Init
333         $v_string_list = array();
334         $v_att_list = array();
335         $v_filedescr_list = array();
336         $p_result_list = array();
338         // ----- Look if the $p_filelist is really an array
339         if (is_array($p_filelist)) {
340             // ----- Look if the first element is also an array
341             //             This will mean that this is a file description entry
342             if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
343                 $v_att_list = $p_filelist;
344             } else {
345                 // ----- The list is a list of string names
346                 $v_string_list = $p_filelist;
347             }
348         } elseif (is_string($p_filelist)) {
349             // ----- Look if the $p_filelist is a string
350             // ----- Create a list from the string
351             $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
352         } else {
353             // ----- Invalid variable type for $p_filelist
354             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
355             return 0;
356         }
358         // ----- Reformat the string list
359         if (sizeof($v_string_list) != 0) {
360             foreach ($v_string_list as $v_string) {
361                 if ($v_string != '') {
362                     $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
363                 } else {
364                 }
365             }
366         }
368         // ----- For each file in the list check the attributes
369         $v_supported_attributes = array(
370             PCLZIP_ATT_FILE_NAME => 'mandatory',
371             PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional',
372             PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional',
373             PCLZIP_ATT_FILE_MTIME => 'optional',
374             PCLZIP_ATT_FILE_CONTENT => 'optional',
375             PCLZIP_ATT_FILE_COMMENT => 'optional'
376         );
377         foreach ($v_att_list as $v_entry) {
378             $v_result = $this->privFileDescrParseAtt($v_entry, $v_filedescr_list[], $v_options, $v_supported_attributes);
379             if ($v_result != 1) {
380                 return 0;
381             }
382         }
384         // ----- Expand the filelist (expand directories)
385         $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
386         if ($v_result != 1) {
387             return 0;
388         }
390         // ----- Call the create fct
391         $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
392         if ($v_result != 1) {
393             return 0;
394         }
396         // ----- Return
397         return $p_result_list;
398     }
399     // --------------------------------------------------------------------------------
401     // --------------------------------------------------------------------------------
402     // Function :
403     //     add($p_filelist, $p_add_dir="", $p_remove_dir="")
404     //     add($p_filelist, $p_option, $p_option_value, ...)
405     // Description :
406     //     This method supports two synopsis. The first one is historical.
407     //     This methods add the list of files in an existing archive.
408     //     If a file with the same name already exists, it is added at the end of the
409     //     archive, the first one is still present.
410     //     If the archive does not exist, it is created.
411     // Parameters :
412     //     $p_filelist : An array containing file or directory names, or
413     //                                 a string containing one filename or one directory name, or
414     //                                 a string containing a list of filenames and/or directory
415     //                                 names separated by spaces.
416     //     $p_add_dir : A path to add before the real path of the archived file,
417     //                                in order to have it memorized in the archive.
418     //     $p_remove_dir : A path to remove from the real path of the file to archive,
419     //                                     in order to have a shorter path memorized in the archive.
420     //                                     When $p_add_dir and $p_remove_dir are set, $p_remove_dir
421     //                                     is removed first, before $p_add_dir is added.
422     // Options :
423     //     PCLZIP_OPT_ADD_PATH :
424     //     PCLZIP_OPT_REMOVE_PATH :
425     //     PCLZIP_OPT_REMOVE_ALL_PATH :
426     //     PCLZIP_OPT_COMMENT :
427     //     PCLZIP_OPT_ADD_COMMENT :
428     //     PCLZIP_OPT_PREPEND_COMMENT :
429     //     PCLZIP_CB_PRE_ADD :
430     //     PCLZIP_CB_POST_ADD :
431     // Return Values :
432     //     0 on failure,
433     //     The list of the added files, with a status of the add action.
434     //     (see PclZip::listContent() for list entry format)
435     // --------------------------------------------------------------------------------
436     public function add($p_filelist)
437     {
438         $v_result=1;
440         // ----- Reset the error handler
441         $this->privErrorReset();
443         // ----- Set default values
444         $v_options = array();
445         $v_options[PCLZIP_OPT_NO_COMPRESSION] = false;
447         // ----- Look for variable options arguments
448         $v_size = func_num_args();
450         // ----- Look for arguments
451         if ($v_size > 1) {
452             // ----- Get the arguments
453             $v_arg_list = func_get_args();
455             // ----- Remove form the options list the first argument
456             array_shift($v_arg_list);
457             $v_size--;
459             // ----- Look for first arg
460             if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
461                 // ----- Parse the options
462                 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (
463                     PCLZIP_OPT_REMOVE_PATH => 'optional',
464                     PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
465                     PCLZIP_OPT_ADD_PATH => 'optional',
466                     PCLZIP_CB_PRE_ADD => 'optional',
467                     PCLZIP_CB_POST_ADD => 'optional',
468                     PCLZIP_OPT_NO_COMPRESSION => 'optional',
469                     PCLZIP_OPT_COMMENT => 'optional',
470                     PCLZIP_OPT_ADD_COMMENT => 'optional',
471                     PCLZIP_OPT_PREPEND_COMMENT => 'optional',
472                     PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
473                     PCLZIP_OPT_TEMP_FILE_ON => 'optional',
474                     PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
475                     //, PCLZIP_OPT_CRYPT => 'optional'
476                 ));
477                 if ($v_result != 1) {
478                     return 0;
479                 }
480             } else {
481                 // ----- Look for 2 args
482                 // Here we need to support the first historic synopsis of the
483                 // method.
484                 // ----- Get the first argument
485                 $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
487                 // ----- Look for the optional second argument
488                 if ($v_size == 2) {
489                     $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
490                 } elseif ($v_size > 2) {
491                     // ----- Error log
492                     PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
494                     // ----- Return
495                     return 0;
496                 }
497             }
498         }
500         // ----- Look for default option values
501         $this->privOptionDefaultThreshold($v_options);
503         // ----- Init
504         $v_string_list = array();
505         $v_att_list = array();
506         $v_filedescr_list = array();
507         $p_result_list = array();
509         // ----- Look if the $p_filelist is really an array
510         if (is_array($p_filelist)) {
511             // ----- Look if the first element is also an array
512             //             This will mean that this is a file description entry
513             if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
514                 $v_att_list = $p_filelist;
515             } else {
516                 // ----- The list is a list of string names
517                 $v_string_list = $p_filelist;
518             }
519         } elseif (is_string($p_filelist)) {
520             // ----- Look if the $p_filelist is a string
521             // ----- Create a list from the string
522             $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
523         } else {
524             // ----- Invalid variable type for $p_filelist
525             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
526             return 0;
527         }
529         // ----- Reformat the string list
530         if (sizeof($v_string_list) != 0) {
531             foreach ($v_string_list as $v_string) {
532                 $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
533             }
534         }
536         // ----- For each file in the list check the attributes
537         $v_supported_attributes = array(
538           PCLZIP_ATT_FILE_NAME => 'mandatory',
539           PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional',
540           PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional',
541           PCLZIP_ATT_FILE_MTIME => 'optional',
542           PCLZIP_ATT_FILE_CONTENT => 'optional',
543           PCLZIP_ATT_FILE_COMMENT => 'optional',
544         );
545         foreach ($v_att_list as $v_entry) {
546             $v_result = $this->privFileDescrParseAtt($v_entry, $v_filedescr_list[], $v_options, $v_supported_attributes);
547             if ($v_result != 1) {
548                 return 0;
549             }
550         }
552         // ----- Expand the filelist (expand directories)
553         $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
554         if ($v_result != 1) {
555             return 0;
556         }
558         // ----- Call the create fct
559         $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
560         if ($v_result != 1) {
561             return 0;
562         }
564         // ----- Return
565         return $p_result_list;
566     }
567     // --------------------------------------------------------------------------------
569     // --------------------------------------------------------------------------------
570     // Function : listContent()
571     // Description :
572     //     This public method, gives the list of the files and directories, with their
573     //     properties.
574     //     The properties of each entries in the list are (used also in other functions) :
575     //         filename : Name of the file. For a create or add action it is the filename
576     //                                given by the user. For an extract function it is the filename
577     //                                of the extracted file.
578     //         stored_filename : Name of the file / directory stored in the archive.
579     //         size : Size of the stored file.
580     //         compressed_size : Size of the file's data compressed in the archive
581     //                                             (without the headers overhead)
582     //         mtime : Last known modification date of the file (UNIX timestamp)
583     //         comment : Comment associated with the file
584     //         folder : true | false
585     //         index : index of the file in the archive
586     //         status : status of the action (depending of the action) :
587     //                            Values are :
588     //                                ok : OK !
589     //                                filtered : the file / dir is not extracted (filtered by user)
590     //                                already_a_directory : the file can not be extracted because a
591     //                                                                            directory with the same name already exists
592     //                                write_protected : the file can not be extracted because a file
593     //                                                                    with the same name already exists and is
594     //                                                                    write protected
595     //                                newer_exist : the file was not extracted because a newer file exists
596     //                                path_creation_fail : the file is not extracted because the folder
597     //                                                                         does not exist and can not be created
598     //                                write_error : the file was not extracted because there was a
599     //                                                            error while writing the file
600     //                                read_error : the file was not extracted because there was a error
601     //                                                         while reading the file
602     //                                invalid_header : the file was not extracted because of an archive
603     //                                                                 format error (bad file header)
604     //     Note that each time a method can continue operating when there
605     //     is an action error on a file, the error is only logged in the file status.
606     // Return Values :
607     //     0 on an unrecoverable failure,
608     //     The list of the files in the archive.
609     // --------------------------------------------------------------------------------
610     public function listContent()
611     {
612         $v_result=1;
614         // ----- Reset the error handler
615         $this->privErrorReset();
617         // ----- Check archive
618         if (!$this->privCheckFormat()) {
619             return(0);
620         }
622         // ----- Call the extracting fct
623         $p_list = array();
624         if (($v_result = $this->privList($p_list)) != 1) {
625             unset($p_list);
626             return(0);
627         }
629         // ----- Return
630         return $p_list;
631     }
632     // --------------------------------------------------------------------------------
634     // --------------------------------------------------------------------------------
635     // Function :
636     //     extract($p_path="./", $p_remove_path="")
637     //     extract([$p_option, $p_option_value, ...])
638     // Description :
639     //     This method supports two synopsis. The first one is historical.
640     //     This method extract all the files / directories from the archive to the
641     //     folder indicated in $p_path.
642     //     If you want to ignore the 'root' part of path of the memorized files
643     //     you can indicate this in the optional $p_remove_path parameter.
644     //     By default, if a newer file with the same name already exists, the
645     //     file is not extracted.
646     //
647     //     If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
648     //     are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
649     //     at the end of the path value of PCLZIP_OPT_PATH.
650     // Parameters :
651     //     $p_path : Path where the files and directories are to be extracted
652     //     $p_remove_path : First part ('root' part) of the memorized path
653     //                                        (if any similar) to remove while extracting.
654     // Options :
655     //     PCLZIP_OPT_PATH :
656     //     PCLZIP_OPT_ADD_PATH :
657     //     PCLZIP_OPT_REMOVE_PATH :
658     //     PCLZIP_OPT_REMOVE_ALL_PATH :
659     //     PCLZIP_CB_PRE_EXTRACT :
660     //     PCLZIP_CB_POST_EXTRACT :
661     // Return Values :
662     //     0 or a negative value on failure,
663     //     The list of the extracted files, with a status of the action.
664     //     (see PclZip::listContent() for list entry format)
665     // --------------------------------------------------------------------------------
666     public function extract()
667     {
668         $v_result=1;
670         // ----- Reset the error handler
671         $this->privErrorReset();
673         // ----- Check archive
674         if (!$this->privCheckFormat()) {
675             return(0);
676         }
678         // ----- Set default values
679         $v_options = array();
680     //        $v_path = "./";
681         $v_path = '';
682         $v_remove_path = "";
683         $v_remove_all_path = false;
685         // ----- Look for variable options arguments
686         $v_size = func_num_args();
688         // ----- Default values for option
689         $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
691         // ----- Look for arguments
692         if ($v_size > 0) {
693             // ----- Get the arguments
694             $v_arg_list = func_get_args();
696             // ----- Look for first arg
697             if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
698                 // ----- Parse the options
699                 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (
700                   PCLZIP_OPT_PATH => 'optional',
701                   PCLZIP_OPT_REMOVE_PATH => 'optional',
702                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
703                   PCLZIP_OPT_ADD_PATH => 'optional',
704                   PCLZIP_CB_PRE_EXTRACT => 'optional',
705                   PCLZIP_CB_POST_EXTRACT => 'optional',
706                   PCLZIP_OPT_SET_CHMOD => 'optional',
707                   PCLZIP_OPT_BY_NAME => 'optional',
708                   PCLZIP_OPT_BY_EREG => 'optional',
709                   PCLZIP_OPT_BY_PREG => 'optional',
710                   PCLZIP_OPT_BY_INDEX => 'optional',
711                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
712                   PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
713                   PCLZIP_OPT_REPLACE_NEWER => 'optional',
714                   PCLZIP_OPT_STOP_ON_ERROR => 'optional',
715                   PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
716                   PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
717                   PCLZIP_OPT_TEMP_FILE_ON => 'optional',
718                   PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
719                 ));
720                 if ($v_result != 1) {
721                     return 0;
722                 }
724                 // ----- Set the arguments
725                 if (isset($v_options[PCLZIP_OPT_PATH])) {
726                     $v_path = $v_options[PCLZIP_OPT_PATH];
727                 }
728                 if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
729                     $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
730                 }
731                 if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
732                     $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
733                 }
734                 if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
735                     // ----- Check for '/' in last path char
736                     if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
737                         $v_path .= '/';
738                     }
739                     $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
740                 }
741             } else {
742                 // ----- Look for 2 args
743                 // Here we need to support the first historic synopsis of the
744                 // method.
745                 // ----- Get the first argument
746                 $v_path = $v_arg_list[0];
748                 // ----- Look for the optional second argument
749                 if ($v_size == 2) {
750                     $v_remove_path = $v_arg_list[1];
751                 } elseif ($v_size > 2) {
752                     // ----- Error log
753                     PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
755                     // ----- Return
756                     return 0;
757                 }
758             }
759         }
761         // ----- Look for default option values
762         $this->privOptionDefaultThreshold($v_options);
764         // ----- Trace
766         // ----- Call the extracting fct
767         $p_list = array();
768         $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options);
769         if ($v_result < 1) {
770             unset($p_list);
771             return(0);
772         }
774         // ----- Return
775         return $p_list;
776     }
777     // --------------------------------------------------------------------------------
780     // --------------------------------------------------------------------------------
781     // Function :
782     //     extractByIndex($p_index, $p_path="./", $p_remove_path="")
783     //     extractByIndex($p_index, [$p_option, $p_option_value, ...])
784     // Description :
785     //     This method supports two synopsis. The first one is historical.
786     //     This method is doing a partial extract of the archive.
787     //     The extracted files or folders are identified by their index in the
788     //     archive (from 0 to n).
789     //     Note that if the index identify a folder, only the folder entry is
790     //     extracted, not all the files included in the archive.
791     // Parameters :
792     //     $p_index : A single index (integer) or a string of indexes of files to
793     //                            extract. The form of the string is "0,4-6,8-12" with only numbers
794     //                            and '-' for range or ',' to separate ranges. No spaces or ';'
795     //                            are allowed.
796     //     $p_path : Path where the files and directories are to be extracted
797     //     $p_remove_path : First part ('root' part) of the memorized path
798     //                                        (if any similar) to remove while extracting.
799     // Options :
800     //     PCLZIP_OPT_PATH :
801     //     PCLZIP_OPT_ADD_PATH :
802     //     PCLZIP_OPT_REMOVE_PATH :
803     //     PCLZIP_OPT_REMOVE_ALL_PATH :
804     //     PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
805     //         not as files.
806     //         The resulting content is in a new field 'content' in the file
807     //         structure.
808     //         This option must be used alone (any other options are ignored).
809     //     PCLZIP_CB_PRE_EXTRACT :
810     //     PCLZIP_CB_POST_EXTRACT :
811     // Return Values :
812     //     0 on failure,
813     //     The list of the extracted files, with a status of the action.
814     //     (see PclZip::listContent() for list entry format)
815     // --------------------------------------------------------------------------------
816     //function extractByIndex($p_index, options...)
817     public function extractByIndex($p_index)
818     {
819         $v_result=1;
821         // ----- Reset the error handler
822         $this->privErrorReset();
824         // ----- Check archive
825         if (!$this->privCheckFormat()) {
826             return(0);
827         }
829         // ----- Set default values
830         $v_options = array();
831     //        $v_path = "./";
832         $v_path = '';
833         $v_remove_path = "";
834         $v_remove_all_path = false;
836         // ----- Look for variable options arguments
837         $v_size = func_num_args();
839         // ----- Default values for option
840         $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
842         // ----- Look for arguments
843         if ($v_size > 1) {
844             // ----- Get the arguments
845             $v_arg_list = func_get_args();
847             // ----- Remove form the options list the first argument
848             array_shift($v_arg_list);
849             $v_size--;
851             // ----- Look for first arg
852             if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
853                 // ----- Parse the options
854                 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array(
855                     PCLZIP_OPT_PATH => 'optional',
856                     PCLZIP_OPT_REMOVE_PATH => 'optional',
857                     PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
858                     PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
859                     PCLZIP_OPT_ADD_PATH => 'optional',
860                     PCLZIP_CB_PRE_EXTRACT => 'optional',
861                     PCLZIP_CB_POST_EXTRACT => 'optional',
862                     PCLZIP_OPT_SET_CHMOD => 'optional',
863                     PCLZIP_OPT_REPLACE_NEWER => 'optional',
864                     PCLZIP_OPT_STOP_ON_ERROR => 'optional',
865                     PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
866                     PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
867                     PCLZIP_OPT_TEMP_FILE_ON => 'optional',
868                     PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
869                 ));
870                 if ($v_result != 1) {
871                     return 0;
872                 }
874                 // ----- Set the arguments
875                 if (isset($v_options[PCLZIP_OPT_PATH])) {
876                     $v_path = $v_options[PCLZIP_OPT_PATH];
877                 }
878                 if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
879                     $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
880                 }
881                 if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
882                     $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
883                 }
884                 if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
885                     // ----- Check for '/' in last path char
886                     if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
887                         $v_path .= '/';
888                     }
889                     $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
890                 }
891                 if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
892                     $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
893                 } else {
894                 }
895             } else {
896                 // ----- Look for 2 args
897                 // Here we need to support the first historic synopsis of the
898                 // method.
900                 // ----- Get the first argument
901                 $v_path = $v_arg_list[0];
903                 // ----- Look for the optional second argument
904                 if ($v_size == 2) {
905                     $v_remove_path = $v_arg_list[1];
906                 } elseif ($v_size > 2) {
907                     // ----- Error log
908                     PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
910                     // ----- Return
911                     return 0;
912                 }
913             }
914         }
916         // ----- Trace
918         // ----- Trick
919         // Here I want to reuse extractByRule(), so I need to parse the $p_index
920         // with privParseOptions()
921         $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
922         $v_options_trick = array();
923         $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick, array (PCLZIP_OPT_BY_INDEX => 'optional'));
924         if ($v_result != 1) {
925             return 0;
926         }
927         $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
929         // ----- Look for default option values
930         $this->privOptionDefaultThreshold($v_options);
932         // ----- Call the extracting fct
933         if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
934             return(0);
935         }
937         // ----- Return
938         return $p_list;
939     }
940     // --------------------------------------------------------------------------------
942     // --------------------------------------------------------------------------------
943     // Function :
944     //     delete([$p_option, $p_option_value, ...])
945     // Description :
946     //     This method removes files from the archive.
947     //     If no parameters are given, then all the archive is emptied.
948     // Parameters :
949     //     None or optional arguments.
950     // Options :
951     //     PCLZIP_OPT_BY_INDEX :
952     //     PCLZIP_OPT_BY_NAME :
953     //     PCLZIP_OPT_BY_EREG :
954     //     PCLZIP_OPT_BY_PREG :
955     // Return Values :
956     //     0 on failure,
957     //     The list of the files which are still present in the archive.
958     //     (see PclZip::listContent() for list entry format)
959     // --------------------------------------------------------------------------------
960     public function delete()
961     {
962         $v_result=1;
964         // ----- Reset the error handler
965         $this->privErrorReset();
967         // ----- Check archive
968         if (!$this->privCheckFormat()) {
969             return(0);
970         }
972         // ----- Set default values
973         $v_options = array();
975         // ----- Look for variable options arguments
976         $v_size = func_num_args();
978         // ----- Look for arguments
979         if ($v_size > 0) {
980             // ----- Get the arguments
981             $v_arg_list = func_get_args();
983             // ----- Parse the options
984             $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (
985                 PCLZIP_OPT_BY_NAME => 'optional',
986                 PCLZIP_OPT_BY_EREG => 'optional',
987                 PCLZIP_OPT_BY_PREG => 'optional',
988                 PCLZIP_OPT_BY_INDEX => 'optional'
989             ));
990             if ($v_result != 1) {
991                     return 0;
992             }
993         }
995         // ----- Magic quotes trick
996         $this->privDisableMagicQuotes();
998         // ----- Call the delete fct
999         $v_list = array();
1000         if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
1001             $this->privSwapBackMagicQuotes();
1002             unset($v_list);
1003             return(0);
1004         }
1006         // ----- Magic quotes trick
1007         $this->privSwapBackMagicQuotes();
1009         // ----- Return
1010         return $v_list;
1011     }
1012     // --------------------------------------------------------------------------------
1014     // --------------------------------------------------------------------------------
1015     // Function : deleteByIndex()
1016     // Description :
1017     //     ***** Deprecated *****
1018     //     delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
1019     // --------------------------------------------------------------------------------
1020     public function deleteByIndex($p_index)
1021     {
1023         $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
1025         // ----- Return
1026         return $p_list;
1027     }
1028     // --------------------------------------------------------------------------------
1030     // --------------------------------------------------------------------------------
1031     // Function : properties()
1032     // Description :
1033     //     This method gives the properties of the archive.
1034     //     The properties are :
1035     //         nb : Number of files in the archive
1036     //         comment : Comment associated with the archive file
1037     //         status : not_exist, ok
1038     // Parameters :
1039     //     None
1040     // Return Values :
1041     //     0 on failure,
1042     //     An array with the archive properties.
1043     // --------------------------------------------------------------------------------
1044     public function properties()
1045     {
1047         // ----- Reset the error handler
1048         $this->privErrorReset();
1050         // ----- Magic quotes trick
1051         $this->privDisableMagicQuotes();
1053         // ----- Check archive
1054         if (!$this->privCheckFormat()) {
1055             $this->privSwapBackMagicQuotes();
1056             return(0);
1057         }
1059         // ----- Default properties
1060         $v_prop = array();
1061         $v_prop['comment'] = '';
1062         $v_prop['nb'] = 0;
1063         $v_prop['status'] = 'not_exist';
1065         // ----- Look if file exists
1066         if (@is_file($this->zipname)) {
1067             // ----- Open the zip file
1068             if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) {
1069                 $this->privSwapBackMagicQuotes();
1071                 // ----- Error log
1072                 PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
1074                 // ----- Return
1075                 return 0;
1076             }
1078             // ----- Read the central directory informations
1079             $v_central_dir = array();
1080             if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
1081                 $this->privSwapBackMagicQuotes();
1082                 return 0;
1083             }
1085             // ----- Close the zip file
1086             $this->privCloseFd();
1088             // ----- Set the user attributes
1089             $v_prop['comment'] = $v_central_dir['comment'];
1090             $v_prop['nb'] = $v_central_dir['entries'];
1091             $v_prop['status'] = 'ok';
1092         }
1094         // ----- Magic quotes trick
1095         $this->privSwapBackMagicQuotes();
1097         // ----- Return
1098         return $v_prop;
1099     }
1100     // --------------------------------------------------------------------------------
1102     // --------------------------------------------------------------------------------
1103     // Function : duplicate()
1104     // Description :
1105     //     This method creates an archive by copying the content of an other one. If
1106     //     the archive already exist, it is replaced by the new one without any warning.
1107     // Parameters :
1108     //     $p_archive : The filename of a valid archive, or
1109     //                                a valid PclZip object.
1110     // Return Values :
1111     //     1 on success.
1112     //     0 or a negative value on error (error code).
1113     // --------------------------------------------------------------------------------
1114     public function duplicate($p_archive)
1115     {
1116         $v_result = 1;
1118         // ----- Reset the error handler
1119         $this->privErrorReset();
1121         // ----- Look if the $p_archive is a PclZip object
1122         if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) {
1123             // ----- Duplicate the archive
1124             $v_result = $this->privDuplicate($p_archive->zipname);
1125         } elseif (is_string($p_archive)) {
1126             // ----- Look if the $p_archive is a string (so a filename)
1127             // ----- Check that $p_archive is a valid zip file
1128             // TBC : Should also check the archive format
1129             if (!is_file($p_archive)) {
1130                 // ----- Error log
1131                 PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
1132                 $v_result = PCLZIP_ERR_MISSING_FILE;
1133             } else {
1134                 // ----- Duplicate the archive
1135                 $v_result = $this->privDuplicate($p_archive);
1136             }
1137         } else {
1138             // ----- Invalid variable
1139             // ----- Error log
1140             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1141             $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1142         }
1144         // ----- Return
1145         return $v_result;
1146     }
1147     // --------------------------------------------------------------------------------
1149     // --------------------------------------------------------------------------------
1150     // Function : merge()
1151     // Description :
1152     //     This method merge the $p_archive_to_add archive at the end of the current
1153     //     one ($this).
1154     //     If the archive ($this) does not exist, the merge becomes a duplicate.
1155     //     If the $p_archive_to_add archive does not exist, the merge is a success.
1156     // Parameters :
1157     //     $p_archive_to_add : It can be directly the filename of a valid zip archive,
1158     //                                             or a PclZip object archive.
1159     // Return Values :
1160     //     1 on success,
1161     //     0 or negative values on error (see below).
1162     // --------------------------------------------------------------------------------
1163     public function merge($p_archive_to_add)
1164     {
1165         $v_result = 1;
1167         // ----- Reset the error handler
1168         $this->privErrorReset();
1170         // ----- Check archive
1171         if (!$this->privCheckFormat()) {
1172             return(0);
1173         }
1175         // ----- Look if the $p_archive_to_add is a PclZip object
1176         if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) {
1177             // ----- Merge the archive
1178             $v_result = $this->privMerge($p_archive_to_add);
1179         } elseif (is_string($p_archive_to_add)) {
1180             // ----- Look if the $p_archive_to_add is a string (so a filename)
1181             // ----- Create a temporary archive
1182             $v_object_archive = new PclZip($p_archive_to_add);
1184             // ----- Merge the archive
1185             $v_result = $this->privMerge($v_object_archive);
1186         } else {
1187             // ----- Invalid variable
1188             // ----- Error log
1189             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1190             $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1191         }
1193         // ----- Return
1194         return $v_result;
1195     }
1196     // --------------------------------------------------------------------------------
1200     // --------------------------------------------------------------------------------
1201     // Function : errorCode()
1202     // Description :
1203     // Parameters :
1204     // --------------------------------------------------------------------------------
1205     public function errorCode()
1206     {
1207         if (PCLZIP_ERROR_EXTERNAL == 1) {
1208             return(PclErrorCode());
1209         } else {
1210             return($this->error_code);
1211         }
1212     }
1213     // --------------------------------------------------------------------------------
1215     // --------------------------------------------------------------------------------
1216     // Function : errorName()
1217     // Description :
1218     // Parameters :
1219     // --------------------------------------------------------------------------------
1220     public function errorName($p_with_code = false)
1221     {
1222         $v_name = array(
1223             PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
1224             PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
1225             PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
1226             PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
1227             PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
1228             PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
1229             PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
1230             PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
1231             PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
1232             PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
1233             PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
1234             PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
1235             PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
1236             PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
1237             PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1238             PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
1239             PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
1240             PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
1241             PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION',
1242             PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE',
1243             PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION',
1244         );
1246         if (isset($v_name[$this->error_code])) {
1247             $v_value = $v_name[$this->error_code];
1248         } else {
1249             $v_value = 'NoName';
1250         }
1252         if ($p_with_code) {
1253             return($v_value.' ('.$this->error_code.')');
1254         } else {
1255             return($v_value);
1256         }
1257     }
1258     // --------------------------------------------------------------------------------
1260     // --------------------------------------------------------------------------------
1261     // Function : errorInfo()
1262     // Description :
1263     // Parameters :
1264     // --------------------------------------------------------------------------------
1265     public function errorInfo($p_full = false)
1266     {
1267         if (PCLZIP_ERROR_EXTERNAL == 1) {
1268             return(PclErrorString());
1269         } else {
1270             if ($p_full) {
1271                 return($this->errorName(true)." : ".$this->error_string);
1272             } else {
1273                 return($this->error_string." [code ".$this->error_code."]");
1274             }
1275         }
1276     }
1277     // --------------------------------------------------------------------------------
1280     // --------------------------------------------------------------------------------
1281     // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1282     // *****                                                                                                                *****
1283     // *****             THESES FUNCTIONS MUST NOT BE USED DIRECTLY             *****
1284     // --------------------------------------------------------------------------------
1288     // --------------------------------------------------------------------------------
1289     // Function : privCheckFormat()
1290     // Description :
1291     //     This method check that the archive exists and is a valid zip archive.
1292     //     Several level of check exists. (futur)
1293     // Parameters :
1294     //     $p_level : Level of check. Default 0.
1295     //                            0 : Check the first bytes (magic codes) (default value))
1296     //                            1 : 0 + Check the central directory (futur)
1297     //                            2 : 1 + Check each file header (futur)
1298     // Return Values :
1299     //     true on success,
1300     //     false on error, the error code is set.
1301     // --------------------------------------------------------------------------------
1302     public function privCheckFormat($p_level = 0)
1303     {
1304         $v_result = true;
1306         // ----- Reset the file system cache
1307         clearstatcache();
1309         // ----- Reset the error handler
1310         $this->privErrorReset();
1312         // ----- Look if the file exits
1313         if (!is_file($this->zipname)) {
1314             // ----- Error log
1315             PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
1316             return(false);
1317         }
1319         // ----- Check that the file is readeable
1320         if (!is_readable($this->zipname)) {
1321             // ----- Error log
1322             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
1323             return(false);
1324         }
1326         // ----- Check the magic code
1327         // TBC
1329         // ----- Check the central header
1330         // TBC
1332         // ----- Check each file header
1333         // TBC
1335         // ----- Return
1336         return $v_result;
1337     }
1338     // --------------------------------------------------------------------------------
1340     // --------------------------------------------------------------------------------
1341     // Function : privParseOptions()
1342     // Description :
1343     //     This internal methods reads the variable list of arguments ($p_options_list,
1344     //     $p_size) and generate an array with the options and values ($v_result_list).
1345     //     $v_requested_options contains the options that can be present and those that
1346     //     must be present.
1347     //     $v_requested_options is an array, with the option value as key, and 'optional',
1348     //     or 'mandatory' as value.
1349     // Parameters :
1350     //     See above.
1351     // Return Values :
1352     //     1 on success.
1353     //     0 on failure.
1354     // --------------------------------------------------------------------------------
1355     public function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options = false)
1356     {
1357         $v_result=1;
1359         // ----- Read the options
1360         $i=0;
1361         while ($i<$p_size) {
1362             // ----- Check if the option is supported
1363             if (!isset($v_requested_options[$p_options_list[$i]])) {
1364                 // ----- Error log
1365                 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1367                 // ----- Return
1368                 return PclZip::errorCode();
1369             }
1371             // ----- Look for next option
1372             switch ($p_options_list[$i]) {
1373                 // ----- Look for options that request a path value
1374                 case PCLZIP_OPT_PATH:
1375                 case PCLZIP_OPT_REMOVE_PATH:
1376                 case PCLZIP_OPT_ADD_PATH:
1377                     // ----- Check the number of parameters
1378                     if (($i+1) >= $p_size) {
1379                         // ----- Error log
1380                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1382                         // ----- Return
1383                         return PclZip::errorCode();
1384                     }
1386                     // ----- Get the value
1387                     $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], false);
1388                     $i++;
1389                     break;
1391                 case PCLZIP_OPT_TEMP_FILE_THRESHOLD:
1392                     // ----- Check the number of parameters
1393                     if (($i+1) >= $p_size) {
1394                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1395                         return PclZip::errorCode();
1396                     }
1398                     // ----- Check for incompatible options
1399                     if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1400                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1401                         return PclZip::errorCode();
1402                     }
1404                     // ----- Check the value
1405                     $v_value = $p_options_list[$i+1];
1406                     if ((!is_integer($v_value)) || ($v_value<0)) {
1407                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1408                         return PclZip::errorCode();
1409                     }
1411                     // ----- Get the value (and convert it in bytes)
1412                     $v_result_list[$p_options_list[$i]] = $v_value*1048576;
1413                     $i++;
1414                     break;
1416                 case PCLZIP_OPT_TEMP_FILE_ON:
1417                     // ----- Check for incompatible options
1418                     if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1419                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1420                         return PclZip::errorCode();
1421                     }
1423                     $v_result_list[$p_options_list[$i]] = true;
1424                     break;
1426                 case PCLZIP_OPT_TEMP_FILE_OFF:
1427                     // ----- Check for incompatible options
1428                     if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
1429                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
1430                         return PclZip::errorCode();
1431                     }
1432                     // ----- Check for incompatible options
1433                     if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1434                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
1435                         return PclZip::errorCode();
1436                     }
1437                     $v_result_list[$p_options_list[$i]] = true;
1438                     break;
1440                 case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION:
1441                     // ----- Check the number of parameters
1442                     if (($i+1) >= $p_size) {
1443                         // ----- Error log
1444                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1445                         // ----- Return
1446                         return PclZip::errorCode();
1447                     }
1449                     // ----- Get the value
1450                     if (is_string($p_options_list[$i+1]) && ($p_options_list[$i+1] != '')) {
1451                         $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], false);
1452                         $i++;
1453                     } else {
1454                     }
1455                     break;
1456                 // ----- Look for options that request an array of string for value
1457                 case PCLZIP_OPT_BY_NAME:
1458                     // ----- Check the number of parameters
1459                     if (($i+1) >= $p_size) {
1460                         // ----- Error log
1461                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1462                         // ----- Return
1463                         return PclZip::errorCode();
1464                     }
1466                     // ----- Get the value
1467                     if (is_string($p_options_list[$i+1])) {
1468                             $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1469                     } elseif (is_array($p_options_list[$i+1])) {
1470                             $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1471                     } else {
1472                         // ----- Error log
1473                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1474                         // ----- Return
1475                         return PclZip::errorCode();
1476                     }
1477                     $i++;
1478                     break;
1479                 // ----- Look for options that request an EREG or PREG expression
1480                 case PCLZIP_OPT_BY_EREG:
1481                     // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
1482                     // to PCLZIP_OPT_BY_PREG
1483                     $p_options_list[$i] = PCLZIP_OPT_BY_PREG;
1484                 case PCLZIP_OPT_BY_PREG:
1485                 //case PCLZIP_OPT_CRYPT :
1486                     // ----- Check the number of parameters
1487                     if (($i+1) >= $p_size) {
1488                         // ----- Error log
1489                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1490                         // ----- Return
1491                         return PclZip::errorCode();
1492                     }
1494                     // ----- Get the value
1495                     if (is_string($p_options_list[$i+1])) {
1496                             $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1497                     } else {
1498                         // ----- Error log
1499                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1500                         // ----- Return
1501                         return PclZip::errorCode();
1502                     }
1503                     $i++;
1504                     break;
1506                 // ----- Look for options that takes a string
1507                 case PCLZIP_OPT_COMMENT:
1508                 case PCLZIP_OPT_ADD_COMMENT:
1509                 case PCLZIP_OPT_PREPEND_COMMENT:
1510                     // ----- Check the number of parameters
1511                     if (($i+1) >= $p_size) {
1512                         // ----- Error log
1513                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1515                         // ----- Return
1516                         return PclZip::errorCode();
1517                     }
1519                     // ----- Get the value
1520                     if (is_string($p_options_list[$i+1])) {
1521                             $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1522                     } else {
1523                         // ----- Error log
1524                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '" .PclZipUtilOptionText($p_options_list[$i]) ."'");
1526                         // ----- Return
1527                         return PclZip::errorCode();
1528                     }
1529                     $i++;
1530                     break;
1532                 // ----- Look for options that request an array of index
1533                 case PCLZIP_OPT_BY_INDEX:
1534                     // ----- Check the number of parameters
1535                     if (($i+1) >= $p_size) {
1536                         // ----- Error log
1537                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1539                         // ----- Return
1540                         return PclZip::errorCode();
1541                     }
1543                     // ----- Get the value
1544                     $v_work_list = array();
1545                     if (is_string($p_options_list[$i+1])) {
1546                         // ----- Remove spaces
1547                         $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
1549                         // ----- Parse items
1550                         $v_work_list = explode(",", $p_options_list[$i+1]);
1551                     } elseif (is_integer($p_options_list[$i+1])) {
1552                             $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1553                     } elseif (is_array($p_options_list[$i+1])) {
1554                             $v_work_list = $p_options_list[$i+1];
1555                     } else {
1556                         // ----- Error log
1557                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1559                         // ----- Return
1560                         return PclZip::errorCode();
1561                     }
1563                     // ----- Reduce the index list
1564                     // each index item in the list must be a couple with a start and
1565                     // an end value : [0,3], [5-5], [8-10], ...
1566                     // ----- Check the format of each item
1567                     $v_sort_flag=false;
1568                     $v_sort_value=0;
1569                     for ($j=0; $j<sizeof($v_work_list); $j++) {
1570                         // ----- Explode the item
1571                         $v_item_list = explode("-", $v_work_list[$j]);
1572                         $v_size_item_list = sizeof($v_item_list);
1574                         // ----- TBC : Here we might check that each item is a
1575                         // real integer ...
1577                         // ----- Look for single value
1578                         if ($v_size_item_list == 1) {
1579                             // ----- Set the option value
1580                             $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1581                             $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1582                         } elseif ($v_size_item_list == 2) {
1583                             // ----- Set the option value
1584                             $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1585                             $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1586                         } else {
1587                             // ----- Error log
1588                             PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1590                             // ----- Return
1591                             return PclZip::errorCode();
1592                         }
1595                         // ----- Look for list sort
1596                         if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1597                             $v_sort_flag=true;
1599                             // ----- TBC : An automatic sort should be writen ...
1600                             // ----- Error log
1601                             PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1603                             // ----- Return
1604                             return PclZip::errorCode();
1605                         }
1606                         $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1607                     }
1609                     // ----- Sort the items
1610                     if ($v_sort_flag) {
1611                         // TBC : To Be Completed
1612                     }
1613                     // ----- Next option
1614                     $i++;
1615                     break;
1616                 // ----- Look for options that request no value
1617                 case PCLZIP_OPT_REMOVE_ALL_PATH:
1618                 case PCLZIP_OPT_EXTRACT_AS_STRING:
1619                 case PCLZIP_OPT_NO_COMPRESSION:
1620                 case PCLZIP_OPT_EXTRACT_IN_OUTPUT:
1621                 case PCLZIP_OPT_REPLACE_NEWER:
1622                 case PCLZIP_OPT_STOP_ON_ERROR:
1623                     $v_result_list[$p_options_list[$i]] = true;
1624                     break;
1625                 // ----- Look for options that request an octal value
1626                 case PCLZIP_OPT_SET_CHMOD:
1627                     // ----- Check the number of parameters
1628                     if (($i+1) >= $p_size) {
1629                         // ----- Error log
1630                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1631                         // ----- Return
1632                         return PclZip::errorCode();
1633                     }
1634                     // ----- Get the value
1635                     $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1636                     $i++;
1637                     break;
1639                 // ----- Look for options that request a call-back
1640                 case PCLZIP_CB_PRE_EXTRACT:
1641                 case PCLZIP_CB_POST_EXTRACT:
1642                 case PCLZIP_CB_PRE_ADD:
1643                 case PCLZIP_CB_POST_ADD:
1644                 /* for futur use
1645                 case PCLZIP_CB_PRE_DELETE :
1646                 case PCLZIP_CB_POST_DELETE :
1647                 case PCLZIP_CB_PRE_LIST :
1648                 case PCLZIP_CB_POST_LIST :
1649                 */
1650                     // ----- Check the number of parameters
1651                     if (($i+1) >= $p_size) {
1652                         // ----- Error log
1653                         PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1654                         // ----- Return
1655                         return PclZip::errorCode();
1656                     }
1658                     // ----- Get the value
1659                     $v_function_name = $p_options_list[$i+1];
1661                     // ----- Check that the value is a valid existing function
1662                     if (!function_exists($v_function_name)) {
1663                         // ----- Error log
1664                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1665                         // ----- Return
1666                         return PclZip::errorCode();
1667                     }
1669                     // ----- Set the attribute
1670                     $v_result_list[$p_options_list[$i]] = $v_function_name;
1671                     $i++;
1672                     break;
1673                 default:
1674                     // ----- Error log
1675                     PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Unknown parameter '" .$p_options_list[$i]."'");
1677                     // ----- Return
1678                     return PclZip::errorCode();
1679             }
1681             // ----- Next options
1682             $i++;
1683         }
1685         // ----- Look for mandatory options
1686         if ($v_requested_options !== false) {
1687             for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1688                 // ----- Look for mandatory option
1689                 if ($v_requested_options[$key] == 'mandatory') {
1690                     // ----- Look if present
1691                     if (!isset($v_result_list[$key])) {
1692                         // ----- Error log
1693                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1695                         // ----- Return
1696                         return PclZip::errorCode();
1697                     }
1698                 }
1699             }
1700         }
1702         // ----- Look for default values
1703         if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1704         }
1706         // ----- Return
1707         return $v_result;
1708     }
1709     // --------------------------------------------------------------------------------
1711     // --------------------------------------------------------------------------------
1712     // Function : privOptionDefaultThreshold()
1713     // Description :
1714     // Parameters :
1715     // Return Values :
1716     // --------------------------------------------------------------------------------
1717     public function privOptionDefaultThreshold(&$p_options)
1718     {
1719         $v_result=1;
1721         if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) {
1722             return $v_result;
1723         }
1725         // ----- Get 'memory_limit' configuration value
1726         $v_memory_limit = ini_get('memory_limit');
1727         $v_memory_limit = trim($v_memory_limit);
1728         $last = strtolower(substr($v_memory_limit, -1));
1730         if ($last == 'g') {
1731             //$v_memory_limit = $v_memory_limit*1024*1024*1024;
1732             $v_memory_limit = $v_memory_limit*1073741824;
1733         }
1734         if ($last == 'm') {
1735             //$v_memory_limit = $v_memory_limit*1024*1024;
1736             $v_memory_limit = $v_memory_limit*1048576;
1737         }
1738         if ($last == 'k') {
1739             $v_memory_limit = $v_memory_limit*1024;
1740         }
1742         $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO);
1744         // ----- Sanity check : No threshold if value lower than 1M
1745         if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
1746             unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
1747         }
1749         // ----- Return
1750         return $v_result;
1751     }
1752     // --------------------------------------------------------------------------------
1754     // --------------------------------------------------------------------------------
1755     // Function : privFileDescrParseAtt()
1756     // Description :
1757     // Parameters :
1758     // Return Values :
1759     //     1 on success.
1760     //     0 on failure.
1761     // --------------------------------------------------------------------------------
1762     public function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options = false)
1763     {
1764         $v_result=1;
1766         // ----- For each file in the list check the attributes
1767         foreach ($p_file_list as $v_key => $v_value) {
1768             // ----- Check if the option is supported
1769             if (!isset($v_requested_options[$v_key])) {
1770                 // ----- Error log
1771                 PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
1773                 // ----- Return
1774                 return PclZip::errorCode();
1775             }
1777             // ----- Look for attribute
1778             switch ($v_key) {
1779                 case PCLZIP_ATT_FILE_NAME:
1780                     if (!is_string($v_value)) {
1781                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1782                         return PclZip::errorCode();
1783                     }
1785                     $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
1787                     if ($p_filedescr['filename'] == '') {
1788                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
1789                         return PclZip::errorCode();
1790                     }
1791                     break;
1792                 case PCLZIP_ATT_FILE_NEW_SHORT_NAME:
1793                     if (!is_string($v_value)) {
1794                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1795                         return PclZip::errorCode();
1796                     }
1798                     $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
1800                     if ($p_filedescr['new_short_name'] == '') {
1801                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
1802                         return PclZip::errorCode();
1803                     }
1804                     break;
1805                 case PCLZIP_ATT_FILE_NEW_FULL_NAME:
1806                     if (!is_string($v_value)) {
1807                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1808                         return PclZip::errorCode();
1809                     }
1811                     $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
1813                     if ($p_filedescr['new_full_name'] == '') {
1814                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
1815                         return PclZip::errorCode();
1816                     }
1817                     break;
1818                 // ----- Look for options that takes a string
1819                 case PCLZIP_ATT_FILE_COMMENT:
1820                     if (!is_string($v_value)) {
1821                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1822                         return PclZip::errorCode();
1823                     }
1824                     $p_filedescr['comment'] = $v_value;
1825                     break;
1826                 case PCLZIP_ATT_FILE_MTIME:
1827                     if (!is_integer($v_value)) {
1828                         PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'");
1829                         return PclZip::errorCode();
1830                     }
1831                     $p_filedescr['mtime'] = $v_value;
1832                     break;
1833                 case PCLZIP_ATT_FILE_CONTENT:
1834                     $p_filedescr['content'] = $v_value;
1835                     break;
1836                 default:
1837                     // ----- Error log
1838                     PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Unknown parameter '".$v_key."'");
1840                     // ----- Return
1841                     return PclZip::errorCode();
1842             }
1844             // ----- Look for mandatory options
1845             if ($v_requested_options !== false) {
1846                 for ($key = reset($v_requested_options); $key = key($v_requested_options); $key = next($v_requested_options)) {
1847                     // ----- Look for mandatory option
1848                     if ($v_requested_options[$key] == 'mandatory') {
1849                         // ----- Look if present
1850                         if (!isset($p_file_list[$key])) {
1851                             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1852                             return PclZip::errorCode();
1853                         }
1854                     }
1855                 }
1856             }
1857         }
1859         // ----- Return
1860         return $v_result;
1861     }
1862     // --------------------------------------------------------------------------------
1864     // --------------------------------------------------------------------------------
1865     // Function : privFileDescrExpand()
1866     // Description :
1867     //     This method look for each item of the list to see if its a file, a folder
1868     //     or a string to be added as file. For any other type of files (link, other)
1869     //     just ignore the item.
1870     //     Then prepare the information that will be stored for that file.
1871     //     When its a folder, expand the folder with all the files that are in that
1872     //     folder (recursively).
1873     // Parameters :
1874     // Return Values :
1875     //     1 on success.
1876     //     0 on failure.
1877     // --------------------------------------------------------------------------------
1878     public function privFileDescrExpand(&$p_filedescr_list, &$p_options)
1879     {
1880         $v_result=1;
1882         // ----- Create a result list
1883         $v_result_list = array();
1885         // ----- Look each entry
1886         for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
1887             // ----- Get filedescr
1888             $v_descr = $p_filedescr_list[$i];
1890             // ----- Reduce the filename
1891             $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
1892             $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
1894             // ----- Look for real file or folder
1895             if (file_exists($v_descr['filename'])) {
1896                 if (@is_file($v_descr['filename'])) {
1897                     $v_descr['type'] = 'file';
1898                 } elseif (@is_dir($v_descr['filename'])) {
1899                     $v_descr['type'] = 'folder';
1900                 } elseif (@is_link($v_descr['filename'])) {
1901                     // skip
1902                     continue;
1903                 } else {
1904                     // skip
1905                     continue;
1906                 }
1907             } elseif (isset($v_descr['content'])) {
1908                 // ----- Look for string added as file
1909                 $v_descr['type'] = 'virtual_file';
1910             } else {
1911                 // ----- Missing file
1912                 // ----- Error log
1913                 PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
1915                 // ----- Return
1916                 return PclZip::errorCode();
1917             }
1919             // ----- Calculate the stored filename
1920             $this->privCalculateStoredFilename($v_descr, $p_options);
1922             // ----- Add the descriptor in result list
1923             $v_result_list[sizeof($v_result_list)] = $v_descr;
1925             // ----- Look for folder
1926             if ($v_descr['type'] == 'folder') {
1927                 // ----- List of items in folder
1928                 $v_dirlist_descr = array();
1929                 $v_dirlist_nb = 0;
1930                 if ($v_folder_handler = @opendir($v_descr['filename'])) {
1931                     while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
1932                         // ----- Skip '.' and '..'
1933                         if (($v_item_handler == '.') || ($v_item_handler == '..')) {
1934                                 continue;
1935                         }
1937                         // ----- Compose the full filename
1938                         $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
1940                         // ----- Look for different stored filename
1941                         // Because the name of the folder was changed, the name of the
1942                         // files/sub-folders also change
1943                         if (($v_descr['stored_filename'] != $v_descr['filename'])
1944                                  && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
1945                             if ($v_descr['stored_filename'] != '') {
1946                                 $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
1947                             } else {
1948                                 $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
1949                             }
1950                         }
1951                         $v_dirlist_nb++;
1952                     }
1954                     @closedir($v_folder_handler);
1955                 } else {
1956                     // TBC : unable to open folder in read mode
1957                 }
1959                 // ----- Expand each element of the list
1960                 if ($v_dirlist_nb != 0) {
1961                     // ----- Expand
1962                     if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
1963                         return $v_result;
1964                     }
1966                     // ----- Concat the resulting list
1967                     $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
1968                 }
1970                 // ----- Free local array
1971                 unset($v_dirlist_descr);
1972             }
1973         }
1975         // ----- Get the result list
1976         $p_filedescr_list = $v_result_list;
1978         // ----- Return
1979         return $v_result;
1980     }
1981     // --------------------------------------------------------------------------------
1983     // --------------------------------------------------------------------------------
1984     // Function : privCreate()
1985     // Description :
1986     // Parameters :
1987     // Return Values :
1988     // --------------------------------------------------------------------------------
1989     public function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
1990     {
1991         $v_result=1;
1992         $v_list_detail = array();
1994         // ----- Magic quotes trick
1995         $this->privDisableMagicQuotes();
1997         // ----- Open the file in write mode
1998         if (($v_result = $this->privOpenFd('wb')) != 1) {
1999             // ----- Return
2000             return $v_result;
2001         }
2003         // ----- Add the list of files
2004         $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
2006         // ----- Close
2007         $this->privCloseFd();
2009         // ----- Magic quotes trick
2010         $this->privSwapBackMagicQuotes();
2012         // ----- Return
2013         return $v_result;
2014     }
2015     // --------------------------------------------------------------------------------
2017     // --------------------------------------------------------------------------------
2018     // Function : privAdd()
2019     // Description :
2020     // Parameters :
2021     // Return Values :
2022     // --------------------------------------------------------------------------------
2023     public function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
2024     {
2025         $v_result=1;
2026         $v_list_detail = array();
2028         // ----- Look if the archive exists or is empty
2029         if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) {
2030             // ----- Do a create
2031             $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
2033             // ----- Return
2034             return $v_result;
2035         }
2036         // ----- Magic quotes trick
2037         $this->privDisableMagicQuotes();
2039         // ----- Open the zip file
2040         if (($v_result=$this->privOpenFd('rb')) != 1) {
2041             // ----- Magic quotes trick
2042             $this->privSwapBackMagicQuotes();
2044             // ----- Return
2045             return $v_result;
2046         }
2048         // ----- Read the central directory informations
2049         $v_central_dir = array();
2050         if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
2051             $this->privCloseFd();
2052             $this->privSwapBackMagicQuotes();
2053             return $v_result;
2054         }
2056         // ----- Go to beginning of File
2057         @rewind($this->zip_fd);
2059         // ----- Creates a temporay file
2060         $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
2062         // ----- Open the temporary file in write mode
2063         if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) {
2064             $this->privCloseFd();
2065             $this->privSwapBackMagicQuotes();
2067             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
2069             // ----- Return
2070             return PclZip::errorCode();
2071         }
2073         // ----- Copy the files from the archive to the temporary file
2074         // TBC : Here I should better append the file and go back to erase the central dir
2075         $v_size = $v_central_dir['offset'];
2076         while ($v_size != 0) {
2077             $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2078             $v_buffer = fread($this->zip_fd, $v_read_size);
2079             @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
2080             $v_size -= $v_read_size;
2081         }
2083         // ----- Swap the file descriptor
2084         // Here is a trick : I swap the temporary fd with the zip fd, in order to use
2085         // the following methods on the temporary fil and not the real archive
2086         $v_swap = $this->zip_fd;
2087         $this->zip_fd = $v_zip_temp_fd;
2088         $v_zip_temp_fd = $v_swap;
2090         // ----- Add the files
2091         $v_header_list = array();
2092         if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) {
2093             fclose($v_zip_temp_fd);
2094             $this->privCloseFd();
2095             @unlink($v_zip_temp_name);
2096             $this->privSwapBackMagicQuotes();
2098             // ----- Return
2099             return $v_result;
2100         }
2102         // ----- Store the offset of the central dir
2103         $v_offset = @ftell($this->zip_fd);
2105         // ----- Copy the block of file headers from the old archive
2106         $v_size = $v_central_dir['size'];
2107         while ($v_size != 0) {
2108             $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2109             $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
2110             @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2111             $v_size -= $v_read_size;
2112         }
2114         // ----- Create the Central Dir files header
2115         for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++) {
2116             // ----- Create the file header
2117             if ($v_header_list[$i]['status'] == 'ok') {
2118                 if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2119                     fclose($v_zip_temp_fd);
2120                     $this->privCloseFd();
2121                     @unlink($v_zip_temp_name);
2122                     $this->privSwapBackMagicQuotes();
2124                     // ----- Return
2125                     return $v_result;
2126                 }
2127                 $v_count++;
2128             }
2130             // ----- Transform the header to a 'usable' info
2131             $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2132         }
2134         // ----- Zip file comment
2135         $v_comment = $v_central_dir['comment'];
2136         if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2137             $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2138         }
2139         if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
2140             $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
2141         }
2142         if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
2143             $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
2144         }
2146         // ----- Calculate the size of the central header
2147         $v_size = @ftell($this->zip_fd)-$v_offset;
2149         // ----- Create the central dir footer
2150         if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) {
2151             // ----- Reset the file list
2152             unset($v_header_list);
2153             $this->privSwapBackMagicQuotes();
2155             // ----- Return
2156             return $v_result;
2157         }
2159         // ----- Swap back the file descriptor
2160         $v_swap = $this->zip_fd;
2161         $this->zip_fd = $v_zip_temp_fd;
2162         $v_zip_temp_fd = $v_swap;
2164         // ----- Close
2165         $this->privCloseFd();
2167         // ----- Close the temporary file
2168         @fclose($v_zip_temp_fd);
2170         // ----- Magic quotes trick
2171         $this->privSwapBackMagicQuotes();
2173         // ----- Delete the zip file
2174         // TBC : I should test the result ...
2175         @unlink($this->zipname);
2177         // ----- Rename the temporary file
2178         // TBC : I should test the result ...
2179         //@rename($v_zip_temp_name, $this->zipname);
2180         PclZipUtilRename($v_zip_temp_name, $this->zipname);
2182         // ----- Return
2183         return $v_result;
2184     }
2185     // --------------------------------------------------------------------------------
2187     // --------------------------------------------------------------------------------
2188     // Function : privOpenFd()
2189     // Description :
2190     // Parameters :
2191     // --------------------------------------------------------------------------------
2192     public function privOpenFd($p_mode)
2193     {
2194         $v_result=1;
2196         // ----- Look if already open
2197         if ($this->zip_fd != 0) {
2198             // ----- Error log
2199             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
2201             // ----- Return
2202             return PclZip::errorCode();
2203         }
2205         // ----- Open the zip file
2206         if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) {
2207             // ----- Error log
2208             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
2210             // ----- Return
2211             return PclZip::errorCode();
2212         }
2214         // ----- Return
2215         return $v_result;
2216     }
2217     // --------------------------------------------------------------------------------
2219     // --------------------------------------------------------------------------------
2220     // Function : privCloseFd()
2221     // Description :
2222     // Parameters :
2223     // --------------------------------------------------------------------------------
2224     public function privCloseFd()
2225     {
2226         $v_result=1;
2228         if ($this->zip_fd != 0) {
2229             @fclose($this->zip_fd);
2230         }
2231         $this->zip_fd = 0;
2233         // ----- Return
2234         return $v_result;
2235     }
2236     // --------------------------------------------------------------------------------
2238     // --------------------------------------------------------------------------------
2239     // Function : privAddList()
2240     // Description :
2241     //     $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2242     //     different from the real path of the file. This is usefull if you want to have PclTar
2243     //     running in any directory, and memorize relative path from an other directory.
2244     // Parameters :
2245     //     $p_list : An array containing the file or directory names to add in the tar
2246     //     $p_result_list : list of added files with their properties (specially the status field)
2247     //     $p_add_dir : Path to add in the filename path archived
2248     //     $p_remove_dir : Path to remove in the filename path archived
2249     // Return Values :
2250     // --------------------------------------------------------------------------------
2251     //    public function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2252     public function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
2253     {
2254         $v_result=1;
2256         // ----- Add the files
2257         $v_header_list = array();
2258         if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) {
2259             // ----- Return
2260             return $v_result;
2261         }
2263         // ----- Store the offset of the central dir
2264         $v_offset = @ftell($this->zip_fd);
2266         // ----- Create the Central Dir files header
2267         for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++) {
2268             // ----- Create the file header
2269             if ($v_header_list[$i]['status'] == 'ok') {
2270                 if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2271                     // ----- Return
2272                     return $v_result;
2273                 }
2274                 $v_count++;
2275             }
2277             // ----- Transform the header to a 'usable' info
2278             $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2279         }
2281         // ----- Zip file comment
2282         $v_comment = '';
2283         if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2284             $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2285         }
2287         // ----- Calculate the size of the central header
2288         $v_size = @ftell($this->zip_fd)-$v_offset;
2290         // ----- Create the central dir footer
2291         if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) {
2292             // ----- Reset the file list
2293             unset($v_header_list);
2295             // ----- Return
2296             return $v_result;
2297         }
2299         // ----- Return
2300         return $v_result;
2301     }
2302     // --------------------------------------------------------------------------------
2304     // --------------------------------------------------------------------------------
2305     // Function : privAddFileList()
2306     // Description :
2307     // Parameters :
2308     //     $p_filedescr_list : An array containing the file description
2309     //                                            or directory names to add in the zip
2310     //     $p_result_list : list of added files with their properties (specially the status field)
2311     // Return Values :
2312     // --------------------------------------------------------------------------------
2313     public function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
2314     {
2315         $v_result=1;
2316         $v_header = array();
2318         // ----- Recuperate the current number of elt in list
2319         $v_nb = sizeof($p_result_list);
2321         // ----- Loop on the files
2322         for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
2323             // ----- Format the filename
2324             $p_filedescr_list[$j]['filename'] = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
2326             // ----- Skip empty file names
2327             // TBC : Can this be possible ? not checked in DescrParseAtt ?
2328             if ($p_filedescr_list[$j]['filename'] == "") {
2329                 continue;
2330             }
2332             // ----- Check the filename
2333             if (($p_filedescr_list[$j]['type'] != 'virtual_file') && (!file_exists($p_filedescr_list[$j]['filename']))) {
2334                 PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
2335                 return PclZip::errorCode();
2336             }
2338             // ----- Look if it is a file or a dir with no all path remove option
2339             // or a dir with all its path removed
2340     //            if (    (is_file($p_filedescr_list[$j]['filename']))
2341     //                    || (    is_dir($p_filedescr_list[$j]['filename'])
2342             if (($p_filedescr_list[$j]['type'] == 'file') || ($p_filedescr_list[$j]['type'] == 'virtual_file') || (($p_filedescr_list[$j]['type'] == 'folder') && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]) || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
2343                 // ----- Add the file
2344                 $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header, $p_options);
2345                 if ($v_result != 1) {
2346                     return $v_result;
2347                 }
2349                 // ----- Store the file infos
2350                 $p_result_list[$v_nb++] = $v_header;
2351             }
2352         }
2354         // ----- Return
2355         return $v_result;
2356     }
2357     // --------------------------------------------------------------------------------
2359     // --------------------------------------------------------------------------------
2360     // Function : privAddFile()
2361     // Description :
2362     // Parameters :
2363     // Return Values :
2364     // --------------------------------------------------------------------------------
2365     public function privAddFile($p_filedescr, &$p_header, &$p_options)
2366     {
2367         $v_result=1;
2369         // ----- Working variable
2370         $p_filename = $p_filedescr['filename'];
2372         // TBC : Already done in the fileAtt check ... ?
2373         if ($p_filename == "") {
2374             // ----- Error log
2375             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
2377             // ----- Return
2378             return PclZip::errorCode();
2379         }
2381         // ----- Look for a stored different filename
2382         /* TBC : Removed
2383         if (isset($p_filedescr['stored_filename'])) {
2384             $v_stored_filename = $p_filedescr['stored_filename'];
2385         }
2386         else {
2387             $v_stored_filename = $p_filedescr['stored_filename'];
2388         }
2389         */
2391         // ----- Set the file properties
2392         clearstatcache();
2393         $p_header['version'] = 20;
2394         $p_header['version_extracted'] = 10;
2395         $p_header['flag'] = 0;
2396         $p_header['compression'] = 0;
2397         $p_header['crc'] = 0;
2398         $p_header['compressed_size'] = 0;
2399         $p_header['filename_len'] = strlen($p_filename);
2400         $p_header['extra_len'] = 0;
2401         $p_header['disk'] = 0;
2402         $p_header['internal'] = 0;
2403         $p_header['offset'] = 0;
2404         $p_header['filename'] = $p_filename;
2405     // TBC : Removed        $p_header['stored_filename'] = $v_stored_filename;
2406         $p_header['stored_filename'] = $p_filedescr['stored_filename'];
2407         $p_header['extra'] = '';
2408         $p_header['status'] = 'ok';
2409         $p_header['index'] = -1;
2411         // ----- Look for regular file
2412         if ($p_filedescr['type']=='file') {
2413             $p_header['external'] = 0x00000000;
2414             $p_header['size'] = filesize($p_filename);
2415         } elseif ($p_filedescr['type']=='folder') {
2416             // ----- Look for regular folder
2417             $p_header['external'] = 0x00000010;
2418             $p_header['mtime'] = filemtime($p_filename);
2419             $p_header['size'] = filesize($p_filename);
2420         } elseif ($p_filedescr['type'] == 'virtual_file') {
2421             // ----- Look for virtual file
2422             $p_header['external'] = 0x00000000;
2423             $p_header['size'] = strlen($p_filedescr['content']);
2424         }
2426         // ----- Look for filetime
2427         if (isset($p_filedescr['mtime'])) {
2428             $p_header['mtime'] = $p_filedescr['mtime'];
2429         } elseif ($p_filedescr['type'] == 'virtual_file') {
2430             $p_header['mtime'] = time();
2431         } else {
2432             $p_header['mtime'] = filemtime($p_filename);
2433         }
2435         // ------ Look for file comment
2436         if (isset($p_filedescr['comment'])) {
2437             $p_header['comment_len'] = strlen($p_filedescr['comment']);
2438             $p_header['comment'] = $p_filedescr['comment'];
2439         } else {
2440             $p_header['comment_len'] = 0;
2441             $p_header['comment'] = '';
2442         }
2444         // ----- Look for pre-add callback
2445         if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
2446             // ----- Generate a local information
2447             $v_local_header = array();
2448             $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2450             // ----- Call the callback
2451             // Here I do not use call_user_func() because I need to send a reference to the
2452             // header.
2453     //            eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
2454             $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
2455             if ($v_result == 0) {
2456                 // ----- Change the file status
2457                 $p_header['status'] = "skipped";
2458                 $v_result = 1;
2459             }
2461             // ----- Update the informations
2462             // Only some fields can be modified
2463             if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2464                 $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
2465             }
2466         }
2468         // ----- Look for empty stored filename
2469         if ($p_header['stored_filename'] == "") {
2470             $p_header['status'] = "filtered";
2471         }
2473         // ----- Check the path length
2474         if (strlen($p_header['stored_filename']) > 0xFF) {
2475             $p_header['status'] = 'filename_too_long';
2476         }
2478         // ----- Look if no error, or file not skipped
2479         if ($p_header['status'] == 'ok') {
2480             // ----- Look for a file
2481             if ($p_filedescr['type'] == 'file') {
2482                 // ----- Look for using temporary file to zip
2483                 if ((!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])))) {
2484                     $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
2485                     if ($v_result < PCLZIP_ERR_NO_ERROR) {
2486                         return $v_result;
2487                     }
2488                 } else {
2489                     // ----- Use "in memory" zip algo
2490                     // ----- Open the source file
2491                     if (($v_file = @fopen($p_filename, "rb")) == 0) {
2492                         PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2493                         return PclZip::errorCode();
2494                     }
2496                     // ----- Read the file content
2497                     $v_content = @fread($v_file, $p_header['size']);
2499                     // ----- Close the file
2500                     @fclose($v_file);
2502                     // ----- Calculate the CRC
2503                     $p_header['crc'] = @crc32($v_content);
2505                     // ----- Look for no compression
2506                     if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2507                         // ----- Set header parameters
2508                         $p_header['compressed_size'] = $p_header['size'];
2509                         $p_header['compression'] = 0;
2510                     } else {
2511                         // ----- Look for normal compression
2512                         // ----- Compress the content
2513                         $v_content = @gzdeflate($v_content);
2515                         // ----- Set header parameters
2516                         $p_header['compressed_size'] = strlen($v_content);
2517                         $p_header['compression'] = 8;
2518                     }
2520                     // ----- Call the header generation
2521                     if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2522                         @fclose($v_file);
2523                         return $v_result;
2524                     }
2526                     // ----- Write the compressed (or not) content
2527                     @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2528                 }
2529             } elseif ($p_filedescr['type'] == 'virtual_file') {
2530                 // ----- Look for a virtual file (a file from string)
2531                 $v_content = $p_filedescr['content'];
2533                 // ----- Calculate the CRC
2534                 $p_header['crc'] = @crc32($v_content);
2536                 // ----- Look for no compression
2537                 if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2538                     // ----- Set header parameters
2539                     $p_header['compressed_size'] = $p_header['size'];
2540                     $p_header['compression'] = 0;
2541                 } else {
2542                     // ----- Look for normal compression
2543                     // ----- Compress the content
2544                     $v_content = @gzdeflate($v_content);
2546                     // ----- Set header parameters
2547                     $p_header['compressed_size'] = strlen($v_content);
2548                     $p_header['compression'] = 8;
2549                 }
2551                 // ----- Call the header generation
2552                 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2553                     @fclose($v_file);
2554                     return $v_result;
2555                 }
2557                 // ----- Write the compressed (or not) content
2558                 @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2559             } elseif ($p_filedescr['type'] == 'folder') {
2560                 // ----- Look for a directory
2561                 // ----- Look for directory last '/'
2562                 if (@substr($p_header['stored_filename'], -1) != '/') {
2563                     $p_header['stored_filename'] .= '/';
2564                 }
2566                 // ----- Set the file properties
2567                 $p_header['size'] = 0;
2568                 //$p_header['external'] = 0x41FF0010;     // Value for a folder : to be checked
2569                 $p_header['external'] = 0x00000010;     // Value for a folder : to be checked
2571                 // ----- Call the header generation
2572                 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2573                     return $v_result;
2574                 }
2575             }
2576         }
2578         // ----- Look for post-add callback
2579         if (isset($p_options[PCLZIP_CB_POST_ADD])) {
2580             // ----- Generate a local information
2581             $v_local_header = array();
2582             $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2584             // ----- Call the callback
2585             // Here I do not use call_user_func() because I need to send a reference to the
2586             // header.
2587     //            eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
2588             $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header);
2589             if ($v_result == 0) {
2590                 // ----- Ignored
2591                 $v_result = 1;
2592             }
2594             // ----- Update the informations
2595             // Nothing can be modified
2596         }
2598         // ----- Return
2599         return $v_result;
2600     }
2601     // --------------------------------------------------------------------------------
2603     // --------------------------------------------------------------------------------
2604     // Function : privAddFileUsingTempFile()
2605     // Description :
2606     // Parameters :
2607     // Return Values :
2608     // --------------------------------------------------------------------------------
2609     public function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
2610     {
2611         $v_result=PCLZIP_ERR_NO_ERROR;
2613         // ----- Working variable
2614         $p_filename = $p_filedescr['filename'];
2617         // ----- Open the source file
2618         if (($v_file = @fopen($p_filename, "rb")) == 0) {
2619             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2620             return PclZip::errorCode();
2621         }
2623         // ----- Creates a compressed temporary file
2624         $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
2625         if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
2626             fclose($v_file);
2627             PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
2628             return PclZip::errorCode();
2629         }
2631         // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2632         $v_size = filesize($p_filename);
2633         while ($v_size != 0) {
2634             $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2635             $v_buffer = @fread($v_file, $v_read_size);
2636             //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2637             @gzputs($v_file_compressed, $v_buffer, $v_read_size);
2638             $v_size -= $v_read_size;
2639         }
2641         // ----- Close the file
2642         @fclose($v_file);
2643         @gzclose($v_file_compressed);
2645         // ----- Check the minimum file size
2646         if (filesize($v_gzip_temp_name) < 18) {
2647             PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
2648             return PclZip::errorCode();
2649         }
2651         // ----- Extract the compressed attributes
2652         if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
2653             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2654             return PclZip::errorCode();
2655         }
2657         // ----- Read the gzip file header
2658         $v_binary_data = @fread($v_file_compressed, 10);
2659         $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
2661         // ----- Check some parameters
2662         $v_data_header['os'] = bin2hex($v_data_header['os']);
2664         // ----- Read the gzip file footer
2665         @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8);
2666         $v_binary_data = @fread($v_file_compressed, 8);
2667         $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);
2669         // ----- Set the attributes
2670         $p_header['compression'] = ord($v_data_header['cm']);
2671         //$p_header['mtime'] = $v_data_header['mtime'];
2672         $p_header['crc'] = $v_data_footer['crc'];
2673         $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18;
2675         // ----- Close the file
2676         @fclose($v_file_compressed);
2678         // ----- Call the header generation
2679         if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2680             return $v_result;
2681         }
2683         // ----- Add the compressed data
2684         if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
2685             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2686             return PclZip::errorCode();
2687         }
2689         // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2690         fseek($v_file_compressed, 10);
2691         $v_size = $p_header['compressed_size'];
2692         while ($v_size != 0) {
2693             $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2694             $v_buffer = @fread($v_file_compressed, $v_read_size);
2695             //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2696             @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2697             $v_size -= $v_read_size;
2698         }
2700         // ----- Close the file
2701         @fclose($v_file_compressed);
2703         // ----- Unlink the temporary file
2704         @unlink($v_gzip_temp_name);
2706         // ----- Return
2707         return $v_result;
2708     }
2709     // --------------------------------------------------------------------------------
2711     // --------------------------------------------------------------------------------
2712     // Function : privCalculateStoredFilename()
2713     // Description :
2714     //     Based on file descriptor properties and global options, this method
2715     //     calculate the filename that will be stored in the archive.
2716     // Parameters :
2717     // Return Values :
2718     // --------------------------------------------------------------------------------
2719     public function privCalculateStoredFilename(&$p_filedescr, &$p_options)
2720     {
2721         $v_result=1;
2723         // ----- Working variables
2724         $p_filename = $p_filedescr['filename'];
2725         if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
2726             $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH];
2727         } else {
2728             $p_add_dir = '';
2729         }
2730         if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) {
2731             $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH];
2732         } else {
2733             $p_remove_dir = '';
2734         }
2735         if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
2736             $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
2737         } else {
2738             $p_remove_all_dir = 0;
2739         }
2741         // ----- Look for full name change
2742         if (isset($p_filedescr['new_full_name'])) {
2743             // ----- Remove drive letter if any
2744             $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
2745         } else {
2746             // ----- Look for path and/or short name change
2747             // ----- Look for short name change
2748             // Its when we cahnge just the filename but not the path
2749             if (isset($p_filedescr['new_short_name'])) {
2750                 $v_path_info = pathinfo($p_filename);
2751                 $v_dir = '';
2752                 if ($v_path_info['dirname'] != '') {
2753                     $v_dir = $v_path_info['dirname'].'/';
2754                 }
2755                 $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
2756             } else {
2757                 // ----- Calculate the stored filename
2758                 $v_stored_filename = $p_filename;
2759             }
2761             // ----- Look for all path to remove
2762             if ($p_remove_all_dir) {
2763                 $v_stored_filename = basename($p_filename);
2764             } elseif ($p_remove_dir != "") {
2765                 // ----- Look for partial path remove
2766                 if (substr($p_remove_dir, -1) != '/') {
2767                     $p_remove_dir .= "/";
2768                 }
2770                 if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./")) {
2771                     if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./")) {
2772                         $p_remove_dir = "./".$p_remove_dir;
2773                     }
2774                     if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./")) {
2775                         $p_remove_dir = substr($p_remove_dir, 2);
2776                     }
2777                 }
2779                 $v_compare = PclZipUtilPathInclusion($p_remove_dir, $v_stored_filename);
2780                 if ($v_compare > 0) {
2781                     if ($v_compare == 2) {
2782                         $v_stored_filename = "";
2783                     } else {
2784                         $v_stored_filename = substr($v_stored_filename, strlen($p_remove_dir));
2785                     }
2786                 }
2787             }
2789             // ----- Remove drive letter if any
2790             $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename);
2792             // ----- Look for path to add
2793             if ($p_add_dir != "") {
2794                 if (substr($p_add_dir, -1) == "/") {
2795                     $v_stored_filename = $p_add_dir.$v_stored_filename;
2796                 } else {
2797                     $v_stored_filename = $p_add_dir."/".$v_stored_filename;
2798                 }
2799             }
2800         }
2802         // ----- Filename (reduce the path of stored name)
2803         $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
2804         $p_filedescr['stored_filename'] = $v_stored_filename;
2806         // ----- Return
2807         return $v_result;
2808     }
2809     // --------------------------------------------------------------------------------
2811     // --------------------------------------------------------------------------------
2812     // Function : privWriteFileHeader()
2813     // Description :
2814     // Parameters :
2815     // Return Values :
2816     // --------------------------------------------------------------------------------
2817     public function privWriteFileHeader(&$p_header)
2818     {
2819         $v_result=1;
2821         // ----- Store the offset position of the file
2822         $p_header['offset'] = ftell($this->zip_fd);
2824         // ----- Transform UNIX mtime to DOS format mdate/mtime
2825         $v_date = getdate($p_header['mtime']);
2826         $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
2827         $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
2829         // ----- Packed data
2830         $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, $p_header['version_extracted'], $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], $p_header['compressed_size'], $p_header['size'], strlen($p_header['stored_filename']), $p_header['extra_len']);
2832         // ----- Write the first 148 bytes of the header in the archive
2833         fputs($this->zip_fd, $v_binary_data, 30);
2835         // ----- Write the variable fields
2836         if (strlen($p_header['stored_filename']) != 0) {
2837             fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
2838         }
2839         if ($p_header['extra_len'] != 0) {
2840             fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
2841         }
2843         // ----- Return
2844         return $v_result;
2845     }
2846     // --------------------------------------------------------------------------------
2848     // --------------------------------------------------------------------------------
2849     // Function : privWriteCentralFileHeader()
2850     // Description :
2851     // Parameters :
2852     // Return Values :
2853     // --------------------------------------------------------------------------------
2854     public function privWriteCentralFileHeader(&$p_header)
2855     {
2856         $v_result=1;
2858         // TBC
2859         //for(reset($p_header); $key = key($p_header); next($p_header)) {
2860         //}
2862         // ----- Transform UNIX mtime to DOS format mdate/mtime
2863         $v_date = getdate($p_header['mtime']);
2864         $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
2865         $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
2868         // ----- Packed data
2869         $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, $p_header['version'], $p_header['version_extracted'], $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], $p_header['compressed_size'], $p_header['size'], strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'], $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']);
2871         // ----- Write the 42 bytes of the header in the zip file
2872         fputs($this->zip_fd, $v_binary_data, 46);
2874         // ----- Write the variable fields
2875         if (strlen($p_header['stored_filename']) != 0) {
2876             fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
2877         }
2878         if ($p_header['extra_len'] != 0) {
2879             fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
2880         }
2881         if ($p_header['comment_len'] != 0) {
2882             fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
2883         }
2885         // ----- Return
2886         return $v_result;
2887     }
2888     // --------------------------------------------------------------------------------
2890     // --------------------------------------------------------------------------------
2891     // Function : privWriteCentralHeader()
2892     // Description :
2893     // Parameters :
2894     // Return Values :
2895     // --------------------------------------------------------------------------------
2896     public function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
2897     {
2898         $v_result = 1;
2900         // ----- Packed data
2901         $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment));
2903         // ----- Write the 22 bytes of the header in the zip file
2904         fputs($this->zip_fd, $v_binary_data, 22);
2906         // ----- Write the variable fields
2907         if (strlen($p_comment) != 0) {
2908             fputs($this->zip_fd, $p_comment, strlen($p_comment));
2909         }
2911         // ----- Return
2912         return $v_result;
2913     }
2914     // --------------------------------------------------------------------------------
2916     // --------------------------------------------------------------------------------
2917     // Function : privList()
2918     // Description :
2919     // Parameters :
2920     // Return Values :
2921     // --------------------------------------------------------------------------------
2922     public function privList(&$p_list)
2923     {
2924         $v_result = 1;
2926         // ----- Magic quotes trick
2927         $this->privDisableMagicQuotes();
2929         // ----- Open the zip file
2930         if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) {
2931             // ----- Magic quotes trick
2932             $this->privSwapBackMagicQuotes();
2934             // ----- Error log
2935             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
2937             // ----- Return
2938             return PclZip::errorCode();
2939         }
2941         // ----- Read the central directory informations
2942         $v_central_dir = array();
2943         if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
2944             $this->privSwapBackMagicQuotes();
2945             return $v_result;
2946         }
2948         // ----- Go to beginning of Central Dir
2949         @rewind($this->zip_fd);
2950         if (@fseek($this->zip_fd, $v_central_dir['offset'])) {
2951             $this->privSwapBackMagicQuotes();
2953             // ----- Error log
2954             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
2956             // ----- Return
2957             return PclZip::errorCode();
2958         }
2960         // ----- Read each entry
2961         for ($i=0; $i<$v_central_dir['entries']; $i++) {
2962             // ----- Read the file header
2963             if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) {
2964                 $this->privSwapBackMagicQuotes();
2965                 return $v_result;
2966             }
2967             $v_header['index'] = $i;
2969             // ----- Get the only interesting attributes
2970             $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
2971             unset($v_header);
2972         }
2974         // ----- Close the zip file
2975         $this->privCloseFd();
2977         // ----- Magic quotes trick
2978         $this->privSwapBackMagicQuotes();
2980         // ----- Return
2981         return $v_result;
2982     }
2983     // --------------------------------------------------------------------------------
2985     // --------------------------------------------------------------------------------
2986     // Function : privConvertHeader2FileInfo()
2987     // Description :
2988     //     This function takes the file informations from the central directory
2989     //     entries and extract the interesting parameters that will be given back.
2990     //     The resulting file infos are set in the array $p_info
2991     //         $p_info['filename'] : Filename with full path. Given by user (add),
2992     //                                                     extracted in the filesystem (extract).
2993     //         $p_info['stored_filename'] : Stored filename in the archive.
2994     //         $p_info['size'] = Size of the file.
2995     //         $p_info['compressed_size'] = Compressed size of the file.
2996     //         $p_info['mtime'] = Last modification date of the file.
2997     //         $p_info['comment'] = Comment associated with the file.
2998     //