Project

General

Profile

1
<?php
2
// --------------------------------------------------------------------------------
3
// PhpConcept Library - Zip Module 2.6
4
// --------------------------------------------------------------------------------
5
// License GNU/LGPL - Vincent Blavet - March 2006
6
// http://www.phpconcept.net
7
// --------------------------------------------------------------------------------
8
//
9
// Presentation :
10
//   PclZip is a PHP library that manage ZIP archives.
11
//   So far tests show that archives generated by PclZip are readable by
12
//   WinZip application and other tools.
13
//
14
// Description :
15
//   See readme.txt and http://www.phpconcept.net
16
//
17
// Warning :
18
//   This library and the associated files are non commercial, non professional
19
//   work.
20
//   It should not have unexpected results. However if any damage is caused by
21
//   this software the author can not be responsible.
22
//   The use of this software is at the risk of the user.
23
//
24
// --------------------------------------------------------------------------------
25
// $Id: pclzip.lib.php,v 1.47 2007/07/20 13:56:07 vblavet Exp $
26
// --------------------------------------------------------------------------------
27

    
28
  // ----- Constants
29
  if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
30
    define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
31
  }
32
  
33
  // ----- File list separator
34
  // In version 1.x of PclZip, the separator for file list is a space
35
  // (which is not a very smart choice, specifically for windows paths !).
36
  // A better separator should be a comma (,). This constant gives you the
37
  // abilty to change that.
38
  // However notice that changing this value, may have impact on existing
39
  // scripts, using space separated filenames.
40
  // Recommanded values for compatibility with older versions :
41
  //define( 'PCLZIP_SEPARATOR', ' ' );
42
  // Recommanded values for smart separation of filenames.
43
  if (!defined('PCLZIP_SEPARATOR')) {
44
    define( 'PCLZIP_SEPARATOR', ',' );
45
  }
46

    
47
  // ----- Error configuration
48
  // 0 : PclZip Class integrated error handling
49
  // 1 : PclError external library error handling. By enabling this
50
  //     you must ensure that you have included PclError library.
51
  // [2,...] : reserved for futur use
52
  if (!defined('PCLZIP_ERROR_EXTERNAL')) {
53
    define( 'PCLZIP_ERROR_EXTERNAL', 0 );
54
  }
55

    
56
  // ----- Optional static temporary directory
57
  //       By default temporary files are generated in the script current
58
  //       path.
59
  //       If defined :
60
  //       - MUST BE terminated by a '/'.
61
  //       - MUST be a valid, already created directory
62
  //       Samples :
63
  // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
64
  // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
65
  if (!defined('PCLZIP_TEMPORARY_DIR')) {
66
    define( 'PCLZIP_TEMPORARY_DIR', '' );
67
  }
68

    
69
// --------------------------------------------------------------------------------
70
// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
71
// --------------------------------------------------------------------------------
72

    
73
  // ----- Global variables
74
  $g_pclzip_version = "2.6";
75

    
76
  // ----- Error codes
77
  //   -1 : Unable to open file in binary write mode
78
  //   -2 : Unable to open file in binary read mode
79
  //   -3 : Invalid parameters
80
  //   -4 : File does not exist
81
  //   -5 : Filename is too long (max. 255)
82
  //   -6 : Not a valid zip file
83
  //   -7 : Invalid extracted file size
84
  //   -8 : Unable to create directory
85
  //   -9 : Invalid archive extension
86
  //  -10 : Invalid archive format
87
  //  -11 : Unable to delete file (unlink)
88
  //  -12 : Unable to rename file (rename)
89
  //  -13 : Invalid header checksum
90
  //  -14 : Invalid archive size
91
  define( 'PCLZIP_ERR_USER_ABORTED', 2 );
92
  define( 'PCLZIP_ERR_NO_ERROR', 0 );
93
  define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
94
  define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
95
  define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
96
  define( 'PCLZIP_ERR_MISSING_FILE', -4 );
97
  define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
98
  define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
99
  define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
100
  define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
101
  define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
102
  define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
103
  define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
104
  define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
105
  define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
106
  define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
107
  define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
108
  define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
109
  define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
110
  define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
111
  define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
112
  define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
113
  define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
114

    
115
  // ----- Options values
116
  define( 'PCLZIP_OPT_PATH', 77001 );
117
  define( 'PCLZIP_OPT_ADD_PATH', 77002 );
118
  define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
119
  define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
120
  define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
121
  define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
122
  define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
123
  define( 'PCLZIP_OPT_BY_NAME', 77008 );
124
  define( 'PCLZIP_OPT_BY_INDEX', 77009 );
125
  define( 'PCLZIP_OPT_BY_EREG', 77010 );
126
  define( 'PCLZIP_OPT_BY_PREG', 77011 );
127
  define( 'PCLZIP_OPT_COMMENT', 77012 );
128
  define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
129
  define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
130
  define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
131
  define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
132
  define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
133
  // Having big trouble with crypt. Need to multiply 2 long int
134
  // which is not correctly supported by PHP ...
135
  //define( 'PCLZIP_OPT_CRYPT', 77018 );
136
  define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
137
  
138
  // ----- File description attributes
139
  define( 'PCLZIP_ATT_FILE_NAME', 79001 );
140
  define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
141
  define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
142
  define( 'PCLZIP_ATT_FILE_MTIME', 79004 );
143
  define( 'PCLZIP_ATT_FILE_CONTENT', 79005 );
144
  define( 'PCLZIP_ATT_FILE_COMMENT', 79006 );
145

    
146
  // ----- Call backs values
147
  define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
148
  define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
149
  define( 'PCLZIP_CB_PRE_ADD', 78003 );
150
  define( 'PCLZIP_CB_POST_ADD', 78004 );
151
  /* For futur use
152
  define( 'PCLZIP_CB_PRE_LIST', 78005 );
153
  define( 'PCLZIP_CB_POST_LIST', 78006 );
154
  define( 'PCLZIP_CB_PRE_DELETE', 78007 );
155
  define( 'PCLZIP_CB_POST_DELETE', 78008 );
156
  */
157

    
158
  // --------------------------------------------------------------------------------
159
  // Class : PclZip
160
  // Description :
161
  //   PclZip is the class that represent a Zip archive.
162
  //   The public methods allow the manipulation of the archive.
163
  // Attributes :
164
  //   Attributes must not be accessed directly.
165
  // Methods :
166
  //   PclZip() : Object creator
167
  //   create() : Creates the Zip archive
168
  //   listContent() : List the content of the Zip archive
169
  //   extract() : Extract the content of the archive
170
  //   properties() : List the properties of the archive
171
  // --------------------------------------------------------------------------------
172
  class PclZip
173
  {
174
    // ----- Filename of the zip file
175
    var $zipname = '';
176

    
177
    // ----- File descriptor of the zip file
178
    var $zip_fd = 0;
179

    
180
    // ----- Internal error handling
181
    var $error_code = 1;
182
    var $error_string = '';
183
    
184
    // ----- Current status of the magic_quotes_runtime
185
    // This value store the php configuration for magic_quotes
186
    // The class can then disable the magic_quotes and reset it after
187
    var $magic_quotes_status;
188

    
189
  // --------------------------------------------------------------------------------
190
  // Function : PclZip()
191
  // Description :
192
  //   Creates a PclZip object and set the name of the associated Zip archive
193
  //   filename.
194
  //   Note that no real action is taken, if the archive does not exist it is not
195
  //   created. Use create() for that.
196
  // --------------------------------------------------------------------------------
197
  function PclZip($p_zipname)
198
  {
199
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::PclZip', "zipname=$p_zipname");
200

    
201
    // ----- Tests the zlib
202
    if (!function_exists('gzopen'))
203
    {
204
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 1, "zlib extension seems to be missing");
205
      die('Abort '.basename(__FILE__).' : Missing zlib extensions');
206
    }
207

    
208
    // ----- Set the attributes
209
    $this->zipname = $p_zipname;
210
    $this->zip_fd = 0;
211
    $this->magic_quotes_status = -1;
212

    
213
    // ----- Return
214
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 1);
215
    return;
216
  }
217
  // --------------------------------------------------------------------------------
218

    
219
  // --------------------------------------------------------------------------------
220
  // Function :
221
  //   create($p_filelist, $p_add_dir="", $p_remove_dir="")
222
  //   create($p_filelist, $p_option, $p_option_value, ...)
223
  // Description :
224
  //   This method supports two different synopsis. The first one is historical.
225
  //   This method creates a Zip Archive. The Zip file is created in the
226
  //   filesystem. The files and directories indicated in $p_filelist
227
  //   are added in the archive. See the parameters description for the
228
  //   supported format of $p_filelist.
229
  //   When a directory is in the list, the directory and its content is added
230
  //   in the archive.
231
  //   In this synopsis, the function takes an optional variable list of
232
  //   options. See bellow the supported options.
233
  // Parameters :
234
  //   $p_filelist : An array containing file or directory names, or
235
  //                 a string containing one filename or one directory name, or
236
  //                 a string containing a list of filenames and/or directory
237
  //                 names separated by spaces.
238
  //   $p_add_dir : A path to add before the real path of the archived file,
239
  //                in order to have it memorized in the archive.
240
  //   $p_remove_dir : A path to remove from the real path of the file to archive,
241
  //                   in order to have a shorter path memorized in the archive.
242
  //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
243
  //                   is removed first, before $p_add_dir is added.
244
  // Options :
245
  //   PCLZIP_OPT_ADD_PATH :
246
  //   PCLZIP_OPT_REMOVE_PATH :
247
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
248
  //   PCLZIP_OPT_COMMENT :
249
  //   PCLZIP_CB_PRE_ADD :
250
  //   PCLZIP_CB_POST_ADD :
251
  // Return Values :
252
  //   0 on failure,
253
  //   The list of the added files, with a status of the add action.
254
  //   (see PclZip::listContent() for list entry format)
255
  // --------------------------------------------------------------------------------
256
  function create($p_filelist)
257
  {
258
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::create', "filelist='$p_filelist', ...");
259
    $v_result=1;
260

    
261
    // ----- Reset the error handler
262
    $this->privErrorReset();
263

    
264
    // ----- Set default values
265
    $v_options = array();
266
    $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
267

    
268
    // ----- Look for variable options arguments
269
    $v_size = func_num_args();
270
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
271

    
272
    // ----- Look for arguments
273
    if ($v_size > 1) {
274
      // ----- Get the arguments
275
      $v_arg_list = func_get_args();
276

    
277
      // ----- Remove from the options list the first argument
278
      array_shift($v_arg_list);
279
      $v_size--;
280

    
281
      // ----- Look for first arg
282
      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
283
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
284

    
285
        // ----- Parse the options
286
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
287
                                            array (PCLZIP_OPT_REMOVE_PATH => 'optional',
288
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
289
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
290
                                                   PCLZIP_CB_PRE_ADD => 'optional',
291
                                                   PCLZIP_CB_POST_ADD => 'optional',
292
                                                   PCLZIP_OPT_NO_COMPRESSION => 'optional',
293
                                                   PCLZIP_OPT_COMMENT => 'optional'
294
                                                   //, PCLZIP_OPT_CRYPT => 'optional'
295
                                             ));
296
        if ($v_result != 1) {
297
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
298
          return 0;
299
        }
300
      }
301

    
302
      // ----- Look for 2 args
303
      // Here we need to support the first historic synopsis of the
304
      // method.
305
      else {
306
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
307

    
308
        // ----- Get the first argument
309
        $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
310

    
311
        // ----- Look for the optional second argument
312
        if ($v_size == 2) {
313
          $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
314
        }
315
        else if ($v_size > 2) {
316
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
317
		                       "Invalid number / type of arguments");
318
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
319
          return 0;
320
        }
321
      }
322
    }
323

    
324
    // ----- Init
325
    $v_string_list = array();
326
    $v_att_list = array();
327
    $v_filedescr_list = array();
328
    $p_result_list = array();
329
    
330
    // ----- Look if the $p_filelist is really an array
331
    if (is_array($p_filelist)) {
332
    
333
      // ----- Look if the first element is also an array
334
      //       This will mean that this is a file description entry
335
      if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
336
        $v_att_list = $p_filelist;
337
      }
338
      
339
      // ----- The list is a list of string names
340
      else {
341
        $v_string_list = $p_filelist;
342
      }
343
    }
344

    
345
    // ----- Look if the $p_filelist is a string
346
    else if (is_string($p_filelist)) {
347
      // ----- Create a list from the string
348
      $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
349
    }
350

    
351
    // ----- Invalid variable type for $p_filelist
352
    else {
353
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
354
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
355
      return 0;
356
    }
357
    
358
    // ----- Reformat the string list
359
    if (sizeof($v_string_list) != 0) {
360
      foreach ($v_string_list as $v_string) {
361
        if ($v_string != '') {
362
          $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
363
        }
364
        else {
365
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Ignore an empty filename");
366
        }
367
      }
368
    }
369
    
370
    // ----- For each file in the list check the attributes
371
    $v_supported_attributes
372
    = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
373
             ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
374
             ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
375
             ,PCLZIP_ATT_FILE_MTIME => 'optional'
376
             ,PCLZIP_ATT_FILE_CONTENT => 'optional'
377
             ,PCLZIP_ATT_FILE_COMMENT => 'optional'
378
						);
379
    foreach ($v_att_list as $v_entry) {
380
      $v_result = $this->privFileDescrParseAtt($v_entry,
381
                                               $v_filedescr_list[],
382
                                               $v_options,
383
                                               $v_supported_attributes);
384
      if ($v_result != 1) {
385
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
386
        return 0;
387
      }
388
    }
389

    
390
    // ----- Expand the filelist (expand directories)
391
    $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
392
    if ($v_result != 1) {
393
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
394
      return 0;
395
    }
396

    
397
    // ----- Call the create fct
398
    $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
399
    if ($v_result != 1) {
400
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
401
      return 0;
402
    }
403

    
404
    // ----- Return
405
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
406
    return $p_result_list;
407
  }
408
  // --------------------------------------------------------------------------------
409

    
410
  // --------------------------------------------------------------------------------
411
  // Function :
412
  //   add($p_filelist, $p_add_dir="", $p_remove_dir="")
413
  //   add($p_filelist, $p_option, $p_option_value, ...)
414
  // Description :
415
  //   This method supports two synopsis. The first one is historical.
416
  //   This methods add the list of files in an existing archive.
417
  //   If a file with the same name already exists, it is added at the end of the
418
  //   archive, the first one is still present.
419
  //   If the archive does not exist, it is created.
420
  // Parameters :
421
  //   $p_filelist : An array containing file or directory names, or
422
  //                 a string containing one filename or one directory name, or
423
  //                 a string containing a list of filenames and/or directory
424
  //                 names separated by spaces.
425
  //   $p_add_dir : A path to add before the real path of the archived file,
426
  //                in order to have it memorized in the archive.
427
  //   $p_remove_dir : A path to remove from the real path of the file to archive,
428
  //                   in order to have a shorter path memorized in the archive.
429
  //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
430
  //                   is removed first, before $p_add_dir is added.
431
  // Options :
432
  //   PCLZIP_OPT_ADD_PATH :
433
  //   PCLZIP_OPT_REMOVE_PATH :
434
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
435
  //   PCLZIP_OPT_COMMENT :
436
  //   PCLZIP_OPT_ADD_COMMENT :
437
  //   PCLZIP_OPT_PREPEND_COMMENT :
438
  //   PCLZIP_CB_PRE_ADD :
439
  //   PCLZIP_CB_POST_ADD :
440
  // Return Values :
441
  //   0 on failure,
442
  //   The list of the added files, with a status of the add action.
443
  //   (see PclZip::listContent() for list entry format)
444
  // --------------------------------------------------------------------------------
445
  function add($p_filelist)
446
  {
447
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::add', "filelist='$p_filelist', ...");
448
    $v_result=1;
449

    
450
    // ----- Reset the error handler
451
    $this->privErrorReset();
452

    
453
    // ----- Set default values
454
    $v_options = array();
455
    $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
456

    
457
    // ----- Look for variable options arguments
458
    $v_size = func_num_args();
459
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
460

    
461
    // ----- Look for arguments
462
    if ($v_size > 1) {
463
      // ----- Get the arguments
464
      $v_arg_list = func_get_args();
465

    
466
      // ----- Remove form the options list the first argument
467
      array_shift($v_arg_list);
468
      $v_size--;
469

    
470
      // ----- Look for first arg
471
      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
472
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
473

    
474
        // ----- Parse the options
475
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
476
                                            array (PCLZIP_OPT_REMOVE_PATH => 'optional',
477
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
478
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
479
                                                   PCLZIP_CB_PRE_ADD => 'optional',
480
                                                   PCLZIP_CB_POST_ADD => 'optional',
481
                                                   PCLZIP_OPT_NO_COMPRESSION => 'optional',
482
                                                   PCLZIP_OPT_COMMENT => 'optional',
483
                                                   PCLZIP_OPT_ADD_COMMENT => 'optional',
484
                                                   PCLZIP_OPT_PREPEND_COMMENT => 'optional'
485
                                                   //, PCLZIP_OPT_CRYPT => 'optional'
486
												   ));
487
        if ($v_result != 1) {
488
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
489
          return 0;
490
        }
491
      }
492

    
493
      // ----- Look for 2 args
494
      // Here we need to support the first historic synopsis of the
495
      // method.
496
      else {
497
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
498

    
499
        // ----- Get the first argument
500
        $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
501

    
502
        // ----- Look for the optional second argument
503
        if ($v_size == 2) {
504
          $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
505
        }
506
        else if ($v_size > 2) {
507
          // ----- Error log
508
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
509

    
510
          // ----- Return
511
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
512
          return 0;
513
        }
514
      }
515
    }
516

    
517
    // ----- Init
518
    $v_string_list = array();
519
    $v_att_list = array();
520
    $v_filedescr_list = array();
521
    $p_result_list = array();
522
    
523
    // ----- Look if the $p_filelist is really an array
524
    if (is_array($p_filelist)) {
525
    
526
      // ----- Look if the first element is also an array
527
      //       This will mean that this is a file description entry
528
      if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
529
        $v_att_list = $p_filelist;
530
      }
531
      
532
      // ----- The list is a list of string names
533
      else {
534
        $v_string_list = $p_filelist;
535
      }
536
    }
537

    
538
    // ----- Look if the $p_filelist is a string
539
    else if (is_string($p_filelist)) {
540
      // ----- Create a list from the string
541
      $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
542
    }
543

    
544
    // ----- Invalid variable type for $p_filelist
545
    else {
546
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
547
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
548
      return 0;
549
    }
550
    
551
    // ----- Reformat the string list
552
    if (sizeof($v_string_list) != 0) {
553
      foreach ($v_string_list as $v_string) {
554
        $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
555
      }
556
    }
557
    
558
    // ----- For each file in the list check the attributes
559
    $v_supported_attributes
560
    = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
561
             ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
562
             ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
563
             ,PCLZIP_ATT_FILE_MTIME => 'optional'
564
             ,PCLZIP_ATT_FILE_CONTENT => 'optional'
565
             ,PCLZIP_ATT_FILE_COMMENT => 'optional'
566
						);
567
    foreach ($v_att_list as $v_entry) {
568
      $v_result = $this->privFileDescrParseAtt($v_entry,
569
                                               $v_filedescr_list[],
570
                                               $v_options,
571
                                               $v_supported_attributes);
572
      if ($v_result != 1) {
573
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
574
        return 0;
575
      }
576
    }
577

    
578
    // ----- Expand the filelist (expand directories)
579
    $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
580
    if ($v_result != 1) {
581
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
582
      return 0;
583
    }
584

    
585
    // ----- Call the create fct
586
    $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
587
    if ($v_result != 1) {
588
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
589
      return 0;
590
    }
591

    
592
    // ----- Return
593
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
594
    return $p_result_list;
595
  }
596
  // --------------------------------------------------------------------------------
597

    
598
  // --------------------------------------------------------------------------------
599
  // Function : listContent()
600
  // Description :
601
  //   This public method, gives the list of the files and directories, with their
602
  //   properties.
603
  //   The properties of each entries in the list are (used also in other functions) :
604
  //     filename : Name of the file. For a create or add action it is the filename
605
  //                given by the user. For an extract function it is the filename
606
  //                of the extracted file.
607
  //     stored_filename : Name of the file / directory stored in the archive.
608
  //     size : Size of the stored file.
609
  //     compressed_size : Size of the file's data compressed in the archive
610
  //                       (without the headers overhead)
611
  //     mtime : Last known modification date of the file (UNIX timestamp)
612
  //     comment : Comment associated with the file
613
  //     folder : true | false
614
  //     index : index of the file in the archive
615
  //     status : status of the action (depending of the action) :
616
  //              Values are :
617
  //                ok : OK !
618
  //                filtered : the file / dir is not extracted (filtered by user)
619
  //                already_a_directory : the file can not be extracted because a
620
  //                                      directory with the same name already exists
621
  //                write_protected : the file can not be extracted because a file
622
  //                                  with the same name already exists and is
623
  //                                  write protected
624
  //                newer_exist : the file was not extracted because a newer file exists
625
  //                path_creation_fail : the file is not extracted because the folder
626
  //                                     does not exists and can not be created
627
  //                write_error : the file was not extracted because there was a
628
  //                              error while writing the file
629
  //                read_error : the file was not extracted because there was a error
630
  //                             while reading the file
631
  //                invalid_header : the file was not extracted because of an archive
632
  //                                 format error (bad file header)
633
  //   Note that each time a method can continue operating when there
634
  //   is an action error on a file, the error is only logged in the file status.
635
  // Return Values :
636
  //   0 on an unrecoverable failure,
637
  //   The list of the files in the archive.
638
  // --------------------------------------------------------------------------------
639
  function listContent()
640
  {
641
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::listContent', "");
642
    $v_result=1;
643

    
644
    // ----- Reset the error handler
645
    $this->privErrorReset();
646

    
647
    // ----- Check archive
648
    if (!$this->privCheckFormat()) {
649
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
650
      return(0);
651
    }
652

    
653
    // ----- Call the extracting fct
654
    $p_list = array();
655
    if (($v_result = $this->privList($p_list)) != 1)
656
    {
657
      unset($p_list);
658
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
659
      return(0);
660
    }
661

    
662
    // ----- Return
663
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
664
    return $p_list;
665
  }
666
  // --------------------------------------------------------------------------------
667

    
668
  // --------------------------------------------------------------------------------
669
  // Function :
670
  //   extract($p_path="./", $p_remove_path="")
671
  //   extract([$p_option, $p_option_value, ...])
672
  // Description :
673
  //   This method supports two synopsis. The first one is historical.
674
  //   This method extract all the files / directories from the archive to the
675
  //   folder indicated in $p_path.
676
  //   If you want to ignore the 'root' part of path of the memorized files
677
  //   you can indicate this in the optional $p_remove_path parameter.
678
  //   By default, if a newer file with the same name already exists, the
679
  //   file is not extracted.
680
  //
681
  //   If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
682
  //   are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
683
  //   at the end of the path value of PCLZIP_OPT_PATH.
684
  // Parameters :
685
  //   $p_path : Path where the files and directories are to be extracted
686
  //   $p_remove_path : First part ('root' part) of the memorized path
687
  //                    (if any similar) to remove while extracting.
688
  // Options :
689
  //   PCLZIP_OPT_PATH :
690
  //   PCLZIP_OPT_ADD_PATH :
691
  //   PCLZIP_OPT_REMOVE_PATH :
692
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
693
  //   PCLZIP_CB_PRE_EXTRACT :
694
  //   PCLZIP_CB_POST_EXTRACT :
695
  // Return Values :
696
  //   0 or a negative value on failure,
697
  //   The list of the extracted files, with a status of the action.
698
  //   (see PclZip::listContent() for list entry format)
699
  // --------------------------------------------------------------------------------
700
  function extract()
701
  {
702
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extract", "");
703
    $v_result=1;
704

    
705
    // ----- Reset the error handler
706
    $this->privErrorReset();
707

    
708
    // ----- Check archive
709
    if (!$this->privCheckFormat()) {
710
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
711
      return(0);
712
    }
713

    
714
    // ----- Set default values
715
    $v_options = array();
716
//    $v_path = "./";
717
    $v_path = '';
718
    $v_remove_path = "";
719
    $v_remove_all_path = false;
720

    
721
    // ----- Look for variable options arguments
722
    $v_size = func_num_args();
723
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
724

    
725
    // ----- Default values for option
726
    $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
727

    
728
    // ----- Look for arguments
729
    if ($v_size > 0) {
730
      // ----- Get the arguments
731
      $v_arg_list = func_get_args();
732

    
733
      // ----- Look for first arg
734
      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
735
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
736

    
737
        // ----- Parse the options
738
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
739
                                            array (PCLZIP_OPT_PATH => 'optional',
740
                                                   PCLZIP_OPT_REMOVE_PATH => 'optional',
741
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
742
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
743
                                                   PCLZIP_CB_PRE_EXTRACT => 'optional',
744
                                                   PCLZIP_CB_POST_EXTRACT => 'optional',
745
                                                   PCLZIP_OPT_SET_CHMOD => 'optional',
746
                                                   PCLZIP_OPT_BY_NAME => 'optional',
747
                                                   PCLZIP_OPT_BY_EREG => 'optional',
748
                                                   PCLZIP_OPT_BY_PREG => 'optional',
749
                                                   PCLZIP_OPT_BY_INDEX => 'optional',
750
                                                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
751
                                                   PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
752
                                                   PCLZIP_OPT_REPLACE_NEWER => 'optional'
753
                                                   ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
754
                                                   ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional'
755
												    ));
756
        if ($v_result != 1) {
757
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
758
          return 0;
759
        }
760

    
761
        // ----- Set the arguments
762
        if (isset($v_options[PCLZIP_OPT_PATH])) {
763
          $v_path = $v_options[PCLZIP_OPT_PATH];
764
        }
765
        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
766
          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
767
        }
768
        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
769
          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
770
        }
771
        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
772
          // ----- Check for '/' in last path char
773
          if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
774
            $v_path .= '/';
775
          }
776
          $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
777
        }
778
      }
779

    
780
      // ----- Look for 2 args
781
      // Here we need to support the first historic synopsis of the
782
      // method.
783
      else {
784
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
785

    
786
        // ----- Get the first argument
787
        $v_path = $v_arg_list[0];
788

    
789
        // ----- Look for the optional second argument
790
        if ($v_size == 2) {
791
          $v_remove_path = $v_arg_list[1];
792
        }
793
        else if ($v_size > 2) {
794
          // ----- Error log
795
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
796

    
797
          // ----- Return
798
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
799
          return 0;
800
        }
801
      }
802
    }
803

    
804
    // ----- Trace
805
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
806

    
807
    // ----- Call the extracting fct
808
    $p_list = array();
809
    $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
810
	                                     $v_remove_all_path, $v_options);
811
    if ($v_result < 1) {
812
      unset($p_list);
813
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
814
      return(0);
815
    }
816

    
817
    // ----- Return
818
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
819
    return $p_list;
820
  }
821
  // --------------------------------------------------------------------------------
822

    
823

    
824
  // --------------------------------------------------------------------------------
825
  // Function :
826
  //   extractByIndex($p_index, $p_path="./", $p_remove_path="")
827
  //   extractByIndex($p_index, [$p_option, $p_option_value, ...])
828
  // Description :
829
  //   This method supports two synopsis. The first one is historical.
830
  //   This method is doing a partial extract of the archive.
831
  //   The extracted files or folders are identified by their index in the
832
  //   archive (from 0 to n).
833
  //   Note that if the index identify a folder, only the folder entry is
834
  //   extracted, not all the files included in the archive.
835
  // Parameters :
836
  //   $p_index : A single index (integer) or a string of indexes of files to
837
  //              extract. The form of the string is "0,4-6,8-12" with only numbers
838
  //              and '-' for range or ',' to separate ranges. No spaces or ';'
839
  //              are allowed.
840
  //   $p_path : Path where the files and directories are to be extracted
841
  //   $p_remove_path : First part ('root' part) of the memorized path
842
  //                    (if any similar) to remove while extracting.
843
  // Options :
844
  //   PCLZIP_OPT_PATH :
845
  //   PCLZIP_OPT_ADD_PATH :
846
  //   PCLZIP_OPT_REMOVE_PATH :
847
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
848
  //   PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
849
  //     not as files.
850
  //     The resulting content is in a new field 'content' in the file
851
  //     structure.
852
  //     This option must be used alone (any other options are ignored).
853
  //   PCLZIP_CB_PRE_EXTRACT :
854
  //   PCLZIP_CB_POST_EXTRACT :
855
  // Return Values :
856
  //   0 on failure,
857
  //   The list of the extracted files, with a status of the action.
858
  //   (see PclZip::listContent() for list entry format)
859
  // --------------------------------------------------------------------------------
860
  //function extractByIndex($p_index, options...)
861
  function extractByIndex($p_index)
862
  {
863
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extractByIndex", "index='$p_index', ...");
864
    $v_result=1;
865

    
866
    // ----- Reset the error handler
867
    $this->privErrorReset();
868

    
869
    // ----- Check archive
870
    if (!$this->privCheckFormat()) {
871
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
872
      return(0);
873
    }
874

    
875
    // ----- Set default values
876
    $v_options = array();
877
//    $v_path = "./";
878
    $v_path = '';
879
    $v_remove_path = "";
880
    $v_remove_all_path = false;
881

    
882
    // ----- Look for variable options arguments
883
    $v_size = func_num_args();
884
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
885

    
886
    // ----- Default values for option
887
    $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
888

    
889
    // ----- Look for arguments
890
    if ($v_size > 1) {
891
      // ----- Get the arguments
892
      $v_arg_list = func_get_args();
893

    
894
      // ----- Remove form the options list the first argument
895
      array_shift($v_arg_list);
896
      $v_size--;
897

    
898
      // ----- Look for first arg
899
      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
900
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
901

    
902
        // ----- Parse the options
903
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
904
                                            array (PCLZIP_OPT_PATH => 'optional',
905
                                                   PCLZIP_OPT_REMOVE_PATH => 'optional',
906
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
907
                                                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
908
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
909
                                                   PCLZIP_CB_PRE_EXTRACT => 'optional',
910
                                                   PCLZIP_CB_POST_EXTRACT => 'optional',
911
                                                   PCLZIP_OPT_SET_CHMOD => 'optional',
912
                                                   PCLZIP_OPT_REPLACE_NEWER => 'optional'
913
                                                   ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
914
                                                   ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional'
915
												   ));
916
        if ($v_result != 1) {
917
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
918
          return 0;
919
        }
920

    
921
        // ----- Set the arguments
922
        if (isset($v_options[PCLZIP_OPT_PATH])) {
923
          $v_path = $v_options[PCLZIP_OPT_PATH];
924
        }
925
        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
926
          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
927
        }
928
        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
929
          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
930
        }
931
        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
932
          // ----- Check for '/' in last path char
933
          if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
934
            $v_path .= '/';
935
          }
936
          $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
937
        }
938
        if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
939
          $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
940
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING not set.");
941
        }
942
        else {
943
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING set.");
944
        }
945
      }
946

    
947
      // ----- Look for 2 args
948
      // Here we need to support the first historic synopsis of the
949
      // method.
950
      else {
951
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
952

    
953
        // ----- Get the first argument
954
        $v_path = $v_arg_list[0];
955

    
956
        // ----- Look for the optional second argument
957
        if ($v_size == 2) {
958
          $v_remove_path = $v_arg_list[1];
959
        }
960
        else if ($v_size > 2) {
961
          // ----- Error log
962
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
963

    
964
          // ----- Return
965
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
966
          return 0;
967
        }
968
      }
969
    }
970

    
971
    // ----- Trace
972
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "index='$p_index', path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
973

    
974
    // ----- Trick
975
    // Here I want to reuse extractByRule(), so I need to parse the $p_index
976
    // with privParseOptions()
977
    $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
978
    $v_options_trick = array();
979
    $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
980
                                        array (PCLZIP_OPT_BY_INDEX => 'optional' ));
981
    if ($v_result != 1) {
982
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
983
        return 0;
984
    }
985
    $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
986

    
987
    // ----- Call the extracting fct
988
    if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
989
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
990
        return(0);
991
    }
992

    
993
    // ----- Return
994
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
995
    return $p_list;
996
  }
997
  // --------------------------------------------------------------------------------
998

    
999
  // --------------------------------------------------------------------------------
1000
  // Function :
1001
  //   delete([$p_option, $p_option_value, ...])
1002
  // Description :
1003
  //   This method removes files from the archive.
1004
  //   If no parameters are given, then all the archive is emptied.
1005
  // Parameters :
1006
  //   None or optional arguments.
1007
  // Options :
1008
  //   PCLZIP_OPT_BY_INDEX :
1009
  //   PCLZIP_OPT_BY_NAME :
1010
  //   PCLZIP_OPT_BY_EREG : 
1011
  //   PCLZIP_OPT_BY_PREG :
1012
  // Return Values :
1013
  //   0 on failure,
1014
  //   The list of the files which are still present in the archive.
1015
  //   (see PclZip::listContent() for list entry format)
1016
  // --------------------------------------------------------------------------------
1017
  function delete()
1018
  {
1019
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::delete", "");
1020
    $v_result=1;
1021

    
1022
    // ----- Reset the error handler
1023
    $this->privErrorReset();
1024

    
1025
    // ----- Check archive
1026
    if (!$this->privCheckFormat()) {
1027
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
1028
      return(0);
1029
    }
1030

    
1031
    // ----- Set default values
1032
    $v_options = array();
1033

    
1034
    // ----- Look for variable options arguments
1035
    $v_size = func_num_args();
1036
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
1037

    
1038
    // ----- Look for arguments
1039
    if ($v_size > 0) {
1040
      // ----- Get the arguments
1041
      $v_arg_list = func_get_args();
1042

    
1043
      // ----- Parse the options
1044
      $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
1045
                                        array (PCLZIP_OPT_BY_NAME => 'optional',
1046
                                               PCLZIP_OPT_BY_EREG => 'optional',
1047
                                               PCLZIP_OPT_BY_PREG => 'optional',
1048
                                               PCLZIP_OPT_BY_INDEX => 'optional' ));
1049
      if ($v_result != 1) {
1050
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
1051
          return 0;
1052
      }
1053
    }
1054

    
1055
    // ----- Magic quotes trick
1056
    $this->privDisableMagicQuotes();
1057

    
1058
    // ----- Call the delete fct
1059
    $v_list = array();
1060
    if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
1061
      $this->privSwapBackMagicQuotes();
1062
      unset($v_list);
1063
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
1064
      return(0);
1065
    }
1066

    
1067
    // ----- Magic quotes trick
1068
    $this->privSwapBackMagicQuotes();
1069

    
1070
    // ----- Return
1071
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_list);
1072
    return $v_list;
1073
  }
1074
  // --------------------------------------------------------------------------------
1075

    
1076
  // --------------------------------------------------------------------------------
1077
  // Function : deleteByIndex()
1078
  // Description :
1079
  //   ***** Deprecated *****
1080
  //   delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
1081
  // --------------------------------------------------------------------------------
1082
  function deleteByIndex($p_index)
1083
  {
1084
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::deleteByIndex", "index='$p_index'");
1085
    
1086
    $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
1087

    
1088
    // ----- Return
1089
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
1090
    return $p_list;
1091
  }
1092
  // --------------------------------------------------------------------------------
1093

    
1094
  // --------------------------------------------------------------------------------
1095
  // Function : properties()
1096
  // Description :
1097
  //   This method gives the properties of the archive.
1098
  //   The properties are :
1099
  //     nb : Number of files in the archive
1100
  //     comment : Comment associated with the archive file
1101
  //     status : not_exist, ok
1102
  // Parameters :
1103
  //   None
1104
  // Return Values :
1105
  //   0 on failure,
1106
  //   An array with the archive properties.
1107
  // --------------------------------------------------------------------------------
1108
  function properties()
1109
  {
1110
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::properties", "");
1111

    
1112
    // ----- Reset the error handler
1113
    $this->privErrorReset();
1114

    
1115
    // ----- Magic quotes trick
1116
    $this->privDisableMagicQuotes();
1117

    
1118
    // ----- Check archive
1119
    if (!$this->privCheckFormat()) {
1120
      $this->privSwapBackMagicQuotes();
1121
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
1122
      return(0);
1123
    }
1124

    
1125
    // ----- Default properties
1126
    $v_prop = array();
1127
    $v_prop['comment'] = '';
1128
    $v_prop['nb'] = 0;
1129
    $v_prop['status'] = 'not_exist';
1130

    
1131
    // ----- Look if file exists
1132
    if (@is_file($this->zipname))
1133
    {
1134
      // ----- Open the zip file
1135
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
1136
      if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
1137
      {
1138
        $this->privSwapBackMagicQuotes();
1139
        
1140
        // ----- Error log
1141
        PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
1142

    
1143
        // ----- Return
1144
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), 0);
1145
        return 0;
1146
      }
1147

    
1148
      // ----- Read the central directory informations
1149
      $v_central_dir = array();
1150
      if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
1151
      {
1152
        $this->privSwapBackMagicQuotes();
1153
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
1154
        return 0;
1155
      }
1156

    
1157
      // ----- Close the zip file
1158
      $this->privCloseFd();
1159

    
1160
      // ----- Set the user attributes
1161
      $v_prop['comment'] = $v_central_dir['comment'];
1162
      $v_prop['nb'] = $v_central_dir['entries'];
1163
      $v_prop['status'] = 'ok';
1164
    }
1165

    
1166
    // ----- Magic quotes trick
1167
    $this->privSwapBackMagicQuotes();
1168

    
1169
    // ----- Return
1170
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_prop);
1171
    return $v_prop;
1172
  }
1173
  // --------------------------------------------------------------------------------
1174

    
1175
  // --------------------------------------------------------------------------------
1176
  // Function : duplicate()
1177
  // Description :
1178
  //   This method creates an archive by copying the content of an other one. If
1179
  //   the archive already exist, it is replaced by the new one without any warning.
1180
  // Parameters :
1181
  //   $p_archive : The filename of a valid archive, or
1182
  //                a valid PclZip object.
1183
  // Return Values :
1184
  //   1 on success.
1185
  //   0 or a negative value on error (error code).
1186
  // --------------------------------------------------------------------------------
1187
  function duplicate($p_archive)
1188
  {
1189
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::duplicate", "");
1190
    $v_result = 1;
1191

    
1192
    // ----- Reset the error handler
1193
    $this->privErrorReset();
1194

    
1195
    // ----- Look if the $p_archive is a PclZip object
1196
    if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
1197
    {
1198
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is valid PclZip object '".$p_archive->zipname."'");
1199

    
1200
      // ----- Duplicate the archive
1201
      $v_result = $this->privDuplicate($p_archive->zipname);
1202
    }
1203

    
1204
    // ----- Look if the $p_archive is a string (so a filename)
1205
    else if (is_string($p_archive))
1206
    {
1207
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is a filename '$p_archive'");
1208

    
1209
      // ----- Check that $p_archive is a valid zip file
1210
      // TBC : Should also check the archive format
1211
      if (!is_file($p_archive)) {
1212
        // ----- Error log
1213
        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
1214
        $v_result = PCLZIP_ERR_MISSING_FILE;
1215
      }
1216
      else {
1217
        // ----- Duplicate the archive
1218
        $v_result = $this->privDuplicate($p_archive);
1219
      }
1220
    }
1221

    
1222
    // ----- Invalid variable
1223
    else
1224
    {
1225
      // ----- Error log
1226
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1227
      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1228
    }
1229

    
1230
    // ----- Return
1231
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1232
    return $v_result;
1233
  }
1234
  // --------------------------------------------------------------------------------
1235

    
1236
  // --------------------------------------------------------------------------------
1237
  // Function : merge()
1238
  // Description :
1239
  //   This method merge the $p_archive_to_add archive at the end of the current
1240
  //   one ($this).
1241
  //   If the archive ($this) does not exist, the merge becomes a duplicate.
1242
  //   If the $p_archive_to_add archive does not exist, the merge is a success.
1243
  // Parameters :
1244
  //   $p_archive_to_add : It can be directly the filename of a valid zip archive,
1245
  //                       or a PclZip object archive.
1246
  // Return Values :
1247
  //   1 on success,
1248
  //   0 or negative values on error (see below).
1249
  // --------------------------------------------------------------------------------
1250
  function merge($p_archive_to_add)
1251
  {
1252
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::merge", "");
1253
    $v_result = 1;
1254

    
1255
    // ----- Reset the error handler
1256
    $this->privErrorReset();
1257

    
1258
    // ----- Check archive
1259
    if (!$this->privCheckFormat()) {
1260
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
1261
      return(0);
1262
    }
1263

    
1264
    // ----- Look if the $p_archive_to_add is a PclZip object
1265
    if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
1266
    {
1267
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is valid PclZip object");
1268

    
1269
      // ----- Merge the archive
1270
      $v_result = $this->privMerge($p_archive_to_add);
1271
    }
1272

    
1273
    // ----- Look if the $p_archive_to_add is a string (so a filename)
1274
    else if (is_string($p_archive_to_add))
1275
    {
1276
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is a filename");
1277

    
1278
      // ----- Create a temporary archive
1279
      $v_object_archive = new PclZip($p_archive_to_add);
1280

    
1281
      // ----- Merge the archive
1282
      $v_result = $this->privMerge($v_object_archive);
1283
    }
1284

    
1285
    // ----- Invalid variable
1286
    else
1287
    {
1288
      // ----- Error log
1289
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1290
      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1291
    }
1292

    
1293
    // ----- Return
1294
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1295
    return $v_result;
1296
  }
1297
  // --------------------------------------------------------------------------------
1298

    
1299

    
1300

    
1301
  // --------------------------------------------------------------------------------
1302
  // Function : errorCode()
1303
  // Description :
1304
  // Parameters :
1305
  // --------------------------------------------------------------------------------
1306
  function errorCode()
1307
  {
1308
    if (PCLZIP_ERROR_EXTERNAL == 1) {
1309
      return(PclErrorCode());
1310
    }
1311
    else {
1312
      return($this->error_code);
1313
    }
1314
  }
1315
  // --------------------------------------------------------------------------------
1316

    
1317
  // --------------------------------------------------------------------------------
1318
  // Function : errorName()
1319
  // Description :
1320
  // Parameters :
1321
  // --------------------------------------------------------------------------------
1322
  function errorName($p_with_code=false)
1323
  {
1324
    $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
1325
                      PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
1326
                      PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
1327
                      PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
1328
                      PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
1329
                      PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
1330
                      PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
1331
                      PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
1332
                      PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
1333
                      PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
1334
                      PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
1335
                      PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
1336
                      PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
1337
                      PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
1338
                      PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1339
                      PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
1340
                      PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
1341
                      PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
1342
                      PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
1343
                      ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
1344
                      ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
1345
                    );
1346

    
1347
    if (isset($v_name[$this->error_code])) {
1348
      $v_value = $v_name[$this->error_code];
1349
    }
1350
    else {
1351
      $v_value = 'NoName';
1352
    }
1353

    
1354
    if ($p_with_code) {
1355
      return($v_value.' ('.$this->error_code.')');
1356
    }
1357
    else {
1358
      return($v_value);
1359
    }
1360
  }
1361
  // --------------------------------------------------------------------------------
1362

    
1363
  // --------------------------------------------------------------------------------
1364
  // Function : errorInfo()
1365
  // Description :
1366
  // Parameters :
1367
  // --------------------------------------------------------------------------------
1368
  function errorInfo($p_full=false)
1369
  {
1370
    if (PCLZIP_ERROR_EXTERNAL == 1) {
1371
      return(PclErrorString());
1372
    }
1373
    else {
1374
      if ($p_full) {
1375
        return($this->errorName(true)." : ".$this->error_string);
1376
      }
1377
      else {
1378
        return($this->error_string." [code ".$this->error_code."]");
1379
      }
1380
    }
1381
  }
1382
  // --------------------------------------------------------------------------------
1383

    
1384

    
1385
// --------------------------------------------------------------------------------
1386
// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1387
// *****                                                        *****
1388
// *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       *****
1389
// --------------------------------------------------------------------------------
1390

    
1391

    
1392

    
1393
  // --------------------------------------------------------------------------------
1394
  // Function : privCheckFormat()
1395
  // Description :
1396
  //   This method check that the archive exists and is a valid zip archive.
1397
  //   Several level of check exists. (futur)
1398
  // Parameters :
1399
  //   $p_level : Level of check. Default 0.
1400
  //              0 : Check the first bytes (magic codes) (default value))
1401
  //              1 : 0 + Check the central directory (futur)
1402
  //              2 : 1 + Check each file header (futur)
1403
  // Return Values :
1404
  //   true on success,
1405
  //   false on error, the error code is set.
1406
  // --------------------------------------------------------------------------------
1407
  function privCheckFormat($p_level=0)
1408
  {
1409
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFormat", "");
1410
    $v_result = true;
1411

    
1412
	// ----- Reset the file system cache
1413
    clearstatcache();
1414

    
1415
    // ----- Reset the error handler
1416
    $this->privErrorReset();
1417

    
1418
    // ----- Look if the file exits
1419
    if (!is_file($this->zipname)) {
1420
      // ----- Error log
1421
      PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
1422
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
1423
      return(false);
1424
    }
1425

    
1426
    // ----- Check that the file is readeable
1427
    if (!is_readable($this->zipname)) {
1428
      // ----- Error log
1429
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
1430
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
1431
      return(false);
1432
    }
1433

    
1434
    // ----- Check the magic code
1435
    // TBC
1436

    
1437
    // ----- Check the central header
1438
    // TBC
1439

    
1440
    // ----- Check each file header
1441
    // TBC
1442

    
1443
    // ----- Return
1444
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1445
    return $v_result;
1446
  }
1447
  // --------------------------------------------------------------------------------
1448

    
1449
  // --------------------------------------------------------------------------------
1450
  // Function : privParseOptions()
1451
  // Description :
1452
  //   This internal methods reads the variable list of arguments ($p_options_list,
1453
  //   $p_size) and generate an array with the options and values ($v_result_list).
1454
  //   $v_requested_options contains the options that can be present and those that
1455
  //   must be present.
1456
  //   $v_requested_options is an array, with the option value as key, and 'optional',
1457
  //   or 'mandatory' as value.
1458
  // Parameters :
1459
  //   See above.
1460
  // Return Values :
1461
  //   1 on success.
1462
  //   0 on failure.
1463
  // --------------------------------------------------------------------------------
1464
  function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
1465
  {
1466
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privParseOptions", "");
1467
    $v_result=1;
1468
    
1469
    // ----- Read the options
1470
    $i=0;
1471
    while ($i<$p_size) {
1472
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Looking for table index $i, option = '".PclZipUtilOptionText($p_options_list[$i])."(".$p_options_list[$i].")'");
1473

    
1474
      // ----- Check if the option is supported
1475
      if (!isset($v_requested_options[$p_options_list[$i]])) {
1476
        // ----- Error log
1477
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1478

    
1479
        // ----- Return
1480
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1481
        return PclZip::errorCode();
1482
      }
1483

    
1484
      // ----- Look for next option
1485
      switch ($p_options_list[$i]) {
1486
        // ----- Look for options that request a path value
1487
        case PCLZIP_OPT_PATH :
1488
        case PCLZIP_OPT_REMOVE_PATH :
1489
        case PCLZIP_OPT_ADD_PATH :
1490
          // ----- Check the number of parameters
1491
          if (($i+1) >= $p_size) {
1492
            // ----- Error log
1493
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1494

    
1495
            // ----- Return
1496
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1497
            return PclZip::errorCode();
1498
          }
1499

    
1500
          // ----- Get the value
1501
          $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1502
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1503
          $i++;
1504
        break;
1505

    
1506
        case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
1507
          // ----- Check the number of parameters
1508
          if (($i+1) >= $p_size) {
1509
            // ----- Error log
1510
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1511

    
1512
            // ----- Return
1513
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1514
            return PclZip::errorCode();
1515
          }
1516

    
1517
          // ----- Get the value
1518
          if (   is_string($p_options_list[$i+1])
1519
              && ($p_options_list[$i+1] != '')) {
1520
            $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1521
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1522
            $i++;
1523
          }
1524
          else {
1525
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." set with an empty value is ignored.");
1526
          }
1527
        break;
1528

    
1529
        // ----- Look for options that request an array of string for value
1530
        case PCLZIP_OPT_BY_NAME :
1531
          // ----- Check the number of parameters
1532
          if (($i+1) >= $p_size) {
1533
            // ----- Error log
1534
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1535

    
1536
            // ----- Return
1537
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1538
            return PclZip::errorCode();
1539
          }
1540

    
1541
          // ----- Get the value
1542
          if (is_string($p_options_list[$i+1])) {
1543
              $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1544
          }
1545
          else if (is_array($p_options_list[$i+1])) {
1546
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1547
          }
1548
          else {
1549
            // ----- Error log
1550
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1551

    
1552
            // ----- Return
1553
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1554
            return PclZip::errorCode();
1555
          }
1556
          ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1557
          $i++;
1558
        break;
1559

    
1560
        // ----- Look for options that request an EREG or PREG expression
1561
        case PCLZIP_OPT_BY_EREG :
1562
        case PCLZIP_OPT_BY_PREG :
1563
        //case PCLZIP_OPT_CRYPT :
1564
          // ----- Check the number of parameters
1565
          if (($i+1) >= $p_size) {
1566
            // ----- Error log
1567
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1568

    
1569
            // ----- Return
1570
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1571
            return PclZip::errorCode();
1572
          }
1573

    
1574
          // ----- Get the value
1575
          if (is_string($p_options_list[$i+1])) {
1576
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1577
          }
1578
          else {
1579
            // ----- Error log
1580
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1581

    
1582
            // ----- Return
1583
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1584
            return PclZip::errorCode();
1585
          }
1586
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1587
          $i++;
1588
        break;
1589

    
1590
        // ----- Look for options that takes a string
1591
        case PCLZIP_OPT_COMMENT :
1592
        case PCLZIP_OPT_ADD_COMMENT :
1593
        case PCLZIP_OPT_PREPEND_COMMENT :
1594
          // ----- Check the number of parameters
1595
          if (($i+1) >= $p_size) {
1596
            // ----- Error log
1597
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
1598
			                     "Missing parameter value for option '"
1599
								 .PclZipUtilOptionText($p_options_list[$i])
1600
								 ."'");
1601

    
1602
            // ----- Return
1603
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1604
            return PclZip::errorCode();
1605
          }
1606

    
1607
          // ----- Get the value
1608
          if (is_string($p_options_list[$i+1])) {
1609
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1610
          }
1611
          else {
1612
            // ----- Error log
1613
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
1614
			                     "Wrong parameter value for option '"
1615
								 .PclZipUtilOptionText($p_options_list[$i])
1616
								 ."'");
1617

    
1618
            // ----- Return
1619
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1620
            return PclZip::errorCode();
1621
          }
1622
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1623
          $i++;
1624
        break;
1625

    
1626
        // ----- Look for options that request an array of index
1627
        case PCLZIP_OPT_BY_INDEX :
1628
          // ----- Check the number of parameters
1629
          if (($i+1) >= $p_size) {
1630
            // ----- Error log
1631
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1632

    
1633
            // ----- Return
1634
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1635
            return PclZip::errorCode();
1636
          }
1637

    
1638
          // ----- Get the value
1639
          $v_work_list = array();
1640
          if (is_string($p_options_list[$i+1])) {
1641
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is a string '".$p_options_list[$i+1]."'");
1642

    
1643
              // ----- Remove spaces
1644
              $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
1645

    
1646
              // ----- Parse items
1647
              $v_work_list = explode(",", $p_options_list[$i+1]);
1648
          }
1649
          else if (is_integer($p_options_list[$i+1])) {
1650
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an integer '".$p_options_list[$i+1]."'");
1651
              $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1652
          }
1653
          else if (is_array($p_options_list[$i+1])) {
1654
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an array");
1655
              $v_work_list = $p_options_list[$i+1];
1656
          }
1657
          else {
1658
            // ----- Error log
1659
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1660

    
1661
            // ----- Return
1662
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1663
            return PclZip::errorCode();
1664
          }
1665
          
1666
          // ----- Reduce the index list
1667
          // each index item in the list must be a couple with a start and
1668
          // an end value : [0,3], [5-5], [8-10], ...
1669
          // ----- Check the format of each item
1670
          $v_sort_flag=false;
1671
          $v_sort_value=0;
1672
          for ($j=0; $j<sizeof($v_work_list); $j++) {
1673
              // ----- Explode the item
1674
              $v_item_list = explode("-", $v_work_list[$j]);
1675
              $v_size_item_list = sizeof($v_item_list);
1676
              
1677
              // ----- TBC : Here we might check that each item is a
1678
              // real integer ...
1679
              
1680
              // ----- Look for single value
1681
              if ($v_size_item_list == 1) {
1682
                  // ----- Set the option value
1683
                  $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1684
                  $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1685
              }
1686
              elseif ($v_size_item_list == 2) {
1687
                  // ----- Set the option value
1688
                  $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1689
                  $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1690
              }
1691
              else {
1692
                  // ----- Error log
1693
                  PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1694

    
1695
                  // ----- Return
1696
                  //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1697
                  return PclZip::errorCode();
1698
              }
1699

    
1700
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extracted index item = [".$v_result_list[$p_options_list[$i]][$j]['start'].",".$v_result_list[$p_options_list[$i]][$j]['end']."]");
1701

    
1702
              // ----- Look for list sort
1703
              if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1704
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The list should be sorted ...");
1705
                  $v_sort_flag=true;
1706

    
1707
                  // ----- TBC : An automatic sort should be writen ...
1708
                  // ----- Error log
1709
                  PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1710

    
1711
                  // ----- Return
1712
                  //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1713
                  return PclZip::errorCode();
1714
              }
1715
              $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1716
          }
1717
          
1718
          // ----- Sort the items
1719
          if ($v_sort_flag) {
1720
              // TBC : To Be Completed
1721
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "List sorting is not yet write ...");
1722
          }
1723

    
1724
          // ----- Next option
1725
          $i++;
1726
        break;
1727

    
1728
        // ----- Look for options that request no value
1729
        case PCLZIP_OPT_REMOVE_ALL_PATH :
1730
        case PCLZIP_OPT_EXTRACT_AS_STRING :
1731
        case PCLZIP_OPT_NO_COMPRESSION :
1732
        case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
1733
        case PCLZIP_OPT_REPLACE_NEWER :
1734
        case PCLZIP_OPT_STOP_ON_ERROR :
1735
          $v_result_list[$p_options_list[$i]] = true;
1736
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1737
        break;
1738

    
1739
        // ----- Look for options that request an octal value
1740
        case PCLZIP_OPT_SET_CHMOD :
1741
          // ----- Check the number of parameters
1742
          if (($i+1) >= $p_size) {
1743
            // ----- Error log
1744
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1745

    
1746
            // ----- Return
1747
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1748
            return PclZip::errorCode();
1749
          }
1750

    
1751
          // ----- Get the value
1752
          $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1753
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1754
          $i++;
1755
        break;
1756

    
1757
        // ----- Look for options that request a call-back
1758
        case PCLZIP_CB_PRE_EXTRACT :
1759
        case PCLZIP_CB_POST_EXTRACT :
1760
        case PCLZIP_CB_PRE_ADD :
1761
        case PCLZIP_CB_POST_ADD :
1762
        /* for futur use
1763
        case PCLZIP_CB_PRE_DELETE :
1764
        case PCLZIP_CB_POST_DELETE :
1765
        case PCLZIP_CB_PRE_LIST :
1766
        case PCLZIP_CB_POST_LIST :
1767
        */
1768
          // ----- Check the number of parameters
1769
          if (($i+1) >= $p_size) {
1770
            // ----- Error log
1771
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1772

    
1773
            // ----- Return
1774
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1775
            return PclZip::errorCode();
1776
          }
1777

    
1778
          // ----- Get the value
1779
          $v_function_name = $p_options_list[$i+1];
1780
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "call-back ".PclZipUtilOptionText($p_options_list[$i])." = '".$v_function_name."'");
1781

    
1782
          // ----- Check that the value is a valid existing function
1783
          if (!function_exists($v_function_name)) {
1784
            // ----- Error log
1785
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1786

    
1787
            // ----- Return
1788
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1789
            return PclZip::errorCode();
1790
          }
1791

    
1792
          // ----- Set the attribute
1793
          $v_result_list[$p_options_list[$i]] = $v_function_name;
1794
          $i++;
1795
        break;
1796

    
1797
        default :
1798
          // ----- Error log
1799
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1800
		                       "Unknown parameter '"
1801
							   .$p_options_list[$i]."'");
1802

    
1803
          // ----- Return
1804
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1805
          return PclZip::errorCode();
1806
      }
1807

    
1808
      // ----- Next options
1809
      $i++;
1810
    }
1811

    
1812
    // ----- Look for mandatory options
1813
    if ($v_requested_options !== false) {
1814
      for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1815
        // ----- Look for mandatory option
1816
        if ($v_requested_options[$key] == 'mandatory') {
1817
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
1818
          // ----- Look if present
1819
          if (!isset($v_result_list[$key])) {
1820
            // ----- Error log
1821
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1822

    
1823
            // ----- Return
1824
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1825
            return PclZip::errorCode();
1826
          }
1827
        }
1828
      }
1829
    }
1830

    
1831
    // ----- Return
1832
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1833
    return $v_result;
1834
  }
1835
  // --------------------------------------------------------------------------------
1836

    
1837
  // --------------------------------------------------------------------------------
1838
  // Function : privFileDescrParseAtt()
1839
  // Description :
1840
  // Parameters :
1841
  // Return Values :
1842
  //   1 on success.
1843
  //   0 on failure.
1844
  // --------------------------------------------------------------------------------
1845
  function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
1846
  {
1847
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrParseAtt", "");
1848
    $v_result=1;
1849
    
1850
    // ----- For each file in the list check the attributes
1851
    foreach ($p_file_list as $v_key => $v_value) {
1852
    
1853
      // ----- Check if the option is supported
1854
      if (!isset($v_requested_options[$v_key])) {
1855
        // ----- Error log
1856
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
1857

    
1858
        // ----- Return
1859
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1860
        return PclZip::errorCode();
1861
      }
1862

    
1863
      // ----- Look for attribute
1864
      switch ($v_key) {
1865
        case PCLZIP_ATT_FILE_NAME :
1866
          if (!is_string($v_value)) {
1867
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1868
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1869
            return PclZip::errorCode();
1870
          }
1871

    
1872
          $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
1873
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
1874
          
1875
          if ($p_filedescr['filename'] == '') {
1876
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
1877
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1878
            return PclZip::errorCode();
1879
          }
1880

    
1881
        break;
1882

    
1883
        case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
1884
          if (!is_string($v_value)) {
1885
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1886
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1887
            return PclZip::errorCode();
1888
          }
1889

    
1890
          $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
1891
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
1892

    
1893
          if ($p_filedescr['new_short_name'] == '') {
1894
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
1895
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1896
            return PclZip::errorCode();
1897
          }
1898
        break;
1899

    
1900
        case PCLZIP_ATT_FILE_NEW_FULL_NAME :
1901
          if (!is_string($v_value)) {
1902
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1903
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1904
            return PclZip::errorCode();
1905
          }
1906

    
1907
          $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
1908
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
1909

    
1910
          if ($p_filedescr['new_full_name'] == '') {
1911
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
1912
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1913
            return PclZip::errorCode();
1914
          }
1915
        break;
1916

    
1917
        // ----- Look for options that takes a string
1918
        case PCLZIP_ATT_FILE_COMMENT :
1919
          if (!is_string($v_value)) {
1920
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1921
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1922
            return PclZip::errorCode();
1923
          }
1924

    
1925
          $p_filedescr['comment'] = $v_value;
1926
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
1927
        break;
1928

    
1929
        case PCLZIP_ATT_FILE_MTIME :
1930
          if (!is_integer($v_value)) {
1931
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'");
1932
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1933
            return PclZip::errorCode();
1934
          }
1935

    
1936
          $p_filedescr['mtime'] = $v_value;
1937
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
1938
        break;
1939

    
1940
        case PCLZIP_ATT_FILE_CONTENT :
1941
          $p_filedescr['content'] = $v_value;
1942
          ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
1943
        break;
1944

    
1945
        default :
1946
          // ----- Error log
1947
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1948
		                           "Unknown parameter '".$v_key."'");
1949

    
1950
          // ----- Return
1951
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1952
          return PclZip::errorCode();
1953
      }
1954

    
1955
      // ----- Look for mandatory options
1956
      if ($v_requested_options !== false) {
1957
        for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1958
          // ----- Look for mandatory option
1959
          if ($v_requested_options[$key] == 'mandatory') {
1960
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
1961
            // ----- Look if present
1962
            if (!isset($p_file_list[$key])) {
1963
              PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1964
              //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1965
              return PclZip::errorCode();
1966
            }
1967
          }
1968
        }
1969
      }
1970
    
1971
    // end foreach
1972
    }
1973
    
1974
    // ----- Return
1975
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1976
    return $v_result;
1977
  }
1978
  // --------------------------------------------------------------------------------
1979

    
1980
  // --------------------------------------------------------------------------------
1981
  // Function : privFileDescrExpand()
1982
  // Description :
1983
  // Parameters :
1984
  // Return Values :
1985
  //   1 on success.
1986
  //   0 on failure.
1987
  // --------------------------------------------------------------------------------
1988
  function privFileDescrExpand(&$p_filedescr_list, &$p_options)
1989
  {
1990
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrExpand", "");
1991
    $v_result=1;
1992
    
1993
    // ----- Create a result list
1994
    $v_result_list = array();
1995
    
1996
    // ----- Look each entry
1997
    for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
1998
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for file ".$i.".");
1999
      
2000
      // ----- Get filedescr
2001
      $v_descr = $p_filedescr_list[$i];
2002
      
2003
      // ----- Reduce the filename
2004
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filedescr before reduction :'".$v_descr['filename']."'");
2005
      $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename']);
2006
      $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
2007
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filedescr after reduction :'".$v_descr['filename']."'");
2008
      
2009
      // ----- Look for real file or folder
2010
      if (file_exists($v_descr['filename'])) {
2011
        if (@is_file($v_descr['filename'])) {
2012
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a file");
2013
          $v_descr['type'] = 'file';
2014
        }
2015
        else if (@is_dir($v_descr['filename'])) {
2016
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a folder");
2017
          $v_descr['type'] = 'folder';
2018
        }
2019
        else if (@is_link($v_descr['filename'])) {
2020
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Unsupported file type : link");
2021
          // skip
2022
          continue;
2023
        }
2024
        else {
2025
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Unsupported file type : unknown type");
2026
          // skip
2027
          continue;
2028
        }
2029
      }
2030
      
2031
      // ----- Look for string added as file
2032
      else if (isset($v_descr['content'])) {
2033
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a string added as a file");
2034
        $v_descr['type'] = 'virtual_file';
2035
      }
2036
      
2037
      // ----- Missing file
2038
      else {
2039
        // ----- Error log
2040
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_descr['filename']."' does not exists");
2041
        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exists");
2042

    
2043
        // ----- Return
2044
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2045
        return PclZip::errorCode();
2046
      }
2047
      
2048
      // ----- Calculate the stored filename
2049
      $this->privCalculateStoredFilename($v_descr, $p_options);
2050
      
2051
      // ----- Add the descriptor in result list
2052
      $v_result_list[sizeof($v_result_list)] = $v_descr;
2053
      
2054
      // ----- Look for folder
2055
      if ($v_descr['type'] == 'folder') {
2056
        // ----- List of items in folder
2057
        $v_dirlist_descr = array();
2058
        $v_dirlist_nb = 0;
2059
        if ($v_folder_handler = @opendir($v_descr['filename'])) {
2060
          while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
2061
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for '".$v_item_handler."' in the directory");
2062

    
2063
            // ----- Skip '.' and '..'
2064
            if (($v_item_handler == '.') || ($v_item_handler == '..')) {
2065
                continue;
2066
            }
2067
            
2068
            // ----- Compose the full filename
2069
            $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
2070
            
2071
            // ----- Look for different stored filename
2072
            // Because the name of the folder was changed, the name of the
2073
            // files/sub-folders also change
2074
            if ($v_descr['stored_filename'] != $v_descr['filename']) {
2075
              if ($v_descr['stored_filename'] != '') {
2076
                $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
2077
              }
2078
              else {
2079
                $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
2080
              }
2081
            }
2082
      
2083
            $v_dirlist_nb++;
2084
          }
2085
          
2086
          @closedir($v_folder_handler);
2087
        }
2088
        else {
2089
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to open dir '".$v_descr['filename']."' in read mode. Skipped.");
2090
          // TBC : unable to open folder in read mode
2091
        }
2092
        
2093
        // ----- Expand each element of the list
2094
        if ($v_dirlist_nb != 0) {
2095
          // ----- Expand
2096
          if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
2097
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2098
            return $v_result;
2099
          }
2100
          
2101
          // ----- Concat the resulting list
2102
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Merging result list (size '".sizeof($v_result_list)."') with dirlist (size '".sizeof($v_dirlist_descr)."')");
2103
          $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
2104
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "merged result list is size '".sizeof($v_result_list)."'");
2105
        }
2106
        else {
2107
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Nothing in this folder to expand.");
2108
        }
2109
          
2110
        // ----- Free local array
2111
        unset($v_dirlist_descr);
2112
      }
2113
    }
2114
    
2115
    // ----- Get the result list
2116
    $p_filedescr_list = $v_result_list;
2117

    
2118
    // ----- Return
2119
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2120
    return $v_result;
2121
  }
2122
  // --------------------------------------------------------------------------------
2123

    
2124
  // --------------------------------------------------------------------------------
2125
  // Function : privCreate()
2126
  // Description :
2127
  // Parameters :
2128
  // Return Values :
2129
  // --------------------------------------------------------------------------------
2130
  function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
2131
  {
2132
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCreate", "list");
2133
    $v_result=1;
2134
    $v_list_detail = array();
2135
    
2136
    // ----- Magic quotes trick
2137
    $this->privDisableMagicQuotes();
2138

    
2139
    // ----- Open the file in write mode
2140
    if (($v_result = $this->privOpenFd('wb')) != 1)
2141
    {
2142
      // ----- Return
2143
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2144
      return $v_result;
2145
    }
2146

    
2147
    // ----- Add the list of files
2148
    $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
2149

    
2150
    // ----- Close
2151
    $this->privCloseFd();
2152

    
2153
    // ----- Magic quotes trick
2154
    $this->privSwapBackMagicQuotes();
2155

    
2156
    // ----- Return
2157
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2158
    return $v_result;
2159
  }
2160
  // --------------------------------------------------------------------------------
2161

    
2162
  // --------------------------------------------------------------------------------
2163
  // Function : privAdd()
2164
  // Description :
2165
  // Parameters :
2166
  // Return Values :
2167
  // --------------------------------------------------------------------------------
2168
  function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
2169
  {
2170
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAdd", "list");
2171
    $v_result=1;
2172
    $v_list_detail = array();
2173

    
2174
    // ----- Look if the archive exists or is empty
2175
    if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
2176
    {
2177
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, or is empty, create it.");
2178

    
2179
      // ----- Do a create
2180
      $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
2181

    
2182
      // ----- Return
2183
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2184
      return $v_result;
2185
    }
2186
    // ----- Magic quotes trick
2187
    $this->privDisableMagicQuotes();
2188

    
2189
    // ----- Open the zip file
2190
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2191
    if (($v_result=$this->privOpenFd('rb')) != 1)
2192
    {
2193
      // ----- Magic quotes trick
2194
      $this->privSwapBackMagicQuotes();
2195

    
2196
      // ----- Return
2197
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2198
      return $v_result;
2199
    }
2200

    
2201
    // ----- Read the central directory informations
2202
    $v_central_dir = array();
2203
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
2204
    {
2205
      $this->privCloseFd();
2206
      $this->privSwapBackMagicQuotes();
2207
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2208
      return $v_result;
2209
    }
2210

    
2211
    // ----- Go to beginning of File
2212
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
2213
    @rewind($this->zip_fd);
2214
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
2215

    
2216
    // ----- Creates a temporay file
2217
    $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
2218

    
2219
    // ----- Open the temporary file in write mode
2220
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2221
    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
2222
    {
2223
      $this->privCloseFd();
2224
      $this->privSwapBackMagicQuotes();
2225

    
2226
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
2227

    
2228
      // ----- Return
2229
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2230
      return PclZip::errorCode();
2231
    }
2232

    
2233
    // ----- Copy the files from the archive to the temporary file
2234
    // TBC : Here I should better append the file and go back to erase the central dir
2235
    $v_size = $v_central_dir['offset'];
2236
    while ($v_size != 0)
2237
    {
2238
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2239
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
2240
      $v_buffer = fread($this->zip_fd, $v_read_size);
2241
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
2242
      $v_size -= $v_read_size;
2243
    }
2244

    
2245
    // ----- Swap the file descriptor
2246
    // Here is a trick : I swap the temporary fd with the zip fd, in order to use
2247
    // the following methods on the temporary fil and not the real archive
2248
    $v_swap = $this->zip_fd;
2249
    $this->zip_fd = $v_zip_temp_fd;
2250
    $v_zip_temp_fd = $v_swap;
2251

    
2252
    // ----- Add the files
2253
    $v_header_list = array();
2254
    if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2255
    {
2256
      fclose($v_zip_temp_fd);
2257
      $this->privCloseFd();
2258
      @unlink($v_zip_temp_name);
2259
      $this->privSwapBackMagicQuotes();
2260

    
2261
      // ----- Return
2262
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2263
      return $v_result;
2264
    }
2265

    
2266
    // ----- Store the offset of the central dir
2267
    $v_offset = @ftell($this->zip_fd);
2268
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
2269

    
2270
    // ----- Copy the block of file headers from the old archive
2271
    $v_size = $v_central_dir['size'];
2272
    while ($v_size != 0)
2273
    {
2274
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2275
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
2276
      $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
2277
      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2278
      $v_size -= $v_read_size;
2279
    }
2280

    
2281
    // ----- Create the Central Dir files header
2282
    for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
2283
    {
2284
      // ----- Create the file header
2285
      if ($v_header_list[$i]['status'] == 'ok') {
2286
        if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2287
          fclose($v_zip_temp_fd);
2288
          $this->privCloseFd();
2289
          @unlink($v_zip_temp_name);
2290
          $this->privSwapBackMagicQuotes();
2291

    
2292
          // ----- Return
2293
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2294
          return $v_result;
2295
        }
2296
        $v_count++;
2297
      }
2298

    
2299
      // ----- Transform the header to a 'usable' info
2300
      $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2301
    }
2302

    
2303
    // ----- Zip file comment
2304
    $v_comment = $v_central_dir['comment'];
2305
    if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2306
      $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2307
    }
2308
    if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
2309
      $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
2310
    }
2311
    if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
2312
      $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
2313
    }
2314

    
2315
    // ----- Calculate the size of the central header
2316
    $v_size = @ftell($this->zip_fd)-$v_offset;
2317

    
2318
    // ----- Create the central dir footer
2319
    if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
2320
    {
2321
      // ----- Reset the file list
2322
      unset($v_header_list);
2323
      $this->privSwapBackMagicQuotes();
2324

    
2325
      // ----- Return
2326
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2327
      return $v_result;
2328
    }
2329

    
2330
    // ----- Swap back the file descriptor
2331
    $v_swap = $this->zip_fd;
2332
    $this->zip_fd = $v_zip_temp_fd;
2333
    $v_zip_temp_fd = $v_swap;
2334

    
2335
    // ----- Close
2336
    $this->privCloseFd();
2337

    
2338
    // ----- Close the temporary file
2339
    @fclose($v_zip_temp_fd);
2340

    
2341
    // ----- Magic quotes trick
2342
    $this->privSwapBackMagicQuotes();
2343

    
2344
    // ----- Delete the zip file
2345
    // TBC : I should test the result ...
2346
    @unlink($this->zipname);
2347

    
2348
    // ----- Rename the temporary file
2349
    // TBC : I should test the result ...
2350
    //@rename($v_zip_temp_name, $this->zipname);
2351
    PclZipUtilRename($v_zip_temp_name, $this->zipname);
2352

    
2353
    // ----- Return
2354
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2355
    return $v_result;
2356
  }
2357
  // --------------------------------------------------------------------------------
2358

    
2359
  // --------------------------------------------------------------------------------
2360
  // Function : privOpenFd()
2361
  // Description :
2362
  // Parameters :
2363
  // --------------------------------------------------------------------------------
2364
  function privOpenFd($p_mode)
2365
  {
2366
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOpenFd", 'mode='.$p_mode);
2367
    $v_result=1;
2368

    
2369
    // ----- Look if already open
2370
    if ($this->zip_fd != 0)
2371
    {
2372
      // ----- Error log
2373
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
2374

    
2375
      // ----- Return
2376
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2377
      return PclZip::errorCode();
2378
    }
2379

    
2380
    // ----- Open the zip file
2381
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Open file in '.$p_mode.' mode');
2382
    if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
2383
    {
2384
      // ----- Error log
2385
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
2386

    
2387
      // ----- Return
2388
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2389
      return PclZip::errorCode();
2390
    }
2391

    
2392
    // ----- Return
2393
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2394
    return $v_result;
2395
  }
2396
  // --------------------------------------------------------------------------------
2397

    
2398
  // --------------------------------------------------------------------------------
2399
  // Function : privCloseFd()
2400
  // Description :
2401
  // Parameters :
2402
  // --------------------------------------------------------------------------------
2403
  function privCloseFd()
2404
  {
2405
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCloseFd", "");
2406
    $v_result=1;
2407

    
2408
    if ($this->zip_fd != 0)
2409
      @fclose($this->zip_fd);
2410
    $this->zip_fd = 0;
2411

    
2412
    // ----- Return
2413
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2414
    return $v_result;
2415
  }
2416
  // --------------------------------------------------------------------------------
2417

    
2418
  // --------------------------------------------------------------------------------
2419
  // Function : privAddList()
2420
  // Description :
2421
  //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2422
  //   different from the real path of the file. This is usefull if you want to have PclTar
2423
  //   running in any directory, and memorize relative path from an other directory.
2424
  // Parameters :
2425
  //   $p_list : An array containing the file or directory names to add in the tar
2426
  //   $p_result_list : list of added files with their properties (specially the status field)
2427
  //   $p_add_dir : Path to add in the filename path archived
2428
  //   $p_remove_dir : Path to remove in the filename path archived
2429
  // Return Values :
2430
  // --------------------------------------------------------------------------------
2431
//  function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2432
  function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
2433
  {
2434
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddList", "list");
2435
    $v_result=1;
2436

    
2437
    // ----- Add the files
2438
    $v_header_list = array();
2439
    if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2440
    {
2441
      // ----- Return
2442
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2443
      return $v_result;
2444
    }
2445

    
2446
    // ----- Store the offset of the central dir
2447
    $v_offset = @ftell($this->zip_fd);
2448

    
2449
    // ----- Create the Central Dir files header
2450
    for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
2451
    {
2452
      // ----- Create the file header
2453
      if ($v_header_list[$i]['status'] == 'ok') {
2454
        if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2455
          // ----- Return
2456
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2457
          return $v_result;
2458
        }
2459
        $v_count++;
2460
      }
2461

    
2462
      // ----- Transform the header to a 'usable' info
2463
      $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2464
    }
2465

    
2466
    // ----- Zip file comment
2467
    $v_comment = '';
2468
    if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2469
      $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2470
    }
2471

    
2472
    // ----- Calculate the size of the central header
2473
    $v_size = @ftell($this->zip_fd)-$v_offset;
2474

    
2475
    // ----- Create the central dir footer
2476
    if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
2477
    {
2478
      // ----- Reset the file list
2479
      unset($v_header_list);
2480

    
2481
      // ----- Return
2482
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2483
      return $v_result;
2484
    }
2485

    
2486
    // ----- Return
2487
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2488
    return $v_result;
2489
  }
2490
  // --------------------------------------------------------------------------------
2491

    
2492
  // --------------------------------------------------------------------------------
2493
  // Function : privAddFileList()
2494
  // Description :
2495
  // Parameters :
2496
  //   $p_filedescr_list : An array containing the file description 
2497
  //                      or directory names to add in the zip
2498
  //   $p_result_list : list of added files with their properties (specially the status field)
2499
  // Return Values :
2500
  // --------------------------------------------------------------------------------
2501
  function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
2502
  {
2503
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileList", "filedescr_list");
2504
    $v_result=1;
2505
    $v_header = array();
2506

    
2507
    // ----- Recuperate the current number of elt in list
2508
    $v_nb = sizeof($p_result_list);
2509
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Before add, list have ".$v_nb." elements");
2510

    
2511
    // ----- Loop on the files
2512
    for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
2513
      // ----- Format the filename
2514
      $p_filedescr_list[$j]['filename']
2515
      = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
2516
      
2517
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for file '".$p_filedescr_list[$j]['filename']."'");
2518

    
2519
      // ----- Skip empty file names
2520
      // TBC : Can this be possible ? not checked in DescrParseAtt ?
2521
      if ($p_filedescr_list[$j]['filename'] == "") {
2522
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Skip empty filename");
2523
        continue;
2524
      }
2525

    
2526
      // ----- Check the filename
2527
      if (   ($p_filedescr_list[$j]['type'] != 'virtual_file')
2528
          && (!file_exists($p_filedescr_list[$j]['filename']))) {
2529
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_filedescr_list[$j]['filename']."' does not exists");
2530
        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exists");
2531
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2532
        return PclZip::errorCode();
2533
      }
2534

    
2535
      // ----- Look if it is a file or a dir with no all path remove option
2536
      // or a dir with all its path removed
2537
//      if (   (is_file($p_filedescr_list[$j]['filename']))
2538
//          || (   is_dir($p_filedescr_list[$j]['filename'])
2539
      if (   ($p_filedescr_list[$j]['type'] == 'file')
2540
          || ($p_filedescr_list[$j]['type'] == 'virtual_file')
2541
          || (   ($p_filedescr_list[$j]['type'] == 'folder')
2542
              && (   !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
2543
                  || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
2544
          ) {
2545

    
2546
        // ----- Add the file
2547
        $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
2548
                                       $p_options);
2549
        if ($v_result != 1) {
2550
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2551
          return $v_result;
2552
        }
2553

    
2554
        // ----- Store the file infos
2555
        $p_result_list[$v_nb++] = $v_header;
2556
      }
2557
    }
2558
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "After add, list have ".$v_nb." elements");
2559

    
2560
    // ----- Return
2561
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2562
    return $v_result;
2563
  }
2564
  // --------------------------------------------------------------------------------
2565

    
2566
  // --------------------------------------------------------------------------------
2567
  // Function : privAddFile()
2568
  // Description :
2569
  // Parameters :
2570
  // Return Values :
2571
  // --------------------------------------------------------------------------------
2572
  function privAddFile($p_filedescr, &$p_header, &$p_options)
2573
  {
2574
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFile", "filename='".$p_filedescr['filename']."'");
2575
    $v_result=1;
2576
    
2577
    // ----- Working variable
2578
    $p_filename = $p_filedescr['filename'];
2579

    
2580
    // TBC : Already done in the fileAtt check ... ?
2581
    if ($p_filename == "") {
2582
      // ----- Error log
2583
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
2584

    
2585
      // ----- Return
2586
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2587
      return PclZip::errorCode();
2588
    }
2589
  
2590
    // ----- Look for a stored different filename 
2591
    /* TBC : Removed
2592
    if (isset($p_filedescr['stored_filename'])) {
2593
      $v_stored_filename = $p_filedescr['stored_filename'];
2594
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is NOT the same "'.$v_stored_filename.'"');
2595
    }
2596
    else {
2597
      $v_stored_filename = $p_filedescr['stored_filename'];
2598
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is the same');
2599
    }
2600
    */
2601

    
2602
    // ----- Set the file properties
2603
    clearstatcache();
2604
    $p_header['version'] = 20;
2605
    $p_header['version_extracted'] = 10;
2606
    $p_header['flag'] = 0;
2607
    $p_header['compression'] = 0;
2608
    $p_header['crc'] = 0;
2609
    $p_header['compressed_size'] = 0;
2610
    $p_header['filename_len'] = strlen($p_filename);
2611
    $p_header['extra_len'] = 0;
2612
    $p_header['disk'] = 0;
2613
    $p_header['internal'] = 0;
2614
    $p_header['offset'] = 0;
2615
    $p_header['filename'] = $p_filename;
2616
// TBC : Removed    $p_header['stored_filename'] = $v_stored_filename;
2617
    $p_header['stored_filename'] = $p_filedescr['stored_filename'];
2618
    $p_header['extra'] = '';
2619
    $p_header['status'] = 'ok';
2620
    $p_header['index'] = -1;
2621

    
2622
    // ----- Look for regular file
2623
    if ($p_filedescr['type']=='file') {
2624
      $p_header['external'] = 0x00000000;
2625
      $p_header['size'] = filesize($p_filename);
2626
    }
2627
    
2628
    // ----- Look for regular folder
2629
    else if ($p_filedescr['type']=='folder') {
2630
      $p_header['external'] = 0x00000010;
2631
      $p_header['mtime'] = filemtime($p_filename);
2632
      $p_header['size'] = filesize($p_filename);
2633
    }
2634
    
2635
    // ----- Look for virtual file
2636
    else if ($p_filedescr['type'] == 'virtual_file') {
2637
      $p_header['external'] = 0x00000000;
2638
      $p_header['size'] = strlen($p_filedescr['content']);
2639
    }
2640
    
2641
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header external extension '".sprintf("0x%X",$p_header['external'])."'");
2642

    
2643
    // ----- Look for filetime
2644
    if (isset($p_filedescr['mtime'])) {
2645
      $p_header['mtime'] = $p_filedescr['mtime'];
2646
    }
2647
    else if ($p_filedescr['type'] == 'virtual_file') {
2648
      $p_header['mtime'] = mktime();
2649
    }
2650
    else {
2651
      $p_header['mtime'] = filemtime($p_filename);
2652
    }
2653

    
2654
    // ------ Look for file comment
2655
    if (isset($p_filedescr['comment'])) {
2656
      $p_header['comment_len'] = strlen($p_filedescr['comment']);
2657
      $p_header['comment'] = $p_filedescr['comment'];
2658
    }
2659
    else {
2660
      $p_header['comment_len'] = 0;
2661
      $p_header['comment'] = '';
2662
    }
2663

    
2664
    // ----- Look for pre-add callback
2665
    if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
2666
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_ADD]."()') is defined for the extraction");
2667

    
2668
      // ----- Generate a local information
2669
      $v_local_header = array();
2670
      $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2671

    
2672
      // ----- Call the callback
2673
      // Here I do not use call_user_func() because I need to send a reference to the
2674
      // header.
2675
      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
2676
      if ($v_result == 0) {
2677
        // ----- Change the file status
2678
        $p_header['status'] = "skipped";
2679
        $v_result = 1;
2680
      }
2681

    
2682
      // ----- Update the informations
2683
      // Only some fields can be modified
2684
      if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2685
        $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
2686
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New stored filename is '".$p_header['stored_filename']."'");
2687
      }
2688
    }
2689

    
2690
    // ----- Look for empty stored filename
2691
    if ($p_header['stored_filename'] == "") {
2692
      $p_header['status'] = "filtered";
2693
    }
2694
    
2695
    // ----- Check the path length
2696
    if (strlen($p_header['stored_filename']) > 0xFF) {
2697
      $p_header['status'] = 'filename_too_long';
2698
    }
2699

    
2700
    // ----- Look if no error, or file not skipped
2701
    if ($p_header['status'] == 'ok') {
2702

    
2703
      // ----- Look for a file
2704
//      if (is_file($p_filename))
2705
      if (   ($p_filedescr['type'] == 'file')
2706
          || ($p_filedescr['type'] == 'virtual_file')) {
2707
          
2708
        // ----- Get content from real file
2709
        if ($p_filedescr['type'] == 'file') {        
2710
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a file");
2711

    
2712
          // ----- Open the source file
2713
          if (($v_file = @fopen($p_filename, "rb")) == 0) {
2714
            PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2715
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2716
            return PclZip::errorCode();
2717
          }
2718

    
2719
          // ----- Read the file content
2720
          $v_content = @fread($v_file, $p_header['size']);
2721

    
2722
          // ----- Close the file
2723
          @fclose($v_file);
2724
        }
2725
        else if ($p_filedescr['type'] == 'virtual_file') {        
2726
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Add by string");
2727
          $v_content = $p_filedescr['content'];
2728
        }
2729

    
2730
        // ----- Calculate the CRC
2731
        $p_header['crc'] = @crc32($v_content);
2732
        
2733
        // ----- Look for no compression
2734
        if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2735
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be compressed");
2736
          // ----- Set header parameters
2737
          $p_header['compressed_size'] = $p_header['size'];
2738
          $p_header['compression'] = 0;
2739
        }
2740
        
2741
        // ----- Look for normal compression
2742
        else {
2743
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will be compressed");
2744
          // ----- Compress the content
2745
          $v_content = @gzdeflate($v_content);
2746

    
2747
          // ----- Set header parameters
2748
          $p_header['compressed_size'] = strlen($v_content);
2749
          $p_header['compression'] = 8;
2750
        }
2751
        
2752
        // ----- Look for encryption
2753
        /*
2754
        if ((isset($p_options[PCLZIP_OPT_CRYPT]))
2755
		    && ($p_options[PCLZIP_OPT_CRYPT] != "")) {
2756
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File need to be crypted ....");
2757
          
2758
          // Should be a random header
2759
          $v_header = 'xxxxxxxxxxxx';
2760
	      $v_content_compressed = PclZipUtilZipEncrypt($v_content_compressed,
2761
		                                           $p_header['compressed_size'],
2762
	                                               $v_header,
2763
												   $p_header['crc'],
2764
												   "test");
2765
												   
2766
          $p_header['compressed_size'] += 12;
2767
          $p_header['flag'] = 1;
2768
          
2769
          // ----- Add the header to the data
2770
          $v_content_compressed = $v_header.$v_content_compressed;
2771
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size after header : ".strlen($v_content_compressed)."");
2772
        }
2773
        */
2774

    
2775
        // ----- Call the header generation
2776
        if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2777
          @fclose($v_file);
2778
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2779
          return $v_result;
2780
        }
2781

    
2782
        // ----- Write the compressed (or not) content
2783
        @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2784
      }
2785

    
2786
      // ----- Look for a directory
2787
      else if ($p_filedescr['type'] == 'folder') {
2788
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a folder");
2789
        // ----- Look for directory last '/'
2790
        if (@substr($p_header['stored_filename'], -1) != '/') {
2791
          $p_header['stored_filename'] .= '/';
2792
        }
2793

    
2794
        // ----- Set the file properties
2795
        $p_header['size'] = 0;
2796
        //$p_header['external'] = 0x41FF0010;   // Value for a folder : to be checked
2797
        $p_header['external'] = 0x00000010;   // Value for a folder : to be checked
2798

    
2799
        // ----- Call the header generation
2800
        if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
2801
        {
2802
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2803
          return $v_result;
2804
        }
2805
      }
2806
    }
2807

    
2808
    // ----- Look for post-add callback
2809
    if (isset($p_options[PCLZIP_CB_POST_ADD])) {
2810
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_ADD]."()') is defined for the extraction");
2811

    
2812
      // ----- Generate a local information
2813
      $v_local_header = array();
2814
      $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2815

    
2816
      // ----- Call the callback
2817
      // Here I do not use call_user_func() because I need to send a reference to the
2818
      // header.
2819
      eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
2820
      if ($v_result == 0) {
2821
        // ----- Ignored
2822
        $v_result = 1;
2823
      }
2824

    
2825
      // ----- Update the informations
2826
      // Nothing can be modified
2827
    }
2828

    
2829
    // ----- Return
2830
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2831
    return $v_result;
2832
  }
2833
  // --------------------------------------------------------------------------------
2834

    
2835
  // --------------------------------------------------------------------------------
2836
  // Function : privCalculateStoredFilename()
2837
  // Description :
2838
  //   Based on file descriptor properties and global options, this method
2839
  //   calculate the filename that will be stored in the archive.
2840
  // Parameters :
2841
  // Return Values :
2842
  // --------------------------------------------------------------------------------
2843
  function privCalculateStoredFilename(&$p_filedescr, &$p_options)
2844
  {
2845
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCalculateStoredFilename", "filename='".$p_filedescr['filename']."'");
2846
    $v_result=1;
2847
    
2848
    // ----- Working variables
2849
    $p_filename = $p_filedescr['filename'];
2850
    if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
2851
      $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH];
2852
    }
2853
    else {
2854
      $p_add_dir = '';
2855
    }
2856
    if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) {
2857
      $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH];
2858
    }
2859
    else {
2860
      $p_remove_dir = '';
2861
    }
2862
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Remove path ='".$p_remove_dir."'");
2863
    if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
2864
      $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
2865
    }
2866
    else {
2867
      $p_remove_all_dir = 0;
2868
    }
2869

    
2870
    // ----- Look for full name change
2871
    if (isset($p_filedescr['new_full_name'])) {
2872
      $v_stored_filename = $p_filedescr['new_full_name'];
2873
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing full name of '".$p_filename."' for '".$v_stored_filename."'");
2874
    }
2875
    
2876
    // ----- Look for path and/or short name change
2877
    else {
2878

    
2879
      // ----- Look for short name change
2880
      if (isset($p_filedescr['new_short_name'])) {
2881
        $v_path_info = pathinfo($p_filename);
2882
        $v_dir = '';
2883
        if ($v_path_info['dirname'] != '') {
2884
          $v_dir = $v_path_info['dirname'].'/';
2885
        }
2886
        $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
2887
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing short name of '".$p_filename."' for '".$v_stored_filename."'");
2888
      }
2889
      else {
2890
        // ----- Calculate the stored filename
2891
        $v_stored_filename = $p_filename;
2892
      }
2893

    
2894
      // ----- Look for all path to remove
2895
      if ($p_remove_all_dir) {
2896
        $v_stored_filename = basename($p_filename);
2897
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove all path selected change '".$p_filename."' for '".$v_stored_filename."'");
2898
      }
2899
      // ----- Look for partial path remove
2900
      else if ($p_remove_dir != "") {
2901
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Partial path to remove");
2902
        if (substr($p_remove_dir, -1) != '/')
2903
          $p_remove_dir .= "/";
2904

    
2905
        if (   (substr($p_filename, 0, 2) == "./")
2906
            || (substr($p_remove_dir, 0, 2) == "./")) {
2907
            
2908
          if (   (substr($p_filename, 0, 2) == "./")
2909
              && (substr($p_remove_dir, 0, 2) != "./")) {
2910
            $p_remove_dir = "./".$p_remove_dir;
2911
          }
2912
          if (   (substr($p_filename, 0, 2) != "./")
2913
              && (substr($p_remove_dir, 0, 2) == "./")) {
2914
            $p_remove_dir = substr($p_remove_dir, 2);
2915
          }
2916
        }
2917

    
2918
        $v_compare = PclZipUtilPathInclusion($p_remove_dir,
2919
                                             $v_stored_filename);
2920
        if ($v_compare > 0) {
2921
          if ($v_compare == 2) {
2922
            $v_stored_filename = "";
2923
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Path to remove is the current folder");
2924
          }
2925
          else {
2926
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove path '$p_remove_dir' in file '$v_stored_filename'");
2927
            $v_stored_filename = substr($v_stored_filename,
2928
                                        strlen($p_remove_dir));
2929
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Result is '$v_stored_filename'");
2930
          }
2931
        }
2932
      }
2933
      // ----- Look for path to add
2934
      if ($p_add_dir != "") {
2935
        if (substr($p_add_dir, -1) == "/")
2936
          $v_stored_filename = $p_add_dir.$v_stored_filename;
2937
        else
2938
          $v_stored_filename = $p_add_dir."/".$v_stored_filename;
2939
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
2940
      }
2941
    }
2942

    
2943
    // ----- Filename (reduce the path of stored name)
2944
    $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
2945
    $p_filedescr['stored_filename'] = $v_stored_filename;
2946
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Stored filename will be '".$p_filedescr['stored_filename']."', strlen ".strlen($p_filedescr['stored_filename']));
2947
    
2948
    // ----- Return
2949
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2950
    return $v_result;
2951
  }
2952
  // --------------------------------------------------------------------------------
2953

    
2954
  // --------------------------------------------------------------------------------
2955
  // Function : privWriteFileHeader()
2956
  // Description :
2957
  // Parameters :
2958
  // Return Values :
2959
  // --------------------------------------------------------------------------------
2960
  function privWriteFileHeader(&$p_header)
2961
  {
2962
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
2963
    $v_result=1;
2964

    
2965
    // ----- Store the offset position of the file
2966
    $p_header['offset'] = ftell($this->zip_fd);
2967
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'File offset of the header :'.$p_header['offset']);
2968

    
2969
    // ----- Transform UNIX mtime to DOS format mdate/mtime
2970
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
2971
    $v_date = getdate($p_header['mtime']);
2972
    $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
2973
    $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
2974

    
2975
    // ----- Packed data
2976
    $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
2977
	                      $p_header['version_extracted'], $p_header['flag'],
2978
                          $p_header['compression'], $v_mtime, $v_mdate,
2979
                          $p_header['crc'], $p_header['compressed_size'],
2980
						  $p_header['size'],
2981
                          strlen($p_header['stored_filename']),
2982
						  $p_header['extra_len']);
2983

    
2984
    // ----- Write the first 148 bytes of the header in the archive
2985
    fputs($this->zip_fd, $v_binary_data, 30);
2986

    
2987
    // ----- Write the variable fields
2988
    if (strlen($p_header['stored_filename']) != 0)
2989
    {
2990
      fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
2991
    }
2992
    if ($p_header['extra_len'] != 0)
2993
    {
2994
      fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
2995
    }
2996

    
2997
    // ----- Return
2998
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2999
    return $v_result;
3000
  }
3001
  // --------------------------------------------------------------------------------
3002

    
3003
  // --------------------------------------------------------------------------------
3004
  // Function : privWriteCentralFileHeader()
3005
  // Description :
3006
  // Parameters :
3007
  // Return Values :
3008
  // --------------------------------------------------------------------------------
3009
  function privWriteCentralFileHeader(&$p_header)
3010
  {
3011
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
3012
    $v_result=1;
3013

    
3014
    // TBC
3015
    //for(reset($p_header); $key = key($p_header); next($p_header)) {
3016
    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
3017
    //}
3018

    
3019
    // ----- Transform UNIX mtime to DOS format mdate/mtime
3020
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
3021
    $v_date = getdate($p_header['mtime']);
3022
    $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3023
    $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3024

    
3025
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment size : \''.$p_header['comment_len'].'\'');
3026

    
3027
    // ----- Packed data
3028
    $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
3029
	                      $p_header['version'], $p_header['version_extracted'],
3030
                          $p_header['flag'], $p_header['compression'],
3031
						  $v_mtime, $v_mdate, $p_header['crc'],
3032
                          $p_header['compressed_size'], $p_header['size'],
3033
                          strlen($p_header['stored_filename']),
3034
						  $p_header['extra_len'], $p_header['comment_len'],
3035
                          $p_header['disk'], $p_header['internal'],
3036
						  $p_header['external'], $p_header['offset']);
3037

    
3038
    // ----- Write the 42 bytes of the header in the zip file
3039
    fputs($this->zip_fd, $v_binary_data, 46);
3040

    
3041
    // ----- Write the variable fields
3042
    if (strlen($p_header['stored_filename']) != 0)
3043
    {
3044
      fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3045
    }
3046
    if ($p_header['extra_len'] != 0)
3047
    {
3048
      fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3049
    }
3050
    if ($p_header['comment_len'] != 0)
3051
    {
3052
      fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
3053
    }
3054

    
3055
    // ----- Return
3056
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3057
    return $v_result;
3058
  }
3059
  // --------------------------------------------------------------------------------
3060

    
3061
  // --------------------------------------------------------------------------------
3062
  // Function : privWriteCentralHeader()
3063
  // Description :
3064
  // Parameters :
3065
  // Return Values :
3066
  // --------------------------------------------------------------------------------
3067
  function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
3068
  {
3069
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralHeader", 'nb_entries='.$p_nb_entries.', size='.$p_size.', offset='.$p_offset.', comment="'.$p_comment.'"');
3070
    $v_result=1;
3071

    
3072
    // ----- Packed data
3073
    $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
3074
	                      $p_nb_entries, $p_size,
3075
						  $p_offset, strlen($p_comment));
3076

    
3077
    // ----- Write the 22 bytes of the header in the zip file
3078
    fputs($this->zip_fd, $v_binary_data, 22);
3079

    
3080
    // ----- Write the variable fields
3081
    if (strlen($p_comment) != 0)
3082
    {
3083
      fputs($this->zip_fd, $p_comment, strlen($p_comment));
3084
    }
3085

    
3086
    // ----- Return
3087
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3088
    return $v_result;
3089
  }
3090
  // --------------------------------------------------------------------------------
3091

    
3092
  // --------------------------------------------------------------------------------
3093
  // Function : privList()
3094
  // Description :
3095
  // Parameters :
3096
  // Return Values :
3097
  // --------------------------------------------------------------------------------
3098
  function privList(&$p_list)
3099
  {
3100
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privList", "list");
3101
    $v_result=1;
3102

    
3103
    // ----- Magic quotes trick
3104
    $this->privDisableMagicQuotes();
3105

    
3106
    // ----- Open the zip file
3107
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
3108
    if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
3109
    {
3110
      // ----- Magic quotes trick
3111
      $this->privSwapBackMagicQuotes();
3112
      
3113
      // ----- Error log
3114
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
3115

    
3116
      // ----- Return
3117
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3118
      return PclZip::errorCode();
3119
    }
3120

    
3121
    // ----- Read the central directory informations
3122
    $v_central_dir = array();
3123
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3124
    {
3125
      $this->privSwapBackMagicQuotes();
3126
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3127
      return $v_result;
3128
    }
3129

    
3130
    // ----- Go to beginning of Central Dir
3131
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset : ".$v_central_dir['offset']."'");
3132
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
3133
    @rewind($this->zip_fd);
3134
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
3135
    if (@fseek($this->zip_fd, $v_central_dir['offset']))
3136
    {
3137
      $this->privSwapBackMagicQuotes();
3138

    
3139
      // ----- Error log
3140
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3141

    
3142
      // ----- Return
3143
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3144
      return PclZip::errorCode();
3145
    }
3146
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
3147

    
3148
    // ----- Read each entry
3149
    for ($i=0; $i<$v_central_dir['entries']; $i++)
3150
    {
3151
      // ----- Read the file header
3152
      if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3153
      {
3154
        $this->privSwapBackMagicQuotes();
3155
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3156
        return $v_result;
3157
      }
3158
      $v_header['index'] = $i;
3159

    
3160
      // ----- Get the only interesting attributes
3161
      $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
3162
      unset($v_header);
3163
    }
3164

    
3165
    // ----- Close the zip file
3166
    $this->privCloseFd();
3167

    
3168
    // ----- Magic quotes trick
3169
    $this->privSwapBackMagicQuotes();
3170

    
3171
    // ----- Return
3172
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3173
    return $v_result;
3174
  }
3175
  // --------------------------------------------------------------------------------
3176

    
3177
  // --------------------------------------------------------------------------------
3178
  // Function : privConvertHeader2FileInfo()
3179
  // Description :
3180
  //   This function takes the file informations from the central directory
3181
  //   entries and extract the interesting parameters that will be given back.
3182
  //   The resulting file infos are set in the array $p_info
3183
  //     $p_info['filename'] : Filename with full path. Given by user (add),
3184
  //                           extracted in the filesystem (extract).
3185
  //     $p_info['stored_filename'] : Stored filename in the archive.
3186
  //     $p_info['size'] = Size of the file.
3187
  //     $p_info['compressed_size'] = Compressed size of the file.
3188
  //     $p_info['mtime'] = Last modification date of the file.
3189
  //     $p_info['comment'] = Comment associated with the file.
3190
  //     $p_info['folder'] = true/false : indicates if the entry is a folder or not.
3191
  //     $p_info['status'] = status of the action on the file.
3192
  //     $p_info['crc'] = CRC of the file content.
3193
  // Parameters :
3194
  // Return Values :
3195
  // --------------------------------------------------------------------------------
3196
  function privConvertHeader2FileInfo($p_header, &$p_info)
3197
  {
3198
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privConvertHeader2FileInfo", "Filename='".$p_header['filename']."'");
3199
    $v_result=1;
3200

    
3201
    // ----- Get the interesting attributes
3202
    $p_info['filename'] = $p_header['filename'];
3203
    $p_info['stored_filename'] = $p_header['stored_filename'];
3204
    $p_info['size'] = $p_header['size'];
3205
    $p_info['compressed_size'] = $p_header['compressed_size'];
3206
    $p_info['mtime'] = $p_header['mtime'];
3207
    $p_info['comment'] = $p_header['comment'];
3208
    $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
3209
    $p_info['index'] = $p_header['index'];
3210
    $p_info['status'] = $p_header['status'];
3211
    $p_info['crc'] = $p_header['crc'];
3212

    
3213
    // ----- Return
3214
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3215
    return $v_result;
3216
  }
3217
  // --------------------------------------------------------------------------------
3218

    
3219
  // --------------------------------------------------------------------------------
3220
  // Function : privExtractByRule()
3221
  // Description :
3222
  //   Extract a file or directory depending of rules (by index, by name, ...)
3223
  // Parameters :
3224
  //   $p_file_list : An array where will be placed the properties of each
3225
  //                  extracted file
3226
  //   $p_path : Path to add while writing the extracted files
3227
  //   $p_remove_path : Path to remove (from the file memorized path) while writing the
3228
  //                    extracted files. If the path does not match the file path,
3229
  //                    the file is extracted with its memorized path.
3230
  //                    $p_remove_path does not apply to 'list' mode.
3231
  //                    $p_path and $p_remove_path are commulative.
3232
  // Return Values :
3233
  //   1 on success,0 or less on error (see error code list)
3234
  // --------------------------------------------------------------------------------
3235
  function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3236
  {
3237
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtractByRule", "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
3238
    $v_result=1;
3239

    
3240
    // ----- Magic quotes trick
3241
    $this->privDisableMagicQuotes();
3242

    
3243
    // ----- Check the path
3244
    if (   ($p_path == "")
3245
	    || (   (substr($p_path, 0, 1) != "/")
3246
		    && (substr($p_path, 0, 3) != "../")
3247
			&& (substr($p_path,1,2)!=":/")))
3248
      $p_path = "./".$p_path;
3249

    
3250
    // ----- Reduce the path last (and duplicated) '/'
3251
    if (($p_path != "./") && ($p_path != "/"))
3252
    {
3253
      // ----- Look for the path end '/'
3254
      while (substr($p_path, -1) == "/")
3255
      {
3256
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
3257
        $p_path = substr($p_path, 0, strlen($p_path)-1);
3258
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
3259
      }
3260
    }
3261

    
3262
    // ----- Look for path to remove format (should end by /)
3263
    if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
3264
    {
3265
      $p_remove_path .= '/';
3266
    }
3267
    $p_remove_path_size = strlen($p_remove_path);
3268

    
3269
    // ----- Open the zip file
3270
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
3271
    if (($v_result = $this->privOpenFd('rb')) != 1)
3272
    {
3273
      $this->privSwapBackMagicQuotes();
3274
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3275
      return $v_result;
3276
    }
3277

    
3278
    // ----- Read the central directory informations
3279
    $v_central_dir = array();
3280
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3281
    {
3282
      // ----- Close the zip file
3283
      $this->privCloseFd();
3284
      $this->privSwapBackMagicQuotes();
3285

    
3286
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3287
      return $v_result;
3288
    }
3289

    
3290
    // ----- Start at beginning of Central Dir
3291
    $v_pos_entry = $v_central_dir['offset'];
3292

    
3293
    // ----- Read each entry
3294
    $j_start = 0;
3295
    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
3296
    {
3297
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : '$i'");
3298

    
3299
      // ----- Read next Central dir entry
3300
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position before rewind : ".ftell($this->zip_fd)."'");
3301
      @rewind($this->zip_fd);
3302
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position after rewind : ".ftell($this->zip_fd)."'");
3303
      if (@fseek($this->zip_fd, $v_pos_entry))
3304
      {
3305
        // ----- Close the zip file
3306
        $this->privCloseFd();
3307
        $this->privSwapBackMagicQuotes();
3308

    
3309
        // ----- Error log
3310
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3311

    
3312
        // ----- Return
3313
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3314
        return PclZip::errorCode();
3315
      }
3316
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");
3317

    
3318
      // ----- Read the file header
3319
      $v_header = array();
3320
      if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3321
      {
3322
        // ----- Close the zip file
3323
        $this->privCloseFd();
3324
        $this->privSwapBackMagicQuotes();
3325

    
3326
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3327
        return $v_result;
3328
      }
3329

    
3330
      // ----- Store the index
3331
      $v_header['index'] = $i;
3332

    
3333
      // ----- Store the file position
3334
      $v_pos_entry = ftell($this->zip_fd);
3335

    
3336
      // ----- Look for the specific extract rules
3337
      $v_extract = false;
3338

    
3339
      // ----- Look for extract by name rule
3340
      if (   (isset($p_options[PCLZIP_OPT_BY_NAME]))
3341
          && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
3342
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
3343

    
3344
          // ----- Look if the filename is in the list
3345
          for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
3346
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
3347

    
3348
              // ----- Look for a directory
3349
              if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
3350
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
3351

    
3352
                  // ----- Look if the directory is in the filename path
3353
                  if (   (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
3354
                      && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
3355
                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
3356
                      $v_extract = true;
3357
                  }
3358
              }
3359
              // ----- Look for a filename
3360
              elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
3361
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
3362
                  $v_extract = true;
3363
              }
3364
          }
3365
      }
3366

    
3367
      // ----- Look for extract by ereg rule
3368
      else if (   (isset($p_options[PCLZIP_OPT_BY_EREG]))
3369
               && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
3370
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
3371

    
3372
          if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
3373
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
3374
              $v_extract = true;
3375
          }
3376
      }
3377

    
3378
      // ----- Look for extract by preg rule
3379
      else if (   (isset($p_options[PCLZIP_OPT_BY_PREG]))
3380
               && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
3381
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
3382

    
3383
          if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
3384
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
3385
              $v_extract = true;
3386
          }
3387
      }
3388

    
3389
      // ----- Look for extract by index rule
3390
      else if (   (isset($p_options[PCLZIP_OPT_BY_INDEX]))
3391
               && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
3392
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
3393
          
3394
          // ----- Look if the index is in the list
3395
          for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
3396
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
3397

    
3398
              if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
3399
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
3400
                  $v_extract = true;
3401
              }
3402
              if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
3403
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
3404
                  $j_start = $j+1;
3405
              }
3406

    
3407
              if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
3408
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
3409
                  break;
3410
              }
3411
          }
3412
      }
3413

    
3414
      // ----- Look for no rule, which means extract all the archive
3415
      else {
3416
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with no rule (extract all)");
3417
          $v_extract = true;
3418
      }
3419

    
3420
	  // ----- Check compression method
3421
	  if (   ($v_extract)
3422
	      && (   ($v_header['compression'] != 8)
3423
		      && ($v_header['compression'] != 0))) {
3424
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported compression method (".$v_header['compression'].")");
3425
          $v_header['status'] = 'unsupported_compression';
3426

    
3427
          // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3428
          if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3429
		      && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3430
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
3431

    
3432
              $this->privSwapBackMagicQuotes();
3433
              
3434
              PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
3435
			                       "Filename '".$v_header['stored_filename']."' is "
3436
				  	    	  	   ."compressed by an unsupported compression "
3437
				  	    	  	   ."method (".$v_header['compression'].") ");
3438

    
3439
              //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3440
              return PclZip::errorCode();
3441
		  }
3442
	  }
3443
	  
3444
	  // ----- Check encrypted files
3445
	  if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
3446
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported file encryption");
3447
          $v_header['status'] = 'unsupported_encryption';
3448

    
3449
          // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3450
          if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3451
		      && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3452
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
3453

    
3454
              $this->privSwapBackMagicQuotes();
3455

    
3456
              PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
3457
			                       "Unsupported encryption for "
3458
				  	    	  	   ." filename '".$v_header['stored_filename']
3459
								   ."'");
3460

    
3461
              //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3462
              return PclZip::errorCode();
3463
		  }
3464
    }
3465

    
3466
      // ----- Look for real extraction
3467
      if (($v_extract) && ($v_header['status'] != 'ok')) {
3468
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "No need for extract");
3469
          $v_result = $this->privConvertHeader2FileInfo($v_header,
3470
		                                        $p_file_list[$v_nb_extracted++]);
3471
          if ($v_result != 1) {
3472
              $this->privCloseFd();
3473
              $this->privSwapBackMagicQuotes();
3474
              //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3475
              return $v_result;
3476
          }
3477

    
3478
          $v_extract = false;
3479
      }
3480
      
3481
      // ----- Look for real extraction
3482
      if ($v_extract)
3483
      {
3484
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file '".$v_header['filename']."', index '$i'");
3485

    
3486
        // ----- Go to the file position
3487
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
3488
        @rewind($this->zip_fd);
3489
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
3490
        if (@fseek($this->zip_fd, $v_header['offset']))
3491
        {
3492
          // ----- Close the zip file
3493
          $this->privCloseFd();
3494

    
3495
          $this->privSwapBackMagicQuotes();
3496

    
3497
          // ----- Error log
3498
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3499

    
3500
          // ----- Return
3501
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3502
          return PclZip::errorCode();
3503
        }
3504
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
3505

    
3506
        // ----- Look for extraction as string
3507
        if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
3508

    
3509
          // ----- Extracting the file
3510
          $v_result1 = $this->privExtractFileAsString($v_header, $v_string);
3511
          if ($v_result1 < 1) {
3512
            $this->privCloseFd();
3513
            $this->privSwapBackMagicQuotes();
3514
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
3515
            return $v_result1;
3516
          }
3517

    
3518
          // ----- Get the only interesting attributes
3519
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
3520
          {
3521
            // ----- Close the zip file
3522
            $this->privCloseFd();
3523
            $this->privSwapBackMagicQuotes();
3524

    
3525
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3526
            return $v_result;
3527
          }
3528

    
3529
          // ----- Set the file content
3530
          $p_file_list[$v_nb_extracted]['content'] = $v_string;
3531

    
3532
          // ----- Next extracted file
3533
          $v_nb_extracted++;
3534
          
3535
          // ----- Look for user callback abort
3536
          if ($v_result1 == 2) {
3537
          	break;
3538
          }
3539
        }
3540
        // ----- Look for extraction in standard output
3541
        elseif (   (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
3542
		        && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
3543
          // ----- Extracting the file in standard output
3544
          $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
3545
          if ($v_result1 < 1) {
3546
            $this->privCloseFd();
3547
            $this->privSwapBackMagicQuotes();
3548
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
3549
            return $v_result1;
3550
          }
3551

    
3552
          // ----- Get the only interesting attributes
3553
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
3554
            $this->privCloseFd();
3555
            $this->privSwapBackMagicQuotes();
3556
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3557
            return $v_result;
3558
          }
3559

    
3560
          // ----- Look for user callback abort
3561
          if ($v_result1 == 2) {
3562
          	break;
3563
          }
3564
        }
3565
        // ----- Look for normal extraction
3566
        else {
3567
          // ----- Extracting the file
3568
          $v_result1 = $this->privExtractFile($v_header,
3569
		                                      $p_path, $p_remove_path,
3570
											  $p_remove_all_path,
3571
											  $p_options);
3572
          if ($v_result1 < 1) {
3573
            $this->privCloseFd();
3574
            $this->privSwapBackMagicQuotes();
3575
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
3576
            return $v_result1;
3577
          }
3578

    
3579
          // ----- Get the only interesting attributes
3580
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
3581
          {
3582
            // ----- Close the zip file
3583
            $this->privCloseFd();
3584
            $this->privSwapBackMagicQuotes();
3585

    
3586
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3587
            return $v_result;
3588
          }
3589

    
3590
          // ----- Look for user callback abort
3591
          if ($v_result1 == 2) {
3592
          	break;
3593
          }
3594
        }
3595
      }
3596
    }
3597

    
3598
    // ----- Close the zip file
3599
    $this->privCloseFd();
3600
    $this->privSwapBackMagicQuotes();
3601

    
3602
    // ----- Return
3603
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3604
    return $v_result;
3605
  }
3606
  // --------------------------------------------------------------------------------
3607

    
3608
  // --------------------------------------------------------------------------------
3609
  // Function : privExtractFile()
3610
  // Description :
3611
  // Parameters :
3612
  // Return Values :
3613
  //
3614
  // 1 : ... ?
3615
  // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
3616
  // --------------------------------------------------------------------------------
3617
  function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3618
  {
3619
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFile', "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
3620
    $v_result=1;
3621

    
3622
    // ----- Read the file header
3623
    if (($v_result = $this->privReadFileHeader($v_header)) != 1)
3624
    {
3625
      // ----- Return
3626
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3627
      return $v_result;
3628
    }
3629

    
3630
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
3631

    
3632
    // ----- Check that the file header is coherent with $p_entry info
3633
    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
3634
        // TBC
3635
    }
3636

    
3637
    // ----- Look for all path to remove
3638
    if ($p_remove_all_path == true) {
3639
        // ----- Look for folder entry that not need to be extracted
3640
        if (($p_entry['external']&0x00000010)==0x00000010) {
3641
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The entry is a folder : need to be filtered");
3642

    
3643
            $p_entry['status'] = "filtered";
3644

    
3645
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3646
            return $v_result;
3647
        }
3648

    
3649
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "All path is removed");
3650
        // ----- Get the basename of the path
3651
        $p_entry['filename'] = basename($p_entry['filename']);
3652
    }
3653

    
3654
    // ----- Look for path to remove
3655
    else if ($p_remove_path != "")
3656
    {
3657
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look for some path to remove");
3658
      if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
3659
      {
3660
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The folder is the same as the removed path '".$p_entry['filename']."'");
3661

    
3662
        // ----- Change the file status
3663
        $p_entry['status'] = "filtered";
3664

    
3665
        // ----- Return
3666
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3667
        return $v_result;
3668
      }
3669

    
3670
      $p_remove_path_size = strlen($p_remove_path);
3671
      if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
3672
      {
3673
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '".$p_entry['filename']."'");
3674

    
3675
        // ----- Remove the path
3676
        $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
3677

    
3678
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Resulting file is '".$p_entry['filename']."'");
3679
      }
3680
    }
3681

    
3682
    // ----- Add the path
3683
    if ($p_path != '') {
3684
      $p_entry['filename'] = $p_path."/".$p_entry['filename'];
3685
    }
3686
    
3687
    // ----- Check a base_dir_restriction
3688
    if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
3689
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Check the extract directory restriction");
3690
      $v_inclusion
3691
      = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
3692
                                $p_entry['filename']); 
3693
      if ($v_inclusion == 0) {
3694
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_EXTRACT_DIR_RESTRICTION is selected, file is outside restriction");
3695

    
3696
        PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
3697
			                     "Filename '".$p_entry['filename']."' is "
3698
								 ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
3699

    
3700
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3701
        return PclZip::errorCode();
3702
      }
3703
    }
3704

    
3705
    // ----- Look for pre-extract callback
3706
    if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
3707
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
3708

    
3709
      // ----- Generate a local information
3710
      $v_local_header = array();
3711
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3712

    
3713
      // ----- Call the callback
3714
      // Here I do not use call_user_func() because I need to send a reference to the
3715
      // header.
3716
      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
3717
      if ($v_result == 0) {
3718
        // ----- Change the file status
3719
        $p_entry['status'] = "skipped";
3720
        $v_result = 1;
3721
      }
3722
      
3723
      // ----- Look for abort result
3724
      if ($v_result == 2) {
3725
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
3726
        // ----- This status is internal and will be changed in 'skipped'
3727
        $p_entry['status'] = "aborted";
3728
      	$v_result = PCLZIP_ERR_USER_ABORTED;
3729
      }
3730

    
3731
      // ----- Update the informations
3732
      // Only some fields can be modified
3733
      $p_entry['filename'] = $v_local_header['filename'];
3734
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
3735
    }
3736

    
3737
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
3738

    
3739
    // ----- Look if extraction should be done
3740
    if ($p_entry['status'] == 'ok') {
3741

    
3742
    // ----- Look for specific actions while the file exist
3743
    if (file_exists($p_entry['filename']))
3744
    {
3745
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_entry['filename']."' already exists");
3746

    
3747
      // ----- Look if file is a directory
3748
      if (is_dir($p_entry['filename']))
3749
      {
3750
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is a directory");
3751

    
3752
        // ----- Change the file status
3753
        $p_entry['status'] = "already_a_directory";
3754
        
3755
        // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3756
        // For historical reason first PclZip implementation does not stop
3757
        // when this kind of error occurs.
3758
        if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3759
		    && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3760
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
3761

    
3762
            PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
3763
			                     "Filename '".$p_entry['filename']."' is "
3764
								 ."already used by an existing directory");
3765

    
3766
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3767
            return PclZip::errorCode();
3768
		}
3769
      }
3770
      // ----- Look if file is write protected
3771
      else if (!is_writeable($p_entry['filename']))
3772
      {
3773
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is write protected");
3774

    
3775
        // ----- Change the file status
3776
        $p_entry['status'] = "write_protected";
3777

    
3778
        // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3779
        // For historical reason first PclZip implementation does not stop
3780
        // when this kind of error occurs.
3781
        if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3782
		    && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3783
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
3784

    
3785
            PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
3786
			                     "Filename '".$p_entry['filename']."' exists "
3787
								 ."and is write protected");
3788

    
3789
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3790
            return PclZip::errorCode();
3791
		}
3792
      }
3793

    
3794
      // ----- Look if the extracted file is older
3795
      else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
3796
      {
3797
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is newer (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");
3798
        // ----- Change the file status
3799
        if (   (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
3800
		    && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
3801
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_REPLACE_NEWER is selected, file will be replaced");
3802
		}
3803
		else {
3804
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be replaced");
3805
            $p_entry['status'] = "newer_exist";
3806

    
3807
            // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3808
            // For historical reason first PclZip implementation does not stop
3809
            // when this kind of error occurs.
3810
            if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3811
		        && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3812
                //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
3813

    
3814
                PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
3815
			             "Newer version of '".$p_entry['filename']."' exists "
3816
					    ."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
3817

    
3818
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3819
                return PclZip::errorCode();
3820
		    }
3821
		}
3822
      }
3823
      else {
3824
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is older than the extrated one - will be replaced by the extracted one (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");
3825
      }
3826
    }
3827

    
3828
    // ----- Check the directory availability and create it if necessary
3829
    else {
3830
      if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
3831
        $v_dir_to_check = $p_entry['filename'];
3832
      else if (!strstr($p_entry['filename'], "/"))
3833
        $v_dir_to_check = "";
3834
      else
3835
        $v_dir_to_check = dirname($p_entry['filename']);
3836

    
3837
      if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
3838
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '".$p_entry['filename']."'");
3839

    
3840
        // ----- Change the file status
3841
        $p_entry['status'] = "path_creation_fail";
3842

    
3843
        // ----- Return
3844
        ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3845
        //return $v_result;
3846
        $v_result = 1;
3847
      }
3848
    }
3849
    }
3850

    
3851
    // ----- Look if extraction should be done
3852
    if ($p_entry['status'] == 'ok') {
3853

    
3854
      // ----- Do the extraction (if not a folder)
3855
      if (!(($p_entry['external']&0x00000010)==0x00000010))
3856
      {
3857
        // ----- Look for not compressed file
3858
        if ($p_entry['compression'] == 0) {
3859
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
3860

    
3861
		  // ----- Opening destination file
3862
          if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
3863
          {
3864
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
3865

    
3866
            // ----- Change the file status
3867
            $p_entry['status'] = "write_error";
3868

    
3869
            // ----- Return
3870
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3871
            return $v_result;
3872
          }
3873

    
3874
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read '".$p_entry['size']."' bytes");
3875

    
3876
          // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3877
          $v_size = $p_entry['compressed_size'];
3878
          while ($v_size != 0)
3879
          {
3880
            $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3881
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
3882
            $v_buffer = @fread($this->zip_fd, $v_read_size);
3883
            /* Try to speed up the code
3884
            $v_binary_data = pack('a'.$v_read_size, $v_buffer);
3885
            @fwrite($v_dest_file, $v_binary_data, $v_read_size);
3886
            */
3887
            @fwrite($v_dest_file, $v_buffer, $v_read_size);            
3888
            $v_size -= $v_read_size;
3889
          }
3890

    
3891
          // ----- Closing the destination file
3892
          fclose($v_dest_file);
3893

    
3894
          // ----- Change the file mtime
3895
          touch($p_entry['filename'], $p_entry['mtime']);
3896
          
3897

    
3898
        }
3899
        else {
3900
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (Compression method ".$p_entry['compression'].")");
3901
          // ----- TBC
3902
          // Need to be finished
3903
          if (($p_entry['flag'] & 1) == 1) {
3904
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File is encrypted");
3905
            /*
3906
              // ----- Read the encryption header
3907
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read 12 encryption header bytes");
3908
              $v_encryption_header = @fread($this->zip_fd, 12);
3909
              
3910
              // ----- Read the encrypted & compressed file in a buffer
3911
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".($p_entry['compressed_size']-12)."' compressed & encrypted bytes");
3912
              $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']-12);
3913
              
3914
              // ----- Decrypt the buffer
3915
              $this->privDecrypt($v_encryption_header, $v_buffer,
3916
			                     $p_entry['compressed_size']-12, $p_entry['crc']);
3917
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Buffer is '".$v_buffer."'");
3918
              */
3919
          }
3920
          else {
3921
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".$p_entry['compressed_size']."' compressed bytes");
3922
              // ----- Read the compressed file in a buffer (one shot)
3923
              $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3924
          }
3925
          
3926
          // ----- Decompress the file
3927
          $v_file_content = @gzinflate($v_buffer);
3928
          unset($v_buffer);
3929
          if ($v_file_content === FALSE) {
3930
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to inflate compressed file");
3931

    
3932
            // ----- Change the file status
3933
            // TBC
3934
            $p_entry['status'] = "error";
3935
            
3936
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3937
            return $v_result;
3938
          }
3939
          
3940
          // ----- Opening destination file
3941
          if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3942
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
3943

    
3944
            // ----- Change the file status
3945
            $p_entry['status'] = "write_error";
3946

    
3947
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3948
            return $v_result;
3949
          }
3950

    
3951
          // ----- Write the uncompressed data
3952
          @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
3953
          unset($v_file_content);
3954

    
3955
          // ----- Closing the destination file
3956
          @fclose($v_dest_file);
3957

    
3958
          // ----- Change the file mtime
3959
          @touch($p_entry['filename'], $p_entry['mtime']);
3960
        }
3961

    
3962
        // ----- Look for chmod option
3963
        if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
3964
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "chmod option activated '".$p_options[PCLZIP_OPT_SET_CHMOD]."'");
3965

    
3966
          // ----- Change the mode of the file
3967
          @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
3968
        }
3969

    
3970
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
3971
      }
3972
    }
3973

    
3974
	// ----- Change abort status
3975
	if ($p_entry['status'] == "aborted") {
3976
      $p_entry['status'] = "skipped";
3977
	}
3978
	
3979
    // ----- Look for post-extract callback
3980
    elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
3981
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
3982

    
3983
      // ----- Generate a local information
3984
      $v_local_header = array();
3985
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3986

    
3987
      // ----- Call the callback
3988
      // Here I do not use call_user_func() because I need to send a reference to the
3989
      // header.
3990
      eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
3991

    
3992
      // ----- Look for abort result
3993
      if ($v_result == 2) {
3994
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
3995
      	$v_result = PCLZIP_ERR_USER_ABORTED;
3996
      }
3997
    }
3998

    
3999
    // ----- Return
4000
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4001
    return $v_result;
4002
  }
4003
  // --------------------------------------------------------------------------------
4004

    
4005
  // --------------------------------------------------------------------------------
4006
  // Function : privExtractFileInOutput()
4007
  // Description :
4008
  // Parameters :
4009
  // Return Values :
4010
  // --------------------------------------------------------------------------------
4011
  function privExtractFileInOutput(&$p_entry, &$p_options)
4012
  {
4013
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileInOutput', "");
4014
    $v_result=1;
4015

    
4016
    // ----- Read the file header
4017
    if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
4018
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4019
      return $v_result;
4020
    }
4021

    
4022
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
4023

    
4024
    // ----- Check that the file header is coherent with $p_entry info
4025
    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4026
        // TBC
4027
    }
4028

    
4029
    // ----- Look for pre-extract callback
4030
    if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4031
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
4032

    
4033
      // ----- Generate a local information
4034
      $v_local_header = array();
4035
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4036

    
4037
      // ----- Call the callback
4038
      // Here I do not use call_user_func() because I need to send a reference to the
4039
      // header.
4040
      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4041
      if ($v_result == 0) {
4042
        // ----- Change the file status
4043
        $p_entry['status'] = "skipped";
4044
        $v_result = 1;
4045
      }
4046

    
4047
      // ----- Look for abort result
4048
      if ($v_result == 2) {
4049
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
4050
        // ----- This status is internal and will be changed in 'skipped'
4051
        $p_entry['status'] = "aborted";
4052
      	$v_result = PCLZIP_ERR_USER_ABORTED;
4053
      }
4054

    
4055
      // ----- Update the informations
4056
      // Only some fields can be modified
4057
      $p_entry['filename'] = $v_local_header['filename'];
4058
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
4059
    }
4060

    
4061
    // ----- Trace
4062
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
4063

    
4064
    // ----- Look if extraction should be done
4065
    if ($p_entry['status'] == 'ok') {
4066

    
4067
      // ----- Do the extraction (if not a folder)
4068
      if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4069
        // ----- Look for not compressed file
4070
        if ($p_entry['compressed_size'] == $p_entry['size']) {
4071
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
4072
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
4073

    
4074
          // ----- Read the file in a buffer (one shot)
4075
          $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4076

    
4077
          // ----- Send the file to the output
4078
          echo $v_buffer;
4079
          unset($v_buffer);
4080
        }
4081
        else {
4082
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
4083
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Reading '".$p_entry['size']."' bytes");
4084

    
4085
          // ----- Read the compressed file in a buffer (one shot)
4086
          $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4087
          
4088
          // ----- Decompress the file
4089
          $v_file_content = gzinflate($v_buffer);
4090
          unset($v_buffer);
4091

    
4092
          // ----- Send the file to the output
4093
          echo $v_file_content;
4094
          unset($v_file_content);
4095
        }
4096
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
4097
      }
4098
    }
4099

    
4100
	// ----- Change abort status
4101
	if ($p_entry['status'] == "aborted") {
4102
      $p_entry['status'] = "skipped";
4103
	}
4104

    
4105
    // ----- Look for post-extract callback
4106
    elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4107
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
4108

    
4109
      // ----- Generate a local information
4110
      $v_local_header = array();
4111
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4112

    
4113
      // ----- Call the callback
4114
      // Here I do not use call_user_func() because I need to send a reference to the
4115
      // header.
4116
      eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
4117

    
4118
      // ----- Look for abort result
4119
      if ($v_result == 2) {
4120
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
4121
      	$v_result = PCLZIP_ERR_USER_ABORTED;
4122
      }
4123
    }
4124

    
4125
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4126
    return $v_result;
4127
  }
4128
  // --------------------------------------------------------------------------------
4129

    
4130
  // --------------------------------------------------------------------------------
4131
  // Function : privExtractFileAsString()
4132
  // Description :
4133
  // Parameters :
4134
  // Return Values :
4135
  // --------------------------------------------------------------------------------
4136
  function privExtractFileAsString(&$p_entry, &$p_string)
4137
  {
4138
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileAsString', "p_entry['filename']='".$p_entry['filename']."'");
4139
    $v_result=1;
4140

    
4141
    // ----- Read the file header
4142
    $v_header = array();
4143
    if (($v_result = $this->privReadFileHeader($v_header)) != 1)
4144
    {
4145
      // ----- Return
4146
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4147
      return $v_result;
4148
    }
4149

    
4150
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
4151

    
4152
    // ----- Check that the file header is coherent with $p_entry info
4153
    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4154
        // TBC
4155
    }
4156

    
4157
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file in string (with path) '".$p_entry['filename']."', size '$v_header[size]'");
4158

    
4159
    // ----- Do the extraction (if not a folder)
4160
    if (!(($p_entry['external']&0x00000010)==0x00000010))
4161
    {
4162
      // ----- Look for not compressed file
4163
//      if ($p_entry['compressed_size'] == $p_entry['size'])
4164
      if ($p_entry['compression'] == 0) {
4165
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
4166
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
4167

    
4168
        // ----- Reading the file
4169
        $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
4170
      }
4171
      else {
4172
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (compression method '".$p_entry['compression']."')");
4173

    
4174
        // ----- Reading the file
4175
        $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
4176
        
4177
        // ----- Decompress the file
4178
        if (($p_string = @gzinflate($v_data)) === FALSE) {
4179
            // TBC
4180
        }
4181
      }
4182

    
4183
      // ----- Trace
4184
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
4185
    }
4186
    else {
4187
        // TBC : error : can not extract a folder in a string
4188
    }
4189

    
4190
    // ----- Return
4191
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4192
    return $v_result;
4193
  }
4194
  // --------------------------------------------------------------------------------
4195

    
4196
  // --------------------------------------------------------------------------------
4197
  // Function : privReadFileHeader()
4198
  // Description :
4199
  // Parameters :
4200
  // Return Values :
4201
  // --------------------------------------------------------------------------------
4202
  function privReadFileHeader(&$p_header)
4203
  {
4204
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadFileHeader", "");
4205
    $v_result=1;
4206

    
4207
    // ----- Read the 4 bytes signature
4208
    $v_binary_data = @fread($this->zip_fd, 4);
4209
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
4210
    $v_data = unpack('Vid', $v_binary_data);
4211
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
4212

    
4213
    // ----- Check signature
4214
    if ($v_data['id'] != 0x04034b50)
4215
    {
4216
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid File header");
4217

    
4218
      // ----- Error log
4219
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4220

    
4221
      // ----- Return
4222
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4223
      return PclZip::errorCode();
4224
    }
4225

    
4226
    // ----- Read the first 42 bytes of the header
4227
    $v_binary_data = fread($this->zip_fd, 26);
4228

    
4229
    // ----- Look for invalid block size
4230
    if (strlen($v_binary_data) != 26)
4231
    {
4232
      $p_header['filename'] = "";
4233
      $p_header['status'] = "invalid_header";
4234
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
4235

    
4236
      // ----- Error log
4237
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4238

    
4239
      // ----- Return
4240
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4241
      return PclZip::errorCode();
4242
    }
4243

    
4244
    // ----- Extract the values
4245
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'");
4246
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'");
4247
    $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
4248

    
4249
    // ----- Get filename
4250
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$v_data['filename_len']);
4251
    $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
4252
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\'');
4253

    
4254
    // ----- Get extra_fields
4255
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra field length : ".$v_data['extra_len']);
4256
    if ($v_data['extra_len'] != 0) {
4257
      $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
4258
    }
4259
    else {
4260
      $p_header['extra'] = '';
4261
    }
4262
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra field : \''.bin2hex($p_header['extra']).'\'');
4263

    
4264
    // ----- Extract properties
4265
    $p_header['version_extracted'] = $v_data['version'];
4266
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : ('.$p_header['version_extracted'].') \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
4267
    $p_header['compression'] = $v_data['compression'];
4268
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compression method : \''.$p_header['compression'].'\'');
4269
    $p_header['size'] = $v_data['size'];
4270
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\'');
4271
    $p_header['compressed_size'] = $v_data['compressed_size'];
4272
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
4273
    $p_header['crc'] = $v_data['crc'];
4274
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
4275
    $p_header['flag'] = $v_data['flag'];
4276
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\'');
4277
    $p_header['filename_len'] = $v_data['filename_len'];
4278
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename_len : \''.$p_header['filename_len'].'\'');
4279

    
4280
    // ----- Recuperate date in UNIX format
4281
    $p_header['mdate'] = $v_data['mdate'];
4282
    $p_header['mtime'] = $v_data['mtime'];
4283
    if ($p_header['mdate'] && $p_header['mtime'])
4284
    {
4285
      // ----- Extract time
4286
      $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4287
      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4288
      $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4289

    
4290
      // ----- Extract date
4291
      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4292
      $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4293
      $v_day = $p_header['mdate'] & 0x001F;
4294

    
4295
      // ----- Get UNIX date format
4296
      $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4297

    
4298
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
4299
    }
4300
    else
4301
    {
4302
      $p_header['mtime'] = time();
4303
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
4304
    }
4305

    
4306
    // TBC
4307
    //for(reset($v_data); $key = key($v_data); next($v_data)) {
4308
    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Attribut[$key] = ".$v_data[$key]);
4309
    //}
4310

    
4311
    // ----- Set the stored filename
4312
    $p_header['stored_filename'] = $p_header['filename'];
4313

    
4314
    // ----- Set the status field
4315
    $p_header['status'] = "ok";
4316

    
4317
    // ----- Return
4318
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4319
    return $v_result;
4320
  }
4321
  // --------------------------------------------------------------------------------
4322

    
4323
  // --------------------------------------------------------------------------------
4324
  // Function : privReadCentralFileHeader()
4325
  // Description :
4326
  // Parameters :
4327
  // Return Values :
4328
  // --------------------------------------------------------------------------------
4329
  function privReadCentralFileHeader(&$p_header)
4330
  {
4331
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadCentralFileHeader", "");
4332
    $v_result=1;
4333

    
4334
    // ----- Read the 4 bytes signature
4335
    $v_binary_data = @fread($this->zip_fd, 4);
4336
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
4337
    $v_data = unpack('Vid', $v_binary_data);
4338
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
4339

    
4340
    // ----- Check signature
4341
    if ($v_data['id'] != 0x02014b50)
4342
    {
4343
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid Central Dir File signature");
4344

    
4345
      // ----- Error log
4346
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4347

    
4348
      // ----- Return
4349
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4350
      return PclZip::errorCode();
4351
    }
4352

    
4353
    // ----- Read the first 42 bytes of the header
4354
    $v_binary_data = fread($this->zip_fd, 42);
4355

    
4356
    // ----- Look for invalid block size
4357
    if (strlen($v_binary_data) != 42)
4358
    {
4359
      $p_header['filename'] = "";
4360
      $p_header['status'] = "invalid_header";
4361
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
4362

    
4363
      // ----- Error log
4364
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4365

    
4366
      // ----- Return
4367
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4368
      return PclZip::errorCode();
4369
    }
4370

    
4371
    // ----- Extract the values
4372
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header : '".$v_binary_data."'");
4373
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header (Hex) : '".bin2hex($v_binary_data)."'");
4374
    $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
4375

    
4376
    // ----- Get filename
4377
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File name length : ".$p_header['filename_len']);
4378
    if ($p_header['filename_len'] != 0)
4379
      $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
4380
    else
4381
      $p_header['filename'] = '';
4382
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Filename : \''.$p_header['filename'].'\'');
4383

    
4384
    // ----- Get extra
4385
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Extra length : ".$p_header['extra_len']);
4386
    if ($p_header['extra_len'] != 0)
4387
      $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
4388
    else
4389
      $p_header['extra'] = '';
4390
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Extra : \''.$p_header['extra'].'\'');
4391

    
4392
    // ----- Get comment
4393
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Comment length : ".$p_header['comment_len']);
4394
    if ($p_header['comment_len'] != 0)
4395
      $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
4396
    else
4397
      $p_header['comment'] = '';
4398
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Comment : \''.$p_header['comment'].'\'');
4399

    
4400
    // ----- Extract properties
4401
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version : \''.($p_header['version']/10).'.'.($p_header['version']%10).'\'');
4402
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
4403
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Size : \''.$p_header['size'].'\'');
4404
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
4405
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
4406
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Flag : \''.$p_header['flag'].'\'');
4407
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Offset : \''.$p_header['offset'].'\'');
4408

    
4409
    // ----- Recuperate date in UNIX format
4410
    //if ($p_header['mdate'] && $p_header['mtime'])
4411
    // TBC : bug : this was ignoring time with 0/0/0
4412
    if (1)
4413
    {
4414
      // ----- Extract time
4415
      $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4416
      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4417
      $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4418

    
4419
      // ----- Extract date
4420
      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4421
      $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4422
      $v_day = $p_header['mdate'] & 0x001F;
4423

    
4424
      // ----- Get UNIX date format
4425
      $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4426

    
4427
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
4428
    }
4429
    else
4430
    {
4431
      $p_header['mtime'] = time();
4432
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
4433
    }
4434

    
4435
    // ----- Set the stored filename
4436
    $p_header['stored_filename'] = $p_header['filename'];
4437

    
4438
    // ----- Set default status to ok
4439
    $p_header['status'] = 'ok';
4440

    
4441
    // ----- Look if it is a directory
4442
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Internal (Hex) : '".sprintf("Ox%04X", $p_header['internal'])."'");
4443
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "External (Hex) : '".sprintf("Ox%04X", $p_header['external'])."' (".(($p_header['external']&0x00000010)==0x00000010?'is a folder':'is a file').')');
4444
    if (substr($p_header['filename'], -1) == '/') {
4445
      //$p_header['external'] = 0x41FF0010;
4446
      $p_header['external'] = 0x00000010;
4447
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Force folder external : \''.sprintf("Ox%04X", $p_header['external']).'\'');
4448
    }
4449

    
4450
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Header of filename : \''.$p_header['filename'].'\'');
4451

    
4452
    // ----- Return
4453
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4454
    return $v_result;
4455
  }
4456
  // --------------------------------------------------------------------------------
4457

    
4458
  // --------------------------------------------------------------------------------
4459
  // Function : privCheckFileHeaders()
4460
  // Description :
4461
  // Parameters :
4462
  // Return Values :
4463
  //   1 on success,
4464
  //   0 on error;
4465
  // --------------------------------------------------------------------------------
4466
  function privCheckFileHeaders(&$p_local_header, &$p_central_header)
4467
  {
4468
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFileHeaders", "");
4469
    $v_result=1;
4470

    
4471
	// ----- Check the static values
4472
	// TBC
4473
	if ($p_local_header['filename'] != $p_central_header['filename']) {
4474
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename" : TBC To Be Completed');
4475
	}
4476
	if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
4477
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "version_extracted" : TBC To Be Completed');
4478
	}
4479
	if ($p_local_header['flag'] != $p_central_header['flag']) {
4480
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "flag" : TBC To Be Completed');
4481
	}
4482
	if ($p_local_header['compression'] != $p_central_header['compression']) {
4483
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "compression" : TBC To Be Completed');
4484
	}
4485
	if ($p_local_header['mtime'] != $p_central_header['mtime']) {
4486
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "mtime" : TBC To Be Completed');
4487
	}
4488
	if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
4489
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename_len" : TBC To Be Completed');
4490
	}
4491

    
4492
	// ----- Look for flag bit 3
4493
	if (($p_local_header['flag'] & 8) == 8) {
4494
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Purpose bit flag bit 3 set !');
4495
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'File size, compression size and crc found in central header');
4496
        $p_local_header['size'] = $p_central_header['size'];
4497
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_local_header['size'].'\'');
4498
        $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
4499
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_local_header['compressed_size'].'\'');
4500
        $p_local_header['crc'] = $p_central_header['crc'];
4501
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_local_header['crc']).'\'');
4502
	}
4503

    
4504
    // ----- Return
4505
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4506
    return $v_result;
4507
  }
4508
  // --------------------------------------------------------------------------------
4509

    
4510
  // --------------------------------------------------------------------------------
4511
  // Function : privReadEndCentralDir()
4512
  // Description :
4513
  // Parameters :
4514
  // Return Values :
4515
  // --------------------------------------------------------------------------------
4516
  function privReadEndCentralDir(&$p_central_dir)
4517
  {
4518
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadEndCentralDir", "");
4519
    $v_result=1;
4520

    
4521
    // ----- Go to the end of the zip file
4522
    $v_size = filesize($this->zipname);
4523
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size of the file :$v_size");
4524
    @fseek($this->zip_fd, $v_size);
4525
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position at end of zip file : \''.ftell($this->zip_fd).'\'');
4526
    if (@ftell($this->zip_fd) != $v_size)
4527
    {
4528
      // ----- Error log
4529
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
4530

    
4531
      // ----- Return
4532
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4533
      return PclZip::errorCode();
4534
    }
4535

    
4536
    // ----- First try : look if this is an archive with no commentaries (most of the time)
4537
    // in this case the end of central dir is at 22 bytes of the file end
4538
    $v_found = 0;
4539
    if ($v_size > 26) {
4540
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Look for central dir with no comment');
4541
      @fseek($this->zip_fd, $v_size-22);
4542
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after min central position : \''.ftell($this->zip_fd).'\'');
4543
      if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
4544
      {
4545
        // ----- Error log
4546
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4547

    
4548
        // ----- Return
4549
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4550
        return PclZip::errorCode();
4551
      }
4552

    
4553
      // ----- Read for bytes
4554
      $v_binary_data = @fread($this->zip_fd, 4);
4555
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
4556
      $v_data = @unpack('Vid', $v_binary_data);
4557
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
4558

    
4559
      // ----- Check signature
4560
      if ($v_data['id'] == 0x06054b50) {
4561
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found central dir at the default position.");
4562
        $v_found = 1;
4563
      }
4564

    
4565
      $v_pos = ftell($this->zip_fd);
4566
    }
4567

    
4568
    // ----- Go back to the maximum possible size of the Central Dir End Record
4569
    if (!$v_found) {
4570
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Start extended search of end central dir');
4571
      $v_maximum_size = 65557; // 0xFFFF + 22;
4572
      if ($v_maximum_size > $v_size)
4573
        $v_maximum_size = $v_size;
4574
      @fseek($this->zip_fd, $v_size-$v_maximum_size);
4575
      if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
4576
      {
4577
        // ----- Error log
4578
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4579

    
4580
        // ----- Return
4581
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4582
        return PclZip::errorCode();
4583
      }
4584
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');
4585

    
4586
      // ----- Read byte per byte in order to find the signature
4587
      $v_pos = ftell($this->zip_fd);
4588
      $v_bytes = 0x00000000;
4589
      while ($v_pos < $v_size)
4590
      {
4591
        // ----- Read a byte
4592
        $v_byte = @fread($this->zip_fd, 1);
4593

    
4594
        // -----  Add the byte
4595
        $v_bytes = ($v_bytes << 8) | Ord($v_byte);
4596

    
4597
        // ----- Compare the bytes
4598
        if ($v_bytes == 0x504b0506)
4599
        {
4600
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Found End Central Dir signature at position : \''.ftell($this->zip_fd).'\'');
4601
          $v_pos++;
4602
          break;
4603
        }
4604

    
4605
        $v_pos++;
4606
      }
4607

    
4608
      // ----- Look if not found end of central dir
4609
      if ($v_pos == $v_size)
4610
      {
4611
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to find End of Central Dir Record signature");
4612

    
4613
        // ----- Error log
4614
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
4615

    
4616
        // ----- Return
4617
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4618
        return PclZip::errorCode();
4619
      }
4620
    }
4621

    
4622
    // ----- Read the first 18 bytes of the header
4623
    $v_binary_data = fread($this->zip_fd, 18);
4624

    
4625
    // ----- Look for invalid block size
4626
    if (strlen($v_binary_data) != 18)
4627
    {
4628
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
4629

    
4630
      // ----- Error log
4631
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
4632

    
4633
      // ----- Return
4634
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4635
      return PclZip::errorCode();
4636
    }
4637

    
4638
    // ----- Extract the values
4639
    ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record : '".$v_binary_data."'");
4640
    ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record (Hex) : '".bin2hex($v_binary_data)."'");
4641
    $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
4642

    
4643
    // ----- Check the global size
4644
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$v_data['comment_size']);
4645
    if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
4646
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The central dir is not at the end of the archive. Some trailing bytes exists after the archive.");
4647

    
4648
	  // ----- Removed in release 2.2 see readme file
4649
	  // The check of the file size is a little too strict.
4650
	  // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
4651
	  // While decrypted, zip has training 0 bytes
4652
	  if (0) {
4653
      // ----- Error log
4654
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
4655
	                       'The central dir is not at the end of the archive.'
4656
						   .' Some trailing bytes exists after the archive.');
4657

    
4658
      // ----- Return
4659
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4660
      return PclZip::errorCode();
4661
	  }
4662
    }
4663

    
4664
    // ----- Get comment
4665
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment size : \''.$v_data['comment_size'].'\'');
4666
    if ($v_data['comment_size'] != 0) {
4667
      $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
4668
    }
4669
    else
4670
      $p_central_dir['comment'] = '';
4671
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_central_dir['comment'].'\'');
4672

    
4673
    $p_central_dir['entries'] = $v_data['entries'];
4674
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries : \''.$p_central_dir['entries'].'\'');
4675
    $p_central_dir['disk_entries'] = $v_data['disk_entries'];
4676
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries for this disk : \''.$p_central_dir['disk_entries'].'\'');
4677
    $p_central_dir['offset'] = $v_data['offset'];
4678
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset of Central Dir : \''.$p_central_dir['offset'].'\'');
4679
    $p_central_dir['size'] = $v_data['size'];
4680
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size of Central Dir : \''.$p_central_dir['size'].'\'');
4681
    $p_central_dir['disk'] = $v_data['disk'];
4682
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Disk number : \''.$p_central_dir['disk'].'\'');
4683
    $p_central_dir['disk_start'] = $v_data['disk_start'];
4684
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Start disk number : \''.$p_central_dir['disk_start'].'\'');
4685

    
4686
    // TBC
4687
    //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
4688
    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "central_dir[$key] = ".$p_central_dir[$key]);
4689
    //}
4690

    
4691
    // ----- Return
4692
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4693
    return $v_result;
4694
  }
4695
  // --------------------------------------------------------------------------------
4696

    
4697
  // --------------------------------------------------------------------------------
4698
  // Function : privDeleteByRule()
4699
  // Description :
4700
  // Parameters :
4701
  // Return Values :
4702
  // --------------------------------------------------------------------------------
4703
  function privDeleteByRule(&$p_result_list, &$p_options)
4704
  {
4705
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDeleteByRule", "");
4706
    $v_result=1;
4707
    $v_list_detail = array();
4708

    
4709
    // ----- Open the zip file
4710
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
4711
    if (($v_result=$this->privOpenFd('rb')) != 1)
4712
    {
4713
      // ----- Return
4714
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4715
      return $v_result;
4716
    }
4717

    
4718
    // ----- Read the central directory informations
4719
    $v_central_dir = array();
4720
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
4721
    {
4722
      $this->privCloseFd();
4723
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4724
      return $v_result;
4725
    }
4726

    
4727
    // ----- Go to beginning of File
4728
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
4729
    @rewind($this->zip_fd);
4730
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
4731

    
4732
    // ----- Scan all the files
4733
    // ----- Start at beginning of Central Dir
4734
    $v_pos_entry = $v_central_dir['offset'];
4735
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
4736
    @rewind($this->zip_fd);
4737
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
4738
    if (@fseek($this->zip_fd, $v_pos_entry))
4739
    {
4740
      // ----- Close the zip file
4741
      $this->privCloseFd();
4742

    
4743
      // ----- Error log
4744
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4745

    
4746
      // ----- Return
4747
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4748
      return PclZip::errorCode();
4749
    }
4750
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
4751

    
4752
    // ----- Read each entry
4753
    $v_header_list = array();
4754
    $j_start = 0;
4755
    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
4756
    {
4757
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry (index '$i')");
4758

    
4759
      // ----- Read the file header
4760
      $v_header_list[$v_nb_extracted] = array();
4761
      if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
4762
      {
4763
        // ----- Close the zip file
4764
        $this->privCloseFd();
4765

    
4766
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4767
        return $v_result;
4768
      }
4769

    
4770
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename (index '$i') : '".$v_header_list[$v_nb_extracted]['stored_filename']."'");
4771

    
4772
      // ----- Store the index
4773
      $v_header_list[$v_nb_extracted]['index'] = $i;
4774

    
4775
      // ----- Look for the specific extract rules
4776
      $v_found = false;
4777

    
4778
      // ----- Look for extract by name rule
4779
      if (   (isset($p_options[PCLZIP_OPT_BY_NAME]))
4780
          && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
4781
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
4782

    
4783
          // ----- Look if the filename is in the list
4784
          for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
4785
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
4786

    
4787
              // ----- Look for a directory
4788
              if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
4789
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
4790

    
4791
                  // ----- Look if the directory is in the filename path
4792
                  if (   (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
4793
                      && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4794
                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
4795
                      $v_found = true;
4796
                  }
4797
                  elseif (   (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
4798
                          && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4799
                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The entry is the searched directory");
4800
                      $v_found = true;
4801
                  }
4802
              }
4803
              // ----- Look for a filename
4804
              elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
4805
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
4806
                  $v_found = true;
4807
              }
4808
          }
4809
      }
4810

    
4811
      // ----- Look for extract by ereg rule
4812
      else if (   (isset($p_options[PCLZIP_OPT_BY_EREG]))
4813
               && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
4814
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
4815

    
4816
          if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4817
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
4818
              $v_found = true;
4819
          }
4820
      }
4821

    
4822
      // ----- Look for extract by preg rule
4823
      else if (   (isset($p_options[PCLZIP_OPT_BY_PREG]))
4824
               && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
4825
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
4826

    
4827
          if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4828
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
4829
              $v_found = true;
4830
          }
4831
      }
4832

    
4833
      // ----- Look for extract by index rule
4834
      else if (   (isset($p_options[PCLZIP_OPT_BY_INDEX]))
4835
               && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
4836
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
4837

    
4838
          // ----- Look if the index is in the list
4839
          for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
4840
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
4841

    
4842
              if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
4843
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
4844
                  $v_found = true;
4845
              }
4846
              if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
4847
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
4848
                  $j_start = $j+1;
4849
              }
4850

    
4851
              if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
4852
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
4853
                  break;
4854
              }
4855
          }
4856
      }
4857
      else {
4858
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "No argument mean remove all file");
4859
      	$v_found = true;
4860
      }
4861

    
4862
      // ----- Look for deletion
4863
      if ($v_found)
4864
      {
4865
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' need to be deleted");
4866
        unset($v_header_list[$v_nb_extracted]);
4867
      }
4868
      else
4869
      {
4870
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' will not be deleted");
4871
        $v_nb_extracted++;
4872
      }
4873
    }
4874

    
4875
    // ----- Look if something need to be deleted
4876
    if ($v_nb_extracted > 0) {
4877

    
4878
        // ----- Creates a temporay file
4879
        $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
4880

    
4881
        // ----- Creates a temporary zip archive
4882
        $v_temp_zip = new PclZip($v_zip_temp_name);
4883

    
4884
        // ----- Open the temporary zip file in write mode
4885
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary write mode");
4886
        if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
4887
            $this->privCloseFd();
4888

    
4889
            // ----- Return
4890
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4891
            return $v_result;
4892
        }
4893

    
4894
        // ----- Look which file need to be kept
4895
        for ($i=0; $i<sizeof($v_header_list); $i++) {
4896
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Keep entry index '$i' : '".$v_header_list[$i]['filename']."'");
4897

    
4898
            // ----- Calculate the position of the header
4899
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset='". $v_header_list[$i]['offset']."'");
4900
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
4901
            @rewind($this->zip_fd);
4902
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
4903
            if (@fseek($this->zip_fd,  $v_header_list[$i]['offset'])) {
4904
                // ----- Close the zip file
4905
                $this->privCloseFd();
4906
                $v_temp_zip->privCloseFd();
4907
                @unlink($v_zip_temp_name);
4908

    
4909
                // ----- Error log
4910
                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4911

    
4912
                // ----- Return
4913
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4914
                return PclZip::errorCode();
4915
            }
4916
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
4917

    
4918
            // ----- Read the file header
4919
            $v_local_header = array();
4920
            if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
4921
                // ----- Close the zip file
4922
                $this->privCloseFd();
4923
                $v_temp_zip->privCloseFd();
4924
                @unlink($v_zip_temp_name);
4925

    
4926
                // ----- Return
4927
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4928
                return $v_result;
4929
            }
4930
            
4931
            // ----- Check that local file header is same as central file header
4932
            if ($this->privCheckFileHeaders($v_local_header,
4933
			                                $v_header_list[$i]) != 1) {
4934
                // TBC
4935
            }
4936
            unset($v_local_header);
4937

    
4938
            // ----- Write the file header
4939
            if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
4940
                // ----- Close the zip file
4941
                $this->privCloseFd();
4942
                $v_temp_zip->privCloseFd();
4943
                @unlink($v_zip_temp_name);
4944

    
4945
                // ----- Return
4946
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4947
                return $v_result;
4948
            }
4949
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset for this file is '".$v_header_list[$i]['offset']."'");
4950

    
4951
            // ----- Read/write the data block
4952
            if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
4953
                // ----- Close the zip file
4954
                $this->privCloseFd();
4955
                $v_temp_zip->privCloseFd();
4956
                @unlink($v_zip_temp_name);
4957

    
4958
                // ----- Return
4959
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4960
                return $v_result;
4961
            }
4962
        }
4963

    
4964
        // ----- Store the offset of the central dir
4965
        $v_offset = @ftell($v_temp_zip->zip_fd);
4966
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "New offset of central dir : $v_offset");
4967

    
4968
        // ----- Re-Create the Central Dir files header
4969
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the new central directory");
4970
        for ($i=0; $i<sizeof($v_header_list); $i++) {
4971
            // ----- Create the file header
4972
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset of file : ".$v_header_list[$i]['offset']);
4973
            if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
4974
                $v_temp_zip->privCloseFd();
4975
                $this->privCloseFd();
4976
                @unlink($v_zip_temp_name);
4977

    
4978
                // ----- Return
4979
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4980
                return $v_result;
4981
            }
4982

    
4983
            // ----- Transform the header to a 'usable' info
4984
            $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
4985
        }
4986

    
4987
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the central directory footer");
4988

    
4989
        // ----- Zip file comment
4990
        $v_comment = '';
4991
        if (isset($p_options[PCLZIP_OPT_COMMENT])) {
4992
          $v_comment = $p_options[PCLZIP_OPT_COMMENT];
4993
        }
4994

    
4995
        // ----- Calculate the size of the central header
4996
        $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
4997

    
4998
        // ----- Create the central dir footer
4999
        if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
5000
            // ----- Reset the file list
5001
            unset($v_header_list);
5002
            $v_temp_zip->privCloseFd();
5003
            $this->privCloseFd();
5004
            @unlink($v_zip_temp_name);
5005

    
5006
            // ----- Return
5007
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5008
            return $v_result;
5009
        }
5010

    
5011
        // ----- Close
5012
        $v_temp_zip->privCloseFd();
5013
        $this->privCloseFd();
5014

    
5015
        // ----- Delete the zip file
5016
        // TBC : I should test the result ...
5017
        @unlink($this->zipname);
5018

    
5019
        // ----- Rename the temporary file
5020
        // TBC : I should test the result ...
5021
        //@rename($v_zip_temp_name, $this->zipname);
5022
        PclZipUtilRename($v_zip_temp_name, $this->zipname);
5023
    
5024
        // ----- Destroy the temporary archive
5025
        unset($v_temp_zip);
5026
    }
5027
    
5028
    // ----- Remove every files : reset the file
5029
    else if ($v_central_dir['entries'] != 0) {
5030
        $this->privCloseFd();
5031

    
5032
        if (($v_result = $this->privOpenFd('wb')) != 1) {
5033
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5034
          return $v_result;
5035
        }
5036

    
5037
        if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
5038
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5039
          return $v_result;
5040
        }
5041

    
5042
        $this->privCloseFd();
5043
    }
5044

    
5045
    // ----- Return
5046
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5047
    return $v_result;
5048
  }
5049
  // --------------------------------------------------------------------------------
5050

    
5051
  // --------------------------------------------------------------------------------
5052
  // Function : privDirCheck()
5053
  // Description :
5054
  //   Check if a directory exists, if not it creates it and all the parents directory
5055
  //   which may be useful.
5056
  // Parameters :
5057
  //   $p_dir : Directory path to check.
5058
  // Return Values :
5059
  //    1 : OK
5060
  //   -1 : Unable to create directory
5061
  // --------------------------------------------------------------------------------
5062
  function privDirCheck($p_dir, $p_is_dir=false)
5063
  {
5064
    $v_result = 1;
5065

    
5066
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDirCheck", "entry='$p_dir', is_dir='".($p_is_dir?"true":"false")."'");
5067

    
5068
    // ----- Remove the final '/'
5069
    if (($p_is_dir) && (substr($p_dir, -1)=='/'))
5070
    {
5071
      $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
5072
    }
5073
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for entry '$p_dir'");
5074

    
5075
    // ----- Check the directory availability
5076
    if ((is_dir($p_dir)) || ($p_dir == ""))
5077
    {
5078
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
5079
      return 1;
5080
    }
5081

    
5082
    // ----- Extract parent directory
5083
    $p_parent_dir = dirname($p_dir);
5084
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
5085

    
5086
    // ----- Just a check
5087
    if ($p_parent_dir != $p_dir)
5088
    {
5089
      // ----- Look for parent directory
5090
      if ($p_parent_dir != "")
5091
      {
5092
        if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
5093
        {
5094
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5095
          return $v_result;
5096
        }
5097
      }
5098
    }
5099

    
5100
    // ----- Create the directory
5101
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
5102
    if (!@mkdir($p_dir, 0777))
5103
    {
5104
      // ----- Error log
5105
      PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
5106

    
5107
      // ----- Return
5108
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5109
      return PclZip::errorCode();
5110
    }
5111

    
5112
    // ----- Return
5113
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
5114
    return $v_result;
5115
  }
5116
  // --------------------------------------------------------------------------------
5117

    
5118
  // --------------------------------------------------------------------------------
5119
  // Function : privMerge()
5120
  // Description :
5121
  //   If $p_archive_to_add does not exist, the function exit with a success result.
5122
  // Parameters :
5123
  // Return Values :
5124
  // --------------------------------------------------------------------------------
5125
  function privMerge(&$p_archive_to_add)
5126
  {
5127
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privMerge", "archive='".$p_archive_to_add->zipname."'");
5128
    $v_result=1;
5129

    
5130
    // ----- Look if the archive_to_add exists
5131
    if (!is_file($p_archive_to_add->zipname))
5132
    {
5133
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to add does not exist. End of merge.");
5134

    
5135
      // ----- Nothing to merge, so merge is a success
5136
      $v_result = 1;
5137

    
5138
      // ----- Return
5139
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5140
      return $v_result;
5141
    }
5142

    
5143
    // ----- Look if the archive exists
5144
    if (!is_file($this->zipname))
5145
    {
5146
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, duplicate the archive_to_add.");
5147

    
5148
      // ----- Do a duplicate
5149
      $v_result = $this->privDuplicate($p_archive_to_add->zipname);
5150

    
5151
      // ----- Return
5152
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5153
      return $v_result;
5154
    }
5155

    
5156
    // ----- Open the zip file
5157
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5158
    if (($v_result=$this->privOpenFd('rb')) != 1)
5159
    {
5160
      // ----- Return
5161
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5162
      return $v_result;
5163
    }
5164

    
5165
    // ----- Read the central directory informations
5166
    $v_central_dir = array();
5167
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
5168
    {
5169
      $this->privCloseFd();
5170
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5171
      return $v_result;
5172
    }
5173

    
5174
    // ----- Go to beginning of File
5175
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
5176
    @rewind($this->zip_fd);
5177
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
5178

    
5179
    // ----- Open the archive_to_add file
5180
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open archive_to_add in binary read mode");
5181
    if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
5182
    {
5183
      $this->privCloseFd();
5184

    
5185
      // ----- Return
5186
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5187
      return $v_result;
5188
    }
5189

    
5190
    // ----- Read the central directory informations
5191
    $v_central_dir_to_add = array();
5192
    if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
5193
    {
5194
      $this->privCloseFd();
5195
      $p_archive_to_add->privCloseFd();
5196

    
5197
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5198
      return $v_result;
5199
    }
5200

    
5201
    // ----- Go to beginning of File
5202
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
5203
    @rewind($p_archive_to_add->zip_fd);
5204
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
5205

    
5206
    // ----- Creates a temporay file
5207
    $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
5208

    
5209
    // ----- Open the temporary file in write mode
5210
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5211
    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
5212
    {
5213
      $this->privCloseFd();
5214
      $p_archive_to_add->privCloseFd();
5215

    
5216
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
5217

    
5218
      // ----- Return
5219
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5220
      return PclZip::errorCode();
5221
    }
5222

    
5223
    // ----- Copy the files from the archive to the temporary file
5224
    // TBC : Here I should better append the file and go back to erase the central dir
5225
    $v_size = $v_central_dir['offset'];
5226
    while ($v_size != 0)
5227
    {
5228
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5229
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5230
      $v_buffer = fread($this->zip_fd, $v_read_size);
5231
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5232
      $v_size -= $v_read_size;
5233
    }
5234

    
5235
    // ----- Copy the files from the archive_to_add into the temporary file
5236
    $v_size = $v_central_dir_to_add['offset'];
5237
    while ($v_size != 0)
5238
    {
5239
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5240
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5241
      $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
5242
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5243
      $v_size -= $v_read_size;
5244
    }
5245

    
5246
    // ----- Store the offset of the central dir
5247
    $v_offset = @ftell($v_zip_temp_fd);
5248
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
5249

    
5250
    // ----- Copy the block of file headers from the old archive
5251
    $v_size = $v_central_dir['size'];
5252
    while ($v_size != 0)
5253
    {
5254
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5255
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5256
      $v_buffer = @fread($this->zip_fd, $v_read_size);
5257
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5258
      $v_size -= $v_read_size;
5259
    }
5260

    
5261
    // ----- Copy the block of file headers from the archive_to_add
5262
    $v_size = $v_central_dir_to_add['size'];
5263
    while ($v_size != 0)
5264
    {
5265
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5266
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5267
      $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
5268
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5269
      $v_size -= $v_read_size;
5270
    }
5271

    
5272
    // ----- Merge the file comments
5273
    $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
5274

    
5275
    // ----- Calculate the size of the (new) central header
5276
    $v_size = @ftell($v_zip_temp_fd)-$v_offset;
5277

    
5278
    // ----- Swap the file descriptor
5279
    // Here is a trick : I swap the temporary fd with the zip fd, in order to use
5280
    // the following methods on the temporary fil and not the real archive fd
5281
    $v_swap = $this->zip_fd;
5282
    $this->zip_fd = $v_zip_temp_fd;
5283
    $v_zip_temp_fd = $v_swap;
5284

    
5285
    // ----- Create the central dir footer
5286
    if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
5287
    {
5288
      $this->privCloseFd();
5289
      $p_archive_to_add->privCloseFd();
5290
      @fclose($v_zip_temp_fd);
5291
      $this->zip_fd = null;
5292

    
5293
      // ----- Reset the file list
5294
      unset($v_header_list);
5295

    
5296
      // ----- Return
5297
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5298
      return $v_result;
5299
    }
5300

    
5301
    // ----- Swap back the file descriptor
5302
    $v_swap = $this->zip_fd;
5303
    $this->zip_fd = $v_zip_temp_fd;
5304
    $v_zip_temp_fd = $v_swap;
5305

    
5306
    // ----- Close
5307
    $this->privCloseFd();
5308
    $p_archive_to_add->privCloseFd();
5309

    
5310
    // ----- Close the temporary file
5311
    @fclose($v_zip_temp_fd);
5312

    
5313
    // ----- Delete the zip file
5314
    // TBC : I should test the result ...
5315
    @unlink($this->zipname);
5316

    
5317
    // ----- Rename the temporary file
5318
    // TBC : I should test the result ...
5319
    //@rename($v_zip_temp_name, $this->zipname);
5320
    PclZipUtilRename($v_zip_temp_name, $this->zipname);
5321

    
5322
    // ----- Return
5323
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5324
    return $v_result;
5325
  }
5326
  // --------------------------------------------------------------------------------
5327

    
5328
  // --------------------------------------------------------------------------------
5329
  // Function : privDuplicate()
5330
  // Description :
5331
  // Parameters :
5332
  // Return Values :
5333
  // --------------------------------------------------------------------------------
5334
  function privDuplicate($p_archive_filename)
5335
  {
5336
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDuplicate", "archive_filename='$p_archive_filename'");
5337
    $v_result=1;
5338

    
5339
    // ----- Look if the $p_archive_filename exists
5340
    if (!is_file($p_archive_filename))
5341
    {
5342
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to duplicate does not exist. End of duplicate.");
5343

    
5344
      // ----- Nothing to duplicate, so duplicate is a success.
5345
      $v_result = 1;
5346

    
5347
      // ----- Return
5348
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5349
      return $v_result;
5350
    }
5351

    
5352
    // ----- Open the zip file
5353
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5354
    if (($v_result=$this->privOpenFd('wb')) != 1)
5355
    {
5356
      // ----- Return
5357
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5358
      return $v_result;
5359
    }
5360

    
5361
    // ----- Open the temporary file in write mode
5362
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
5363
    if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
5364
    {
5365
      $this->privCloseFd();
5366

    
5367
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
5368

    
5369
      // ----- Return
5370
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
5371
      return PclZip::errorCode();
5372
    }
5373

    
5374
    // ----- Copy the files from the archive to the temporary file
5375
    // TBC : Here I should better append the file and go back to erase the central dir
5376
    $v_size = filesize($p_archive_filename);
5377
    while ($v_size != 0)
5378
    {
5379
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5380
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read $v_read_size bytes");
5381
      $v_buffer = fread($v_zip_temp_fd, $v_read_size);
5382
      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
5383
      $v_size -= $v_read_size;
5384
    }
5385

    
5386
    // ----- Close
5387
    $this->privCloseFd();
5388

    
5389
    // ----- Close the temporary file
5390
    @fclose($v_zip_temp_fd);
5391

    
5392
    // ----- Return
5393
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5394
    return $v_result;
5395
  }
5396
  // --------------------------------------------------------------------------------
5397

    
5398
  // --------------------------------------------------------------------------------
5399
  // Function : privErrorLog()
5400
  // Description :
5401
  // Parameters :
5402
  // --------------------------------------------------------------------------------
5403
  function privErrorLog($p_error_code=0, $p_error_string='')
5404
  {
5405
    if (PCLZIP_ERROR_EXTERNAL == 1) {
5406
      PclError($p_error_code, $p_error_string);
5407
    }
5408
    else {
5409
      $this->error_code = $p_error_code;
5410
      $this->error_string = $p_error_string;
5411
    }
5412
  }
5413
  // --------------------------------------------------------------------------------
5414

    
5415
  // --------------------------------------------------------------------------------
5416
  // Function : privErrorReset()
5417
  // Description :
5418
  // Parameters :
5419
  // --------------------------------------------------------------------------------
5420
  function privErrorReset()
5421
  {
5422
    if (PCLZIP_ERROR_EXTERNAL == 1) {
5423
      PclErrorReset();
5424
    }
5425
    else {
5426
      $this->error_code = 0;
5427
      $this->error_string = '';
5428
    }
5429
  }
5430
  // --------------------------------------------------------------------------------
5431

    
5432
  // --------------------------------------------------------------------------------
5433
  // Function : privDecrypt()
5434
  // Description :
5435
  // Parameters :
5436
  // Return Values :
5437
  // --------------------------------------------------------------------------------
5438
  function privDecrypt($p_encryption_header, &$p_buffer, $p_size, $p_crc)
5439
  {
5440
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDecrypt', "size=".$p_size."");
5441
    $v_result=1;
5442
    
5443
    // ----- To Be Modified ;-)
5444
    $v_pwd = "test";
5445
    
5446
    $p_buffer = PclZipUtilZipDecrypt($p_buffer, $p_size, $p_encryption_header,
5447
	                                 $p_crc, $v_pwd);
5448
    
5449
    // ----- Return
5450
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5451
    return $v_result;
5452
  }
5453
  // --------------------------------------------------------------------------------
5454

    
5455
  // --------------------------------------------------------------------------------
5456
  // Function : privDisableMagicQuotes()
5457
  // Description :
5458
  // Parameters :
5459
  // Return Values :
5460
  // --------------------------------------------------------------------------------
5461
  function privDisableMagicQuotes()
5462
  {
5463
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDisableMagicQuotes', "");
5464
    $v_result=1;
5465

    
5466
    // ----- Look if function exists
5467
    if (   (!function_exists("get_magic_quotes_runtime"))
5468
	    || (!function_exists("set_magic_quotes_runtime"))) {
5469
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported");
5470
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5471
      return $v_result;
5472
	}
5473

    
5474
    // ----- Look if already done
5475
    if ($this->magic_quotes_status != -1) {
5476
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote already disabled");
5477
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5478
      return $v_result;
5479
	}
5480

    
5481
	// ----- Get and memorize the magic_quote value
5482
	$this->magic_quotes_status = @get_magic_quotes_runtime();
5483
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Current magic_quotes_runtime status is '".($this->magic_quotes_status==0?'disable':'enable')."'");
5484

    
5485
	// ----- Disable magic_quotes
5486
	if ($this->magic_quotes_status == 1) {
5487
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Disable magic_quotes");
5488
	  @set_magic_quotes_runtime(0);
5489
	}
5490

    
5491
    // ----- Return
5492
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5493
    return $v_result;
5494
  }
5495
  // --------------------------------------------------------------------------------
5496

    
5497
  // --------------------------------------------------------------------------------
5498
  // Function : privSwapBackMagicQuotes()
5499
  // Description :
5500
  // Parameters :
5501
  // Return Values :
5502
  // --------------------------------------------------------------------------------
5503
  function privSwapBackMagicQuotes()
5504
  {
5505
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privSwapBackMagicQuotes', "");
5506
    $v_result=1;
5507

    
5508
    // ----- Look if function exists
5509
    if (   (!function_exists("get_magic_quotes_runtime"))
5510
	    || (!function_exists("set_magic_quotes_runtime"))) {
5511
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported");
5512
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5513
      return $v_result;
5514
	}
5515

    
5516
    // ----- Look if something to do
5517
    if ($this->magic_quotes_status != -1) {
5518
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote not modified");
5519
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5520
      return $v_result;
5521
	}
5522

    
5523
	// ----- Swap back magic_quotes
5524
	if ($this->magic_quotes_status == 1) {
5525
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Enable back magic_quotes");
5526
  	  @set_magic_quotes_runtime($this->magic_quotes_status);
5527
	}
5528

    
5529
    // ----- Return
5530
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5531
    return $v_result;
5532
  }
5533
  // --------------------------------------------------------------------------------
5534

    
5535
  }
5536
  // End of class
5537
  // --------------------------------------------------------------------------------
5538

    
5539
  // --------------------------------------------------------------------------------
5540
  // Function : PclZipUtilPathReduction()
5541
  // Description :
5542
  // Parameters :
5543
  // Return Values :
5544
  // --------------------------------------------------------------------------------
5545
  function PclZipUtilPathReduction($p_dir)
5546
  {
5547
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathReduction", "dir='$p_dir'");
5548
    $v_result = "";
5549

    
5550
    // ----- Look for not empty path
5551
    if ($p_dir != "") {
5552
      // ----- Explode path by directory names
5553
      $v_list = explode("/", $p_dir);
5554

    
5555
      // ----- Study directories from last to first
5556
      $v_skip = 0;
5557
      for ($i=sizeof($v_list)-1; $i>=0; $i--) {
5558
        // ----- Look for current path
5559
        if ($v_list[$i] == ".") {
5560
          // ----- Ignore this directory
5561
          // Should be the first $i=0, but no check is done
5562
        }
5563
        else if ($v_list[$i] == "..") {
5564
		  $v_skip++;
5565
        }
5566
        else if ($v_list[$i] == "") {
5567
		  // ----- First '/' i.e. root slash
5568
		  if ($i == 0) {
5569
            $v_result = "/".$v_result;
5570
		    if ($v_skip > 0) {
5571
		        // ----- It is an invalid path, so the path is not modified
5572
		        // TBC
5573
		        $v_result = $p_dir;
5574
                //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid path is unchanged");
5575
                $v_skip = 0;
5576
		    }
5577
		  }
5578
		  // ----- Last '/' i.e. indicates a directory
5579
		  else if ($i == (sizeof($v_list)-1)) {
5580
            $v_result = $v_list[$i];
5581
		  }
5582
		  // ----- Double '/' inside the path
5583
		  else {
5584
            // ----- Ignore only the double '//' in path,
5585
            // but not the first and last '/'
5586
		  }
5587
        }
5588
        else {
5589
		  // ----- Look for item to skip
5590
		  if ($v_skip > 0) {
5591
		    $v_skip--;
5592
		  }
5593
		  else {
5594
            $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
5595
		  }
5596
        }
5597
      }
5598
      
5599
      // ----- Look for skip
5600
      if ($v_skip > 0) {
5601
        while ($v_skip > 0) {
5602
            $v_result = '../'.$v_result;
5603
            $v_skip--;
5604
        }
5605
      }
5606
    }
5607

    
5608
    // ----- Return
5609
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5610
    return $v_result;
5611
  }
5612
  // --------------------------------------------------------------------------------
5613

    
5614
  // --------------------------------------------------------------------------------
5615
  // Function : PclZipUtilPathInclusion()
5616
  // Description :
5617
  //   This function indicates if the path $p_path is under the $p_dir tree. Or,
5618
  //   said in an other way, if the file or sub-dir $p_path is inside the dir
5619
  //   $p_dir.
5620
  //   The function indicates also if the path is exactly the same as the dir.
5621
  //   This function supports path with duplicated '/' like '//', but does not
5622
  //   support '.' or '..' statements.
5623
  // Parameters :
5624
  // Return Values :
5625
  //   0 if $p_path is not inside directory $p_dir
5626
  //   1 if $p_path is inside directory $p_dir
5627
  //   2 if $p_path is exactly the same as $p_dir
5628
  // --------------------------------------------------------------------------------
5629
  function PclZipUtilPathInclusion($p_dir, $p_path)
5630
  {
5631
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathInclusion", "dir='$p_dir', path='$p_path'");
5632
    $v_result = 1;
5633
    
5634
    // ----- Look for path beginning by ./
5635
    if (   ($p_dir == '.')
5636
        || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
5637
      $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
5638
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_dir '".$p_dir."'");
5639
    }
5640
    if (   ($p_path == '.')
5641
        || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
5642
      $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
5643
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_path '".$p_path."'");
5644
    }
5645

    
5646
    // ----- Explode dir and path by directory separator
5647
    $v_list_dir = explode("/", $p_dir);
5648
    $v_list_dir_size = sizeof($v_list_dir);
5649
    $v_list_path = explode("/", $p_path);
5650
    $v_list_path_size = sizeof($v_list_path);
5651

    
5652
    // ----- Study directories paths
5653
    $i = 0;
5654
    $j = 0;
5655
    while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
5656
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Working on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'");
5657

    
5658
      // ----- Look for empty dir (path reduction)
5659
      if ($v_list_dir[$i] == '') {
5660
        $i++;
5661
        continue;
5662
      }
5663
      if ($v_list_path[$j] == '') {
5664
        $j++;
5665
        continue;
5666
      }
5667

    
5668
      // ----- Compare the items
5669
      if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != ''))  {
5670
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Items ($i,$j) are different");
5671
        $v_result = 0;
5672
      }
5673

    
5674
      // ----- Next items
5675
      $i++;
5676
      $j++;
5677
    }
5678

    
5679
    // ----- Look if everything seems to be the same
5680
    if ($v_result) {
5681
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Look for tie break");
5682
      // ----- Skip all the empty items
5683
      while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
5684
      while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
5685
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Looking on dir($i)='".($i < $v_list_dir_size?$v_list_dir[$i]:'')."' and path($j)='".($j < $v_list_path_size?$v_list_path[$j]:'')."'");
5686

    
5687
      if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
5688
        // ----- There are exactly the same
5689
        $v_result = 2;
5690
      }
5691
      else if ($i < $v_list_dir_size) {
5692
        // ----- The path is shorter than the dir
5693
        $v_result = 0;
5694
      }
5695
    }
5696

    
5697
    // ----- Return
5698
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5699
    return $v_result;
5700
  }
5701
  // --------------------------------------------------------------------------------
5702

    
5703
  // --------------------------------------------------------------------------------
5704
  // Function : PclZipUtilCopyBlock()
5705
  // Description :
5706
  // Parameters :
5707
  //   $p_mode : read/write compression mode
5708
  //             0 : src & dest normal
5709
  //             1 : src gzip, dest normal
5710
  //             2 : src normal, dest gzip
5711
  //             3 : src & dest gzip
5712
  // Return Values :
5713
  // --------------------------------------------------------------------------------
5714
  function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
5715
  {
5716
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilCopyBlock", "size=$p_size, mode=$p_mode");
5717
    $v_result = 1;
5718

    
5719
    if ($p_mode==0)
5720
    {
5721
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset before read :".(@ftell($p_src)));
5722
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset before write :".(@ftell($p_dest)));
5723
      while ($p_size != 0)
5724
      {
5725
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5726
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5727
        $v_buffer = @fread($p_src, $v_read_size);
5728
        @fwrite($p_dest, $v_buffer, $v_read_size);
5729
        $p_size -= $v_read_size;
5730
      }
5731
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset after read :".(@ftell($p_src)));
5732
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset after write :".(@ftell($p_dest)));
5733
    }
5734
    else if ($p_mode==1)
5735
    {
5736
      while ($p_size != 0)
5737
      {
5738
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5739
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5740
        $v_buffer = @gzread($p_src, $v_read_size);
5741
        @fwrite($p_dest, $v_buffer, $v_read_size);
5742
        $p_size -= $v_read_size;
5743
      }
5744
    }
5745
    else if ($p_mode==2)
5746
    {
5747
      while ($p_size != 0)
5748
      {
5749
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5750
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5751
        $v_buffer = @fread($p_src, $v_read_size);
5752
        @gzwrite($p_dest, $v_buffer, $v_read_size);
5753
        $p_size -= $v_read_size;
5754
      }
5755
    }
5756
    else if ($p_mode==3)
5757
    {
5758
      while ($p_size != 0)
5759
      {
5760
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5761
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
5762
        $v_buffer = @gzread($p_src, $v_read_size);
5763
        @gzwrite($p_dest, $v_buffer, $v_read_size);
5764
        $p_size -= $v_read_size;
5765
      }
5766
    }
5767

    
5768
    // ----- Return
5769
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5770
    return $v_result;
5771
  }
5772
  // --------------------------------------------------------------------------------
5773

    
5774
  // --------------------------------------------------------------------------------
5775
  // Function : PclZipUtilRename()
5776
  // Description :
5777
  //   This function tries to do a simple rename() function. If it fails, it
5778
  //   tries to copy the $p_src file in a new $p_dest file and then unlink the
5779
  //   first one.
5780
  // Parameters :
5781
  //   $p_src : Old filename
5782
  //   $p_dest : New filename
5783
  // Return Values :
5784
  //   1 on success, 0 on failure.
5785
  // --------------------------------------------------------------------------------
5786
  function PclZipUtilRename($p_src, $p_dest)
5787
  {
5788
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilRename", "source=$p_src, destination=$p_dest");
5789
    $v_result = 1;
5790

    
5791
    // ----- Try to rename the files
5792
    if (!@rename($p_src, $p_dest)) {
5793
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to rename file, try copy+unlink");
5794

    
5795
      // ----- Try to copy & unlink the src
5796
      if (!@copy($p_src, $p_dest)) {
5797
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to copy file");
5798
        $v_result = 0;
5799
      }
5800
      else if (!@unlink($p_src)) {
5801
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to unlink old filename");
5802
        $v_result = 0;
5803
      }
5804
    }
5805

    
5806
    // ----- Return
5807
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5808
    return $v_result;
5809
  }
5810
  // --------------------------------------------------------------------------------
5811

    
5812
  // --------------------------------------------------------------------------------
5813
  // Function : PclZipUtilOptionText()
5814
  // Description :
5815
  //   Translate option value in text. Mainly for debug purpose.
5816
  // Parameters :
5817
  //   $p_option : the option value.
5818
  // Return Values :
5819
  //   The option text value.
5820
  // --------------------------------------------------------------------------------
5821
  function PclZipUtilOptionText($p_option)
5822
  {
5823
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilOptionText", "option='".$p_option."'");
5824
    
5825
    $v_list = get_defined_constants();
5826
    for (reset($v_list); $v_key = key($v_list); next($v_list)) {
5827
	  $v_prefix = substr($v_key, 0, 10);
5828
	  if ((   ($v_prefix == 'PCLZIP_OPT')
5829
         || ($v_prefix == 'PCLZIP_CB_')
5830
         || ($v_prefix == 'PCLZIP_ATT'))
5831
	      && ($v_list[$v_key] == $p_option)) {
5832
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_key);
5833
          return $v_key;
5834
	    }
5835
    }
5836
    
5837
    $v_result = 'Unknown';
5838

    
5839
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
5840
    return $v_result;
5841
  }
5842
  // --------------------------------------------------------------------------------
5843

    
5844
  // --------------------------------------------------------------------------------
5845
  // Function : PclZipUtilTranslateWinPath()
5846
  // Description :
5847
  //   Translate windows path by replacing '\' by '/' and optionally removing
5848
  //   drive letter.
5849
  // Parameters :
5850
  //   $p_path : path to translate.
5851
  //   $p_remove_disk_letter : true | false
5852
  // Return Values :
5853
  //   The path translated.
5854
  // --------------------------------------------------------------------------------
5855
  function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
5856
  {
5857
    if (stristr(php_uname(), 'windows')) {
5858
      // ----- Look for potential disk letter
5859
      if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
5860
          $p_path = substr($p_path, $v_position+1);
5861
      }
5862
      // ----- Change potential windows directory separator
5863
      if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
5864
          $p_path = strtr($p_path, '\\', '/');
5865
      }
5866
    }
5867
    return $p_path;
5868
  }
5869
  // --------------------------------------------------------------------------------
5870

    
5871

    
5872
?>
(3-3/4)