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