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