source: branches/2.0/admin/include/pclzip.lib.php @ 2703

Last change on this file since 2703 was 2242, checked in by patdenice, 16 years ago

Enhance plugins administtration

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