Project

General

Profile

1
<?php
2
// --------------------------------------------------------------------------------
3
// PhpConcept Library - Zip Module 2.1
4
// --------------------------------------------------------------------------------
5
// License GNU/LGPL - Vincent Blavet - December 2003
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.1.1.1 2005/01/30 10:31:59 rdjurovich Exp $
26
// --------------------------------------------------------------------------------
27

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

    
43
  // ----- Error configuration
44
  // 0 : PclZip Class integrated error handling
45
  // 1 : PclError external library error handling. By enabling this
46
  //     you must ensure that you have included PclError library.
47
  // [2,...] : reserved for futur use
48
  define( 'PCLZIP_ERROR_EXTERNAL', 0 );
49

    
50
  // ----- Optional static temporary directory
51
  //       By default temporary files are generated in the script current
52
  //       path.
53
  //       If defined :
54
  //       - MUST BE terminated by a '/'.
55
  //       - MUST be a valid, already created directory
56
  //       Samples :
57
  // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
58
  // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
59
  define( 'PCLZIP_TEMPORARY_DIR', '' );
60

    
61
// --------------------------------------------------------------------------------
62
// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
63
// --------------------------------------------------------------------------------
64

    
65
  // ----- Global variables
66
  $g_pclzip_version = "2.1";
67

    
68
  // ----- Error codes
69
  //   -1 : Unable to open file in binary write mode
70
  //   -2 : Unable to open file in binary read mode
71
  //   -3 : Invalid parameters
72
  //   -4 : File does not exist
73
  //   -5 : Filename is too long (max. 255)
74
  //   -6 : Not a valid zip file
75
  //   -7 : Invalid extracted file size
76
  //   -8 : Unable to create directory
77
  //   -9 : Invalid archive extension
78
  //  -10 : Invalid archive format
79
  //  -11 : Unable to delete file (unlink)
80
  //  -12 : Unable to rename file (rename)
81
  //  -13 : Invalid header checksum
82
  //  -14 : Invalid archive size
83
  define( 'PCLZIP_ERR_USER_ABORTED', 2 );
84
  define( 'PCLZIP_ERR_NO_ERROR', 0 );
85
  define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
86
  define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
87
  define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
88
  define( 'PCLZIP_ERR_MISSING_FILE', -4 );
89
  define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
90
  define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
91
  define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
92
  define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
93
  define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
94
  define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
95
  define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
96
  define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
97
  define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
98
  define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
99
  define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
100
  define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
101

    
102
  // ----- Options values
103
  define( 'PCLZIP_OPT_PATH', 77001 );
104
  define( 'PCLZIP_OPT_ADD_PATH', 77002 );
105
  define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
106
  define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
107
  define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
108
  define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
109
  define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
110
  define( 'PCLZIP_OPT_BY_NAME', 77008 );
111
  define( 'PCLZIP_OPT_BY_INDEX', 77009 );
112
  define( 'PCLZIP_OPT_BY_EREG', 77010 );
113
  define( 'PCLZIP_OPT_BY_PREG', 77011 );
114
  define( 'PCLZIP_OPT_COMMENT', 77012 );
115
  define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
116
  define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
117
  define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
118

    
119
  // ----- Call backs values
120
  define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
121
  define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
122
  define( 'PCLZIP_CB_PRE_ADD', 78003 );
123
  define( 'PCLZIP_CB_POST_ADD', 78004 );
124
  /* For futur use
125
  define( 'PCLZIP_CB_PRE_LIST', 78005 );
126
  define( 'PCLZIP_CB_POST_LIST', 78006 );
127
  define( 'PCLZIP_CB_PRE_DELETE', 78007 );
128
  define( 'PCLZIP_CB_POST_DELETE', 78008 );
129
  */
130

    
131
  // --------------------------------------------------------------------------------
132
  // Class : PclZip
133
  // Description :
134
  //   PclZip is the class that represent a Zip archive.
135
  //   The public methods allow the manipulation of the archive.
136
  // Attributes :
137
  //   Attributes must not be accessed directly.
138
  // Methods :
139
  //   PclZip() : Object creator
140
  //   create() : Creates the Zip archive
141
  //   listContent() : List the content of the Zip archive
142
  //   extract() : Extract the content of the archive
143
  //   properties() : List the properties of the archive
144
  // --------------------------------------------------------------------------------
145
  class PclZip
146
  {
147
    // ----- Filename of the zip file
148
    var $zipname = '';
149

    
150
    // ----- File descriptor of the zip file
151
    var $zip_fd = 0;
152

    
153
    // ----- Internal error handling
154
    var $error_code = 1;
155
    var $error_string = '';
156

    
157
  // --------------------------------------------------------------------------------
158
  // Function : PclZip()
159
  // Description :
160
  //   Creates a PclZip object and set the name of the associated Zip archive
161
  //   filename.
162
  //   Note that no real action is taken, if the archive does not exist it is not
163
  //   created. Use create() for that.
164
  // --------------------------------------------------------------------------------
165
  function PclZip($p_zipname)
166
  {
167
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::PclZip', "zipname=$p_zipname");
168

    
169
    // ----- Tests the zlib
170
    if (!function_exists('gzopen'))
171
    {
172
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 1, "zlib extension seems to be missing");
173
      die('Abort '.basename(__FILE__).' : Missing zlib extensions');
174
    }
175

    
176
    // ----- Set the attributes
177
    $this->zipname = $p_zipname;
178
    $this->zip_fd = 0;
179

    
180
    // ----- Return
181
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 1);
182
    return;
183
  }
184
  // --------------------------------------------------------------------------------
185

    
186
  // --------------------------------------------------------------------------------
187
  // Function :
188
  //   create($p_filelist, $p_add_dir="", $p_remove_dir="")
189
  //   create($p_filelist, $p_option, $p_option_value, ...)
190
  // Description :
191
  //   This method supports two different synopsis. The first one is historical.
192
  //   This method creates a Zip Archive. The Zip file is created in the
193
  //   filesystem. The files and directories indicated in $p_filelist
194
  //   are added in the archive. See the parameters description for the
195
  //   supported format of $p_filelist.
196
  //   When a directory is in the list, the directory and its content is added
197
  //   in the archive.
198
  //   In this synopsis, the function takes an optional variable list of
199
  //   options. See bellow the supported options.
200
  // Parameters :
201
  //   $p_filelist : An array containing file or directory names, or
202
  //                 a string containing one filename or one directory name, or
203
  //                 a string containing a list of filenames and/or directory
204
  //                 names separated by spaces.
205
  //   $p_add_dir : A path to add before the real path of the archived file,
206
  //                in order to have it memorized in the archive.
207
  //   $p_remove_dir : A path to remove from the real path of the file to archive,
208
  //                   in order to have a shorter path memorized in the archive.
209
  //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
210
  //                   is removed first, before $p_add_dir is added.
211
  // Options :
212
  //   PCLZIP_OPT_ADD_PATH :
213
  //   PCLZIP_OPT_REMOVE_PATH :
214
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
215
  //   PCLZIP_OPT_COMMENT :
216
  //   PCLZIP_CB_PRE_ADD :
217
  //   PCLZIP_CB_POST_ADD :
218
  // Return Values :
219
  //   0 on failure,
220
  //   The list of the added files, with a status of the add action.
221
  //   (see PclZip::listContent() for list entry format)
222
  // --------------------------------------------------------------------------------
223
//  function create($p_filelist, $p_add_dir="", $p_remove_dir="")
224
  function create($p_filelist /*, options */)
225
  {
226
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::create', "filelist='$p_filelist', ...");
227
    $v_result=1;
228

    
229
    // ----- Reset the error handler
230
    $this->privErrorReset();
231

    
232
    // ----- Set default values
233
    $v_options = array();
234
    $v_add_path = "";
235
    $v_remove_path = "";
236
    $v_remove_all_path = false;
237
    $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
238

    
239
    // ----- Look for variable options arguments
240
    $v_size = func_num_args();
241
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
242

    
243
    // ----- Look for arguments
244
    if ($v_size > 1) {
245
      // ----- Get the arguments
246
      $v_arg_list = &func_get_args();
247

    
248
      // ----- Remove form the options list the first argument
249
      array_shift($v_arg_list);
250
      $v_size--;
251

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

    
256
        // ----- Parse the options
257
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
258
                                            array (PCLZIP_OPT_REMOVE_PATH => 'optional',
259
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
260
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
261
                                                   PCLZIP_CB_PRE_ADD => 'optional',
262
                                                   PCLZIP_CB_POST_ADD => 'optional',
263
                                                   PCLZIP_OPT_NO_COMPRESSION => 'optional',
264
                                                   PCLZIP_OPT_COMMENT => 'optional' ));
265
        if ($v_result != 1) {
266
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
267
          return 0;
268
        }
269

    
270
        // ----- Set the arguments
271
        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
272
          $v_add_path = $v_options[PCLZIP_OPT_ADD_PATH];
273
        }
274
        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
275
          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
276
        }
277
        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
278
          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
279
        }
280
      }
281

    
282
      // ----- Look for 2 args
283
      // Here we need to support the first historic synopsis of the
284
      // method.
285
      else {
286
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
287

    
288
        // ----- Get the first argument
289
        $v_add_path = $v_arg_list[0];
290

    
291
        // ----- Look for the optional second argument
292
        if ($v_size == 2) {
293
          $v_remove_path = $v_arg_list[1];
294
        }
295
        else if ($v_size > 2) {
296
          // ----- Error log
297
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
298
		                       "Invalid number / type of arguments");
299

    
300
          // ----- Return
301
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
302
          return 0;
303
        }
304
      }
305
    }
306

    
307
    // ----- Trace
308
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "add_path='$v_add_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_all_path?'true':'false')."'");
309

    
310
    // ----- Look if the $p_filelist is really an array
311
    $p_result_list = array();
312
    if (is_array($p_filelist))
313
    {
314
      // ----- Call the create fct
315
      $v_result = $this->privCreate($p_filelist, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
316
    }
317

    
318
    // ----- Look if the $p_filelist is a string
319
    else if (is_string($p_filelist))
320
    {
321
      // ----- Create a list with the elements from the string
322
      $v_list = explode(PCLZIP_SEPARATOR, $p_filelist);
323

    
324
      // ----- Call the create fct
325
      $v_result = $this->privCreate($v_list, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
326
    }
327

    
328
    // ----- Invalid variable
329
    else
330
    {
331
      // ----- Error log
332
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
333
      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
334
    }
335

    
336
    if ($v_result != 1)
337
    {
338
      // ----- Return
339
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
340
      return 0;
341
    }
342

    
343
    // ----- Return
344
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
345
    return $p_result_list;
346
  }
347
  // --------------------------------------------------------------------------------
348

    
349
  // --------------------------------------------------------------------------------
350
  // Function :
351
  //   add($p_filelist, $p_add_dir="", $p_remove_dir="")
352
  //   add($p_filelist, $p_option, $p_option_value, ...)
353
  // Description :
354
  //   This method supports two synopsis. The first one is historical.
355
  //   This methods add the list of files in an existing archive.
356
  //   If a file with the same name already exists, it is added at the end of the
357
  //   archive, the first one is still present.
358
  //   If the archive does not exist, it is created.
359
  // Parameters :
360
  //   $p_filelist : An array containing file or directory names, or
361
  //                 a string containing one filename or one directory name, or
362
  //                 a string containing a list of filenames and/or directory
363
  //                 names separated by spaces.
364
  //   $p_add_dir : A path to add before the real path of the archived file,
365
  //                in order to have it memorized in the archive.
366
  //   $p_remove_dir : A path to remove from the real path of the file to archive,
367
  //                   in order to have a shorter path memorized in the archive.
368
  //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
369
  //                   is removed first, before $p_add_dir is added.
370
  // Options :
371
  //   PCLZIP_OPT_ADD_PATH :
372
  //   PCLZIP_OPT_REMOVE_PATH :
373
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
374
  //   PCLZIP_OPT_COMMENT :
375
  //   PCLZIP_OPT_ADD_COMMENT :
376
  //   PCLZIP_OPT_PREPEND_COMMENT :
377
  //   PCLZIP_CB_PRE_ADD :
378
  //   PCLZIP_CB_POST_ADD :
379
  // Return Values :
380
  //   0 on failure,
381
  //   The list of the added files, with a status of the add action.
382
  //   (see PclZip::listContent() for list entry format)
383
  // --------------------------------------------------------------------------------
384
//  function add($p_filelist, $p_add_dir="", $p_remove_dir="")
385
  function add($p_filelist /* options */)
386
  {
387
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::add', "filelist='$p_filelist', ...");
388
    $v_result=1;
389

    
390
    // ----- Reset the error handler
391
    $this->privErrorReset();
392

    
393
    // ----- Set default values
394
    $v_options = array();
395
    $v_add_path = "";
396
    $v_remove_path = "";
397
    $v_remove_all_path = false;
398
    $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
399

    
400
    // ----- Look for variable options arguments
401
    $v_size = func_num_args();
402
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
403

    
404
    // ----- Look for arguments
405
    if ($v_size > 1) {
406
      // ----- Get the arguments
407
      $v_arg_list = &func_get_args();
408

    
409
      // ----- Remove form the options list the first argument
410
      array_shift($v_arg_list);
411
      $v_size--;
412

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

    
417
        // ----- Parse the options
418
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
419
                                            array (PCLZIP_OPT_REMOVE_PATH => 'optional',
420
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
421
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
422
                                                   PCLZIP_CB_PRE_ADD => 'optional',
423
                                                   PCLZIP_CB_POST_ADD => 'optional',
424
                                                   PCLZIP_OPT_NO_COMPRESSION => 'optional',
425
                                                   PCLZIP_OPT_COMMENT => 'optional',
426
                                                   PCLZIP_OPT_ADD_COMMENT => 'optional',
427
                                                   PCLZIP_OPT_PREPEND_COMMENT => 'optional' ));
428
        if ($v_result != 1) {
429
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
430
          return 0;
431
        }
432

    
433
        // ----- Set the arguments
434
        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
435
          $v_add_path = $v_options[PCLZIP_OPT_ADD_PATH];
436
        }
437
        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
438
          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
439
        }
440
        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
441
          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
442
        }
443
      }
444

    
445
      // ----- Look for 2 args
446
      // Here we need to support the first historic synopsis of the
447
      // method.
448
      else {
449
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
450

    
451
        // ----- Get the first argument
452
        $v_add_path = $v_arg_list[0];
453

    
454
        // ----- Look for the optional second argument
455
        if ($v_size == 2) {
456
          $v_remove_path = $v_arg_list[1];
457
        }
458
        else if ($v_size > 2) {
459
          // ----- Error log
460
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
461

    
462
          // ----- Return
463
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
464
          return 0;
465
        }
466
      }
467
    }
468

    
469
    // ----- Trace
470
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "add_path='$v_add_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_all_path?'true':'false')."'");
471

    
472
    // ----- Look if the $p_filelist is really an array
473
    $p_result_list = array();
474
    if (is_array($p_filelist))
475
    {
476
      // ----- Call the create fct
477
      $v_result = $this->privAdd($p_filelist, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
478
    }
479

    
480
    // ----- Look if the $p_filelist is a string
481
    else if (is_string($p_filelist))
482
    {
483
      // ----- Create a list with the elements from the string
484
      $v_list = explode(PCLZIP_SEPARATOR, $p_filelist);
485

    
486
      // ----- Call the create fct
487
      $v_result = $this->privAdd($v_list, $p_result_list, $v_add_path, $v_remove_path, $v_remove_all_path, $v_options);
488
    }
489

    
490
    // ----- Invalid variable
491
    else
492
    {
493
      // ----- Error log
494
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
495
      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
496
    }
497

    
498
    if ($v_result != 1)
499
    {
500
      // ----- Return
501
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
502
      return 0;
503
    }
504

    
505
    // ----- Return
506
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
507
    return $p_result_list;
508
  }
509
  // --------------------------------------------------------------------------------
510

    
511
  // --------------------------------------------------------------------------------
512
  // Function : listContent()
513
  // Description :
514
  //   This public method, gives the list of the files and directories, with their
515
  //   properties.
516
  //   The properties of each entries in the list are (used also in other functions) :
517
  //     filename : Name of the file. For a create or add action it is the filename
518
  //                given by the user. For an extract function it is the filename
519
  //                of the extracted file.
520
  //     stored_filename : Name of the file / directory stored in the archive.
521
  //     size : Size of the stored file.
522
  //     compressed_size : Size of the file's data compressed in the archive
523
  //                       (without the headers overhead)
524
  //     mtime : Last known modification date of the file (UNIX timestamp)
525
  //     comment : Comment associated with the file
526
  //     folder : true | false
527
  //     index : index of the file in the archive
528
  //     status : status of the action (depending of the action) :
529
  //              Values are :
530
  //                ok : OK !
531
  //                filtered : the file / dir is not extracted (filtered by user)
532
  //                already_a_directory : the file can not be extracted because a
533
  //                                      directory with the same name already exists
534
  //                write_protected : the file can not be extracted because a file
535
  //                                  with the same name already exists and is
536
  //                                  write protected
537
  //                newer_exist : the file was not extracted because a newer file exists
538
  //                path_creation_fail : the file is not extracted because the folder
539
  //                                     does not exists and can not be created
540
  //                write_error : the file was not extracted because there was a
541
  //                              error while writing the file
542
  //                read_error : the file was not extracted because there was a error
543
  //                             while reading the file
544
  //                invalid_header : the file was not extracted because of an archive
545
  //                                 format error (bad file header)
546
  //   Note that each time a method can continue operating when there
547
  //   is an action error on a file, the error is only logged in the file status.
548
  // Return Values :
549
  //   0 on an unrecoverable failure,
550
  //   The list of the files in the archive.
551
  // --------------------------------------------------------------------------------
552
  function listContent()
553
  {
554
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::listContent', "");
555
    $v_result=1;
556

    
557
    // ----- Reset the error handler
558
    $this->privErrorReset();
559

    
560
    // ----- Check archive
561
    if (!$this->privCheckFormat()) {
562
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
563
      return(0);
564
    }
565

    
566
    // ----- Call the extracting fct
567
    $p_list = array();
568
    if (($v_result = $this->privList($p_list)) != 1)
569
    {
570
      unset($p_list);
571
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
572
      return(0);
573
    }
574

    
575
    // ----- Return
576
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
577
    return $p_list;
578
  }
579
  // --------------------------------------------------------------------------------
580

    
581
  // --------------------------------------------------------------------------------
582
  // Function :
583
  //   extract($p_path="./", $p_remove_path="")
584
  //   extract([$p_option, $p_option_value, ...])
585
  // Description :
586
  //   This method supports two synopsis. The first one is historical.
587
  //   This method extract all the files / directories from the archive to the
588
  //   folder indicated in $p_path.
589
  //   If you want to ignore the 'root' part of path of the memorized files
590
  //   you can indicate this in the optional $p_remove_path parameter.
591
  //   By default, if a newer file with the same name already exists, the
592
  //   file is not extracted.
593
  //
594
  //   If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
595
  //   are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
596
  //   at the end of the path value of PCLZIP_OPT_PATH.
597
  // Parameters :
598
  //   $p_path : Path where the files and directories are to be extracted
599
  //   $p_remove_path : First part ('root' part) of the memorized path
600
  //                    (if any similar) to remove while extracting.
601
  // Options :
602
  //   PCLZIP_OPT_PATH :
603
  //   PCLZIP_OPT_ADD_PATH :
604
  //   PCLZIP_OPT_REMOVE_PATH :
605
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
606
  //   PCLZIP_CB_PRE_EXTRACT :
607
  //   PCLZIP_CB_POST_EXTRACT :
608
  // Return Values :
609
  //   0 or a negative value on failure,
610
  //   The list of the extracted files, with a status of the action.
611
  //   (see PclZip::listContent() for list entry format)
612
  // --------------------------------------------------------------------------------
613
  //function extract($p_path="./", $p_remove_path="")
614
  function extract(/* options */)
615
  {
616
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extract", "");
617
    $v_result=1;
618

    
619
    // ----- Reset the error handler
620
    $this->privErrorReset();
621

    
622
    // ----- Check archive
623
    if (!$this->privCheckFormat()) {
624
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
625
      return(0);
626
    }
627

    
628
    // ----- Set default values
629
    $v_options = array();
630
    $v_path = "./";
631
    $v_remove_path = "";
632
    $v_remove_all_path = false;
633

    
634
    // ----- Look for variable options arguments
635
    $v_size = func_num_args();
636
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
637

    
638
    // ----- Default values for option
639
    $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
640

    
641
    // ----- Look for arguments
642
    if ($v_size > 0) {
643
      // ----- Get the arguments
644
      $v_arg_list = &func_get_args();
645

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

    
650
        // ----- Parse the options
651
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
652
                                            array (PCLZIP_OPT_PATH => 'optional',
653
                                                   PCLZIP_OPT_REMOVE_PATH => 'optional',
654
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
655
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
656
                                                   PCLZIP_CB_PRE_EXTRACT => 'optional',
657
                                                   PCLZIP_CB_POST_EXTRACT => 'optional',
658
                                                   PCLZIP_OPT_SET_CHMOD => 'optional',
659
                                                   PCLZIP_OPT_BY_NAME => 'optional',
660
                                                   PCLZIP_OPT_BY_EREG => 'optional',
661
                                                   PCLZIP_OPT_BY_PREG => 'optional',
662
                                                   PCLZIP_OPT_BY_INDEX => 'optional',
663
                                                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
664
                                                   PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional' ));
665
        if ($v_result != 1) {
666
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
667
          return 0;
668
        }
669

    
670
        // ----- Set the arguments
671
        if (isset($v_options[PCLZIP_OPT_PATH])) {
672
          $v_path = $v_options[PCLZIP_OPT_PATH];
673
        }
674
        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
675
          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
676
        }
677
        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
678
          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
679
        }
680
        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
681
          // ----- Check for '/' in last path char
682
          if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
683
            $v_path .= '/';
684
          }
685
          $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
686
        }
687
      }
688

    
689
      // ----- Look for 2 args
690
      // Here we need to support the first historic synopsis of the
691
      // method.
692
      else {
693
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
694

    
695
        // ----- Get the first argument
696
        $v_path = $v_arg_list[0];
697

    
698
        // ----- Look for the optional second argument
699
        if ($v_size == 2) {
700
          $v_remove_path = $v_arg_list[1];
701
        }
702
        else if ($v_size > 2) {
703
          // ----- Error log
704
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
705

    
706
          // ----- Return
707
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
708
          return 0;
709
        }
710
      }
711
    }
712

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

    
716
    // ----- Call the extracting fct
717
    $p_list = array();
718
    $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
719
	                                     $v_remove_all_path, $v_options);
720
    if ($v_result < 1) {
721
      unset($p_list);
722
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
723
      return(0);
724
    }
725

    
726
    // ----- Return
727
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
728
    return $p_list;
729
  }
730
  // --------------------------------------------------------------------------------
731

    
732

    
733
  // --------------------------------------------------------------------------------
734
  // Function :
735
  //   extractByIndex($p_index, $p_path="./", $p_remove_path="")
736
  //   extractByIndex($p_index, [$p_option, $p_option_value, ...])
737
  // Description :
738
  //   This method supports two synopsis. The first one is historical.
739
  //   This method is doing a partial extract of the archive.
740
  //   The extracted files or folders are identified by their index in the
741
  //   archive (from 0 to n).
742
  //   Note that if the index identify a folder, only the folder entry is
743
  //   extracted, not all the files included in the archive.
744
  // Parameters :
745
  //   $p_index : A single index (integer) or a string of indexes of files to
746
  //              extract. The form of the string is "0,4-6,8-12" with only numbers
747
  //              and '-' for range or ',' to separate ranges. No spaces or ';'
748
  //              are allowed.
749
  //   $p_path : Path where the files and directories are to be extracted
750
  //   $p_remove_path : First part ('root' part) of the memorized path
751
  //                    (if any similar) to remove while extracting.
752
  // Options :
753
  //   PCLZIP_OPT_PATH :
754
  //   PCLZIP_OPT_ADD_PATH :
755
  //   PCLZIP_OPT_REMOVE_PATH :
756
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
757
  //   PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
758
  //     not as files.
759
  //     The resulting content is in a new field 'content' in the file
760
  //     structure.
761
  //     This option must be used alone (any other options are ignored).
762
  //   PCLZIP_CB_PRE_EXTRACT :
763
  //   PCLZIP_CB_POST_EXTRACT :
764
  // Return Values :
765
  //   0 on failure,
766
  //   The list of the extracted files, with a status of the action.
767
  //   (see PclZip::listContent() for list entry format)
768
  // --------------------------------------------------------------------------------
769
  function extractByIndex($p_index /* $options */)
770
  {
771
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extractByIndex", "index='$p_index', ...");
772
    $v_result=1;
773

    
774
    // ----- Reset the error handler
775
    $this->privErrorReset();
776

    
777
    // ----- Check archive
778
    if (!$this->privCheckFormat()) {
779
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
780
      return(0);
781
    }
782

    
783
    // ----- Set default values
784
    $v_options = array();
785
    $v_path = "./";
786
    $v_remove_path = "";
787
    $v_remove_all_path = false;
788

    
789
    // ----- Look for variable options arguments
790
    $v_size = func_num_args();
791
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
792

    
793
    // ----- Default values for option
794
    $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
795

    
796
    // ----- Look for arguments
797
    if ($v_size > 1) {
798
      // ----- Get the arguments
799
      $v_arg_list = &func_get_args();
800

    
801
      // ----- Remove form the options list the first argument
802
      array_shift($v_arg_list);
803
      $v_size--;
804

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

    
809
        // ----- Parse the options
810
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
811
                                            array (PCLZIP_OPT_PATH => 'optional',
812
                                                   PCLZIP_OPT_REMOVE_PATH => 'optional',
813
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
814
                                                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
815
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
816
                                                   PCLZIP_CB_PRE_EXTRACT => 'optional',
817
                                                   PCLZIP_CB_POST_EXTRACT => 'optional',
818
                                                   PCLZIP_OPT_SET_CHMOD => 'optional' ));
819
        if ($v_result != 1) {
820
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
821
          return 0;
822
        }
823

    
824
        // ----- Set the arguments
825
        if (isset($v_options[PCLZIP_OPT_PATH])) {
826
          $v_path = $v_options[PCLZIP_OPT_PATH];
827
        }
828
        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
829
          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
830
        }
831
        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
832
          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
833
        }
834
        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
835
          // ----- Check for '/' in last path char
836
          if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
837
            $v_path .= '/';
838
          }
839
          $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
840
        }
841
        if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
842
          $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
843
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING not set.");
844
        }
845
        else {
846
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING set.");
847
        }
848
      }
849

    
850
      // ----- Look for 2 args
851
      // Here we need to support the first historic synopsis of the
852
      // method.
853
      else {
854
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
855

    
856
        // ----- Get the first argument
857
        $v_path = $v_arg_list[0];
858

    
859
        // ----- Look for the optional second argument
860
        if ($v_size == 2) {
861
          $v_remove_path = $v_arg_list[1];
862
        }
863
        else if ($v_size > 2) {
864
          // ----- Error log
865
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
866

    
867
          // ----- Return
868
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
869
          return 0;
870
        }
871
      }
872
    }
873

    
874
    // ----- Trace
875
    //--(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')."'");
876

    
877
    // ----- Trick
878
    // Here I want to reuse extractByRule(), so I need to parse the $p_index
879
    // with privParseOptions()
880
    $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
881
    $v_options_trick = array();
882
    $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
883
                                        array (PCLZIP_OPT_BY_INDEX => 'optional' ));
884
    if ($v_result != 1) {
885
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
886
        return 0;
887
    }
888
    $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
889

    
890
    // ----- Call the extracting fct
891
    if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
892
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
893
        return(0);
894
    }
895

    
896
    // ----- Return
897
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
898
    return $p_list;
899
  }
900
  // --------------------------------------------------------------------------------
901

    
902
  // --------------------------------------------------------------------------------
903
  // Function :
904
  //   delete([$p_option, $p_option_value, ...])
905
  // Description :
906
  // Parameters :
907
  //   None
908
  // Options :
909
  //   PCLZIP_OPT_BY_INDEX :
910
  // Return Values :
911
  //   0 on failure,
912
  //   The list of the files which are still present in the archive.
913
  //   (see PclZip::listContent() for list entry format)
914
  // --------------------------------------------------------------------------------
915
  function delete(/* options */)
916
  {
917
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::delete", "");
918
    $v_result=1;
919

    
920
    // ----- Reset the error handler
921
    $this->privErrorReset();
922

    
923
    // ----- Check archive
924
    if (!$this->privCheckFormat()) {
925
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
926
      return(0);
927
    }
928

    
929
    // ----- Set default values
930
    $v_options = array();
931

    
932
    // ----- Look for variable options arguments
933
    $v_size = func_num_args();
934
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
935

    
936
    // ----- Look for no arguments
937
    if ($v_size <= 0) {
938
        // ----- Error log
939
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing arguments");
940

    
941
        // ----- Return
942
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
943
        return 0;
944
    }
945

    
946
    // ----- Get the arguments
947
    $v_arg_list = &func_get_args();
948

    
949
    // ----- Parse the options
950
    $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
951
                                        array (PCLZIP_OPT_BY_NAME => 'optional',
952
                                               PCLZIP_OPT_BY_EREG => 'optional',
953
                                               PCLZIP_OPT_BY_PREG => 'optional',
954
                                               PCLZIP_OPT_BY_INDEX => 'optional' ));
955
    if ($v_result != 1) {
956
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
957
        return 0;
958
    }
959

    
960
    // ----- Check that at least one rule is set
961
    if (   (!isset($v_options[PCLZIP_OPT_BY_NAME]))
962
        && (!isset($v_options[PCLZIP_OPT_BY_EREG]))
963
        && (!isset($v_options[PCLZIP_OPT_BY_PREG]))
964
        && (!isset($v_options[PCLZIP_OPT_BY_INDEX]))) {
965
        // ----- Error log
966
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "At least one filtering rule must be set");
967

    
968
        // ----- Return
969
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
970
        return 0;
971
    }
972

    
973
    // ----- Call the delete fct
974
    $v_list = array();
975
    if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1)
976
    {
977
      unset($v_list);
978
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
979
      return(0);
980
    }
981

    
982
    // ----- Return
983
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_list);
984
    return $v_list;
985
  }
986
  // --------------------------------------------------------------------------------
987

    
988
  // --------------------------------------------------------------------------------
989
  // Function : deleteByIndex()
990
  // Description :
991
  //   ***** Deprecated *****
992
  //   delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
993
  // --------------------------------------------------------------------------------
994
  function deleteByIndex($p_index)
995
  {
996
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::deleteByIndex", "index='$p_index'");
997
    
998
    $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
999

    
1000
    // ----- Return
1001
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
1002
    return $p_list;
1003
  }
1004
  // --------------------------------------------------------------------------------
1005

    
1006
  // --------------------------------------------------------------------------------
1007
  // Function : properties()
1008
  // Description :
1009
  //   This method gives the properties of the archive.
1010
  //   The properties are :
1011
  //     nb : Number of files in the archive
1012
  //     comment : Comment associated with the archive file
1013
  //     status : not_exist, ok
1014
  // Parameters :
1015
  //   None
1016
  // Return Values :
1017
  //   0 on failure,
1018
  //   An array with the archive properties.
1019
  // --------------------------------------------------------------------------------
1020
  function properties()
1021
  {
1022
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::properties", "");
1023

    
1024
    // ----- Reset the error handler
1025
    $this->privErrorReset();
1026

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

    
1033
    // ----- Default properties
1034
    $v_prop = array();
1035
    $v_prop['comment'] = '';
1036
    $v_prop['nb'] = 0;
1037
    $v_prop['status'] = 'not_exist';
1038

    
1039
    // ----- Look if file exists
1040
    if (@is_file($this->zipname))
1041
    {
1042
      // ----- Open the zip file
1043
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
1044
      if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
1045
      {
1046
        // ----- Error log
1047
        PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
1048

    
1049
        // ----- Return
1050
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), 0);
1051
        return 0;
1052
      }
1053

    
1054
      // ----- Read the central directory informations
1055
      $v_central_dir = array();
1056
      if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
1057
      {
1058
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
1059
        return 0;
1060
      }
1061

    
1062
      // ----- Close the zip file
1063
      $this->privCloseFd();
1064

    
1065
      // ----- Set the user attributes
1066
      $v_prop['comment'] = $v_central_dir['comment'];
1067
      $v_prop['nb'] = $v_central_dir['entries'];
1068
      $v_prop['status'] = 'ok';
1069
    }
1070

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

    
1077
  // --------------------------------------------------------------------------------
1078
  // Function : duplicate()
1079
  // Description :
1080
  //   This method creates an archive by copying the content of an other one. If
1081
  //   the archive already exist, it is replaced by the new one without any warning.
1082
  // Parameters :
1083
  //   $p_archive : The filename of a valid archive, or
1084
  //                a valid PclZip object.
1085
  // Return Values :
1086
  //   1 on success.
1087
  //   0 or a negative value on error (error code).
1088
  // --------------------------------------------------------------------------------
1089
  function duplicate($p_archive)
1090
  {
1091
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::duplicate", "");
1092
    $v_result = 1;
1093

    
1094
    // ----- Reset the error handler
1095
    $this->privErrorReset();
1096

    
1097
    // ----- Look if the $p_archive is a PclZip object
1098
    if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
1099
    {
1100
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is valid PclZip object '".$p_archive->zipname."'");
1101

    
1102
      // ----- Duplicate the archive
1103
      $v_result = $this->privDuplicate($p_archive->zipname);
1104
    }
1105

    
1106
    // ----- Look if the $p_archive is a string (so a filename)
1107
    else if (is_string($p_archive))
1108
    {
1109
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is a filename '$p_archive'");
1110

    
1111
      // ----- Check that $p_archive is a valid zip file
1112
      // TBC : Should also check the archive format
1113
      if (!is_file($p_archive)) {
1114
        // ----- Error log
1115
        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
1116
        $v_result = PCLZIP_ERR_MISSING_FILE;
1117
      }
1118
      else {
1119
        // ----- Duplicate the archive
1120
        $v_result = $this->privDuplicate($p_archive);
1121
      }
1122
    }
1123

    
1124
    // ----- Invalid variable
1125
    else
1126
    {
1127
      // ----- Error log
1128
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1129
      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1130
    }
1131

    
1132
    // ----- Return
1133
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1134
    return $v_result;
1135
  }
1136
  // --------------------------------------------------------------------------------
1137

    
1138
  // --------------------------------------------------------------------------------
1139
  // Function : merge()
1140
  // Description :
1141
  //   This method merge the $p_archive_to_add archive at the end of the current
1142
  //   one ($this).
1143
  //   If the archive ($this) does not exist, the merge becomes a duplicate.
1144
  //   If the $p_archive_to_add archive does not exist, the merge is a success.
1145
  // Parameters :
1146
  //   $p_archive_to_add : It can be directly the filename of a valid zip archive,
1147
  //                       or a PclZip object archive.
1148
  // Return Values :
1149
  //   1 on success,
1150
  //   0 or negative values on error (see below).
1151
  // --------------------------------------------------------------------------------
1152
  function merge($p_archive_to_add)
1153
  {
1154
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::merge", "");
1155
    $v_result = 1;
1156

    
1157
    // ----- Reset the error handler
1158
    $this->privErrorReset();
1159

    
1160
    // ----- Check archive
1161
    if (!$this->privCheckFormat()) {
1162
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
1163
      return(0);
1164
    }
1165

    
1166
    // ----- Look if the $p_archive_to_add is a PclZip object
1167
    if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
1168
    {
1169
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is valid PclZip object");
1170

    
1171
      // ----- Merge the archive
1172
      $v_result = $this->privMerge($p_archive_to_add);
1173
    }
1174

    
1175
    // ----- Look if the $p_archive_to_add is a string (so a filename)
1176
    else if (is_string($p_archive_to_add))
1177
    {
1178
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is a filename");
1179

    
1180
      // ----- Create a temporary archive
1181
      $v_object_archive = new PclZip($p_archive_to_add);
1182

    
1183
      // ----- Merge the archive
1184
      $v_result = $this->privMerge($v_object_archive);
1185
    }
1186

    
1187
    // ----- Invalid variable
1188
    else
1189
    {
1190
      // ----- Error log
1191
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1192
      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1193
    }
1194

    
1195
    // ----- Return
1196
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1197
    return $v_result;
1198
  }
1199
  // --------------------------------------------------------------------------------
1200

    
1201

    
1202

    
1203
  // --------------------------------------------------------------------------------
1204
  // Function : errorCode()
1205
  // Description :
1206
  // Parameters :
1207
  // --------------------------------------------------------------------------------
1208
  function errorCode()
1209
  {
1210
    if (PCLZIP_ERROR_EXTERNAL == 1) {
1211
      return(PclErrorCode());
1212
    }
1213
    else {
1214
      return($this->error_code);
1215
    }
1216
  }
1217
  // --------------------------------------------------------------------------------
1218

    
1219
  // --------------------------------------------------------------------------------
1220
  // Function : errorName()
1221
  // Description :
1222
  // Parameters :
1223
  // --------------------------------------------------------------------------------
1224
  function errorName($p_with_code=false)
1225
  {
1226
    $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
1227
                      PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
1228
                      PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
1229
                      PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
1230
                      PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
1231
                      PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
1232
                      PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
1233
                      PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
1234
                      PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
1235
                      PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
1236
                      PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
1237
                      PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
1238
                      PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
1239
                      PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
1240
                      PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1241
                      PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
1242
                      PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE' );
1243

    
1244
    if (isset($v_name[$this->error_code])) {
1245
      $v_value = $v_name[$this->error_code];
1246
    }
1247
    else {
1248
      $v_value = 'NoName';
1249
    }
1250

    
1251
    if ($p_with_code) {
1252
      return($v_value.' ('.$this->error_code.')');
1253
    }
1254
    else {
1255
      return($v_value);
1256
    }
1257
  }
1258
  // --------------------------------------------------------------------------------
1259

    
1260
  // --------------------------------------------------------------------------------
1261
  // Function : errorInfo()
1262
  // Description :
1263
  // Parameters :
1264
  // --------------------------------------------------------------------------------
1265
  function errorInfo($p_full=false)
1266
  {
1267
    if (PCLZIP_ERROR_EXTERNAL == 1) {
1268
      return(PclErrorString());
1269
    }
1270
    else {
1271
      if ($p_full) {
1272
        return($this->errorName(true)." : ".$this->error_string);
1273
      }
1274
      else {
1275
        return($this->error_string." [code ".$this->error_code."]");
1276
      }
1277
    }
1278
  }
1279
  // --------------------------------------------------------------------------------
1280

    
1281

    
1282
// --------------------------------------------------------------------------------
1283
// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1284
// *****                                                        *****
1285
// *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       *****
1286
// --------------------------------------------------------------------------------
1287

    
1288

    
1289

    
1290
  // --------------------------------------------------------------------------------
1291
  // Function : privCheckFormat()
1292
  // Description :
1293
  //   This method check that the archive exists and is a valid zip archive.
1294
  //   Several level of check exists. (futur)
1295
  // Parameters :
1296
  //   $p_level : Level of check. Default 0.
1297
  //              0 : Check the first bytes (magic codes) (default value))
1298
  //              1 : 0 + Check the central directory (futur)
1299
  //              2 : 1 + Check each file header (futur)
1300
  // Return Values :
1301
  //   true on success,
1302
  //   false on error, the error code is set.
1303
  // --------------------------------------------------------------------------------
1304
  function privCheckFormat($p_level=0)
1305
  {
1306
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFormat", "");
1307
    $v_result = true;
1308

    
1309
	// ----- Reset the file system cache
1310
    clearstatcache();
1311

    
1312
    // ----- Reset the error handler
1313
    $this->privErrorReset();
1314

    
1315
    // ----- Look if the file exits
1316
    if (!is_file($this->zipname)) {
1317
      // ----- Error log
1318
      PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
1319
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
1320
      return(false);
1321
    }
1322

    
1323
    // ----- Check that the file is readeable
1324
    if (!is_readable($this->zipname)) {
1325
      // ----- Error log
1326
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
1327
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
1328
      return(false);
1329
    }
1330

    
1331
    // ----- Check the magic code
1332
    // TBC
1333

    
1334
    // ----- Check the central header
1335
    // TBC
1336

    
1337
    // ----- Check each file header
1338
    // TBC
1339

    
1340
    // ----- Return
1341
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1342
    return $v_result;
1343
  }
1344
  // --------------------------------------------------------------------------------
1345

    
1346
  // --------------------------------------------------------------------------------
1347
  // Function : privParseOptions()
1348
  // Description :
1349
  //   This internal methods reads the variable list of arguments ($p_options_list,
1350
  //   $p_size) and generate an array with the options and values ($v_result_list).
1351
  //   $v_requested_options contains the options that can be present and those that
1352
  //   must be present.
1353
  //   $v_requested_options is an array, with the option value as key, and 'optional',
1354
  //   or 'mandatory' as value.
1355
  // Parameters :
1356
  //   See above.
1357
  // Return Values :
1358
  //   1 on success.
1359
  //   0 on failure.
1360
  // --------------------------------------------------------------------------------
1361
  function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
1362
  {
1363
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privParseOptions", "");
1364
    $v_result=1;
1365

    
1366
    // ----- Read the options
1367
    $i=0;
1368
    while ($i<$p_size) {
1369
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Looking for table index $i, option = '".PclZipUtilOptionText($p_options_list[$i])."(".$p_options_list[$i].")'");
1370

    
1371
      // ----- Check if the option is requested
1372
      if (!isset($v_requested_options[$p_options_list[$i]])) {
1373
        // ----- Error log
1374
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1375

    
1376
        // ----- Return
1377
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1378
        return PclZip::errorCode();
1379
      }
1380

    
1381
      // ----- Look for next option
1382
      switch ($p_options_list[$i]) {
1383
        // ----- Look for options that request a path value
1384
        case PCLZIP_OPT_PATH :
1385
        case PCLZIP_OPT_REMOVE_PATH :
1386
        case PCLZIP_OPT_ADD_PATH :
1387
          // ----- Check the number of parameters
1388
          if (($i+1) >= $p_size) {
1389
            // ----- Error log
1390
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1391

    
1392
            // ----- Return
1393
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1394
            return PclZip::errorCode();
1395
          }
1396

    
1397
          // ----- Get the value
1398
          $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], false);
1399
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1400
          $i++;
1401
        break;
1402

    
1403
        // ----- Look for options that request an array of string for value
1404
        case PCLZIP_OPT_BY_NAME :
1405
          // ----- Check the number of parameters
1406
          if (($i+1) >= $p_size) {
1407
            // ----- Error log
1408
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1409

    
1410
            // ----- Return
1411
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1412
            return PclZip::errorCode();
1413
          }
1414

    
1415
          // ----- Get the value
1416
          if (is_string($p_options_list[$i+1])) {
1417
              $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1418
          }
1419
          else if (is_array($p_options_list[$i+1])) {
1420
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1421
          }
1422
          else {
1423
            // ----- Error log
1424
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1425

    
1426
            // ----- Return
1427
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1428
            return PclZip::errorCode();
1429
          }
1430
          ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1431
          $i++;
1432
        break;
1433

    
1434
        // ----- Look for options that request an EREG or PREG expression
1435
        case PCLZIP_OPT_BY_EREG :
1436
        case PCLZIP_OPT_BY_PREG :
1437
          // ----- Check the number of parameters
1438
          if (($i+1) >= $p_size) {
1439
            // ----- Error log
1440
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1441

    
1442
            // ----- Return
1443
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1444
            return PclZip::errorCode();
1445
          }
1446

    
1447
          // ----- Get the value
1448
          if (is_string($p_options_list[$i+1])) {
1449
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1450
          }
1451
          else {
1452
            // ----- Error log
1453
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1454

    
1455
            // ----- Return
1456
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1457
            return PclZip::errorCode();
1458
          }
1459
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1460
          $i++;
1461
        break;
1462

    
1463
        // ----- Look for options that takes a string
1464
        case PCLZIP_OPT_COMMENT :
1465
        case PCLZIP_OPT_ADD_COMMENT :
1466
        case PCLZIP_OPT_PREPEND_COMMENT :
1467
          // ----- Check the number of parameters
1468
          if (($i+1) >= $p_size) {
1469
            // ----- Error log
1470
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
1471
			                     "Missing parameter value for option '"
1472
								 .PclZipUtilOptionText($p_options_list[$i])
1473
								 ."'");
1474

    
1475
            // ----- Return
1476
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1477
            return PclZip::errorCode();
1478
          }
1479

    
1480
          // ----- Get the value
1481
          if (is_string($p_options_list[$i+1])) {
1482
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1483
          }
1484
          else {
1485
            // ----- Error log
1486
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
1487
			                     "Wrong parameter value for option '"
1488
								 .PclZipUtilOptionText($p_options_list[$i])
1489
								 ."'");
1490

    
1491
            // ----- Return
1492
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1493
            return PclZip::errorCode();
1494
          }
1495
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1496
          $i++;
1497
        break;
1498

    
1499
        // ----- Look for options that request an array of index
1500
        case PCLZIP_OPT_BY_INDEX :
1501
          // ----- Check the number of parameters
1502
          if (($i+1) >= $p_size) {
1503
            // ----- Error log
1504
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1505

    
1506
            // ----- Return
1507
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1508
            return PclZip::errorCode();
1509
          }
1510

    
1511
          // ----- Get the value
1512
          $v_work_list = array();
1513
          if (is_string($p_options_list[$i+1])) {
1514
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is a string '".$p_options_list[$i+1]."'");
1515

    
1516
              // ----- Remove spaces
1517
              $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
1518

    
1519
              // ----- Parse items
1520
              $v_work_list = explode(",", $p_options_list[$i+1]);
1521
          }
1522
          else if (is_integer($p_options_list[$i+1])) {
1523
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an integer '".$p_options_list[$i+1]."'");
1524
              $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1525
          }
1526
          else if (is_array($p_options_list[$i+1])) {
1527
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an array");
1528
              $v_work_list = $p_options_list[$i+1];
1529
          }
1530
          else {
1531
            // ----- Error log
1532
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1533

    
1534
            // ----- Return
1535
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1536
            return PclZip::errorCode();
1537
          }
1538
          
1539
          // ----- Reduce the index list
1540
          // each index item in the list must be a couple with a start and
1541
          // an end value : [0,3], [5-5], [8-10], ...
1542
          // ----- Check the format of each item
1543
          $v_sort_flag=false;
1544
          $v_sort_value=0;
1545
          for ($j=0; $j<sizeof($v_work_list); $j++) {
1546
              // ----- Explode the item
1547
              $v_item_list = explode("-", $v_work_list[$j]);
1548
              $v_size_item_list = sizeof($v_item_list);
1549
              
1550
              // ----- TBC : Here we might check that each item is a
1551
              // real integer ...
1552
              
1553
              // ----- Look for single value
1554
              if ($v_size_item_list == 1) {
1555
                  // ----- Set the option value
1556
                  $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1557
                  $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1558
              }
1559
              elseif ($v_size_item_list == 2) {
1560
                  // ----- Set the option value
1561
                  $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1562
                  $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1563
              }
1564
              else {
1565
                  // ----- Error log
1566
                  PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1567

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

    
1573
              //--(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']."]");
1574

    
1575
              // ----- Look for list sort
1576
              if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1577
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The list should be sorted ...");
1578
                  $v_sort_flag=true;
1579

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

    
1584
                  // ----- Return
1585
                  //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1586
                  return PclZip::errorCode();
1587
              }
1588
              $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1589
          }
1590
          
1591
          // ----- Sort the items
1592
          if ($v_sort_flag) {
1593
              // TBC : To Be Completed
1594
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "List sorting is not yet write ...");
1595
          }
1596

    
1597
          // ----- Next option
1598
          $i++;
1599
        break;
1600

    
1601
        // ----- Look for options that request no value
1602
        case PCLZIP_OPT_REMOVE_ALL_PATH :
1603
        case PCLZIP_OPT_EXTRACT_AS_STRING :
1604
        case PCLZIP_OPT_NO_COMPRESSION :
1605
        case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
1606
          $v_result_list[$p_options_list[$i]] = true;
1607
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1608
        break;
1609

    
1610
        // ----- Look for options that request an octal value
1611
        case PCLZIP_OPT_SET_CHMOD :
1612
          // ----- Check the number of parameters
1613
          if (($i+1) >= $p_size) {
1614
            // ----- Error log
1615
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1616

    
1617
            // ----- Return
1618
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1619
            return PclZip::errorCode();
1620
          }
1621

    
1622
          // ----- Get the value
1623
          $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1624
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
1625
          $i++;
1626
        break;
1627

    
1628
        // ----- Look for options that request a call-back
1629
        case PCLZIP_CB_PRE_EXTRACT :
1630
        case PCLZIP_CB_POST_EXTRACT :
1631
        case PCLZIP_CB_PRE_ADD :
1632
        case PCLZIP_CB_POST_ADD :
1633
        /* for futur use
1634
        case PCLZIP_CB_PRE_DELETE :
1635
        case PCLZIP_CB_POST_DELETE :
1636
        case PCLZIP_CB_PRE_LIST :
1637
        case PCLZIP_CB_POST_LIST :
1638
        */
1639
          // ----- Check the number of parameters
1640
          if (($i+1) >= $p_size) {
1641
            // ----- Error log
1642
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1643

    
1644
            // ----- Return
1645
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1646
            return PclZip::errorCode();
1647
          }
1648

    
1649
          // ----- Get the value
1650
          $v_function_name = $p_options_list[$i+1];
1651
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "call-back ".PclZipUtilOptionText($p_options_list[$i])." = '".$v_function_name."'");
1652

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

    
1658
            // ----- Return
1659
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1660
            return PclZip::errorCode();
1661
          }
1662

    
1663
          // ----- Set the attribute
1664
          $v_result_list[$p_options_list[$i]] = $v_function_name;
1665
          $i++;
1666
        break;
1667

    
1668
        default :
1669
          // ----- Error log
1670
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1671
		                       "Unknown parameter '"
1672
							   .$p_options_list[$i]."'");
1673

    
1674
          // ----- Return
1675
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1676
          return PclZip::errorCode();
1677
      }
1678

    
1679
      // ----- Next options
1680
      $i++;
1681
    }
1682

    
1683
    // ----- Look for mandatory options
1684
    if ($v_requested_options !== false) {
1685
      for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1686
        // ----- Look for mandatory option
1687
        if ($v_requested_options[$key] == 'mandatory') {
1688
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
1689
          // ----- Look if present
1690
          if (!isset($v_result_list[$key])) {
1691
            // ----- Error log
1692
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1693

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

    
1702
    // ----- Return
1703
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1704
    return $v_result;
1705
  }
1706
  // --------------------------------------------------------------------------------
1707

    
1708
  // --------------------------------------------------------------------------------
1709
  // Function : privCreate()
1710
  // Description :
1711
  // Parameters :
1712
  // Return Values :
1713
  // --------------------------------------------------------------------------------
1714
  function privCreate($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
1715
  {
1716
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCreate", "list, result_list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1717
    $v_result=1;
1718
    $v_list_detail = array();
1719

    
1720
    // ----- Open the file in write mode
1721
    if (($v_result = $this->privOpenFd('wb')) != 1)
1722
    {
1723
      // ----- Return
1724
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1725
      return $v_result;
1726
    }
1727

    
1728
    // ----- Add the list of files
1729
    $v_result = $this->privAddList($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);
1730

    
1731
    // ----- Close
1732
    $this->privCloseFd();
1733

    
1734
    // ----- Return
1735
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1736
    return $v_result;
1737
  }
1738
  // --------------------------------------------------------------------------------
1739

    
1740
  // --------------------------------------------------------------------------------
1741
  // Function : privAdd()
1742
  // Description :
1743
  // Parameters :
1744
  // Return Values :
1745
  // --------------------------------------------------------------------------------
1746
  function privAdd($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
1747
  {
1748
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAdd", "list, result_list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1749
    $v_result=1;
1750
    $v_list_detail = array();
1751

    
1752
    // ----- Look if the archive exists or is empty
1753
    if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
1754
    {
1755
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, or is empty, create it.");
1756

    
1757
      // ----- Do a create
1758
      $v_result = $this->privCreate($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);
1759

    
1760
      // ----- Return
1761
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1762
      return $v_result;
1763
    }
1764

    
1765
    // ----- Open the zip file
1766
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
1767
    if (($v_result=$this->privOpenFd('rb')) != 1)
1768
    {
1769
      // ----- Return
1770
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1771
      return $v_result;
1772
    }
1773

    
1774
    // ----- Read the central directory informations
1775
    $v_central_dir = array();
1776
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
1777
    {
1778
      $this->privCloseFd();
1779
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1780
      return $v_result;
1781
    }
1782

    
1783
    // ----- Go to beginning of File
1784
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
1785
    @rewind($this->zip_fd);
1786
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
1787

    
1788
    // ----- Creates a temporay file
1789
    $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
1790

    
1791
    // ----- Open the temporary file in write mode
1792
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
1793
    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
1794
    {
1795
      $this->privCloseFd();
1796

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

    
1799
      // ----- Return
1800
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1801
      return PclZip::errorCode();
1802
    }
1803

    
1804
    // ----- Copy the files from the archive to the temporary file
1805
    // TBC : Here I should better append the file and go back to erase the central dir
1806
    $v_size = $v_central_dir['offset'];
1807
    while ($v_size != 0)
1808
    {
1809
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
1810
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
1811
      $v_buffer = fread($this->zip_fd, $v_read_size);
1812
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
1813
      $v_size -= $v_read_size;
1814
    }
1815

    
1816
    // ----- Swap the file descriptor
1817
    // Here is a trick : I swap the temporary fd with the zip fd, in order to use
1818
    // the following methods on the temporary fil and not the real archive
1819
    $v_swap = $this->zip_fd;
1820
    $this->zip_fd = $v_zip_temp_fd;
1821
    $v_zip_temp_fd = $v_swap;
1822

    
1823
    // ----- Add the files
1824
    $v_header_list = array();
1825
    if (($v_result = $this->privAddFileList($p_list, $v_header_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
1826
    {
1827
      fclose($v_zip_temp_fd);
1828
      $this->privCloseFd();
1829
      @unlink($v_zip_temp_name);
1830

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

    
1836
    // ----- Store the offset of the central dir
1837
    $v_offset = @ftell($this->zip_fd);
1838
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
1839

    
1840
    // ----- Copy the block of file headers from the old archive
1841
    $v_size = $v_central_dir['size'];
1842
    while ($v_size != 0)
1843
    {
1844
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
1845
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
1846
      $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
1847
      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
1848
      $v_size -= $v_read_size;
1849
    }
1850

    
1851
    // ----- Create the Central Dir files header
1852
    for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
1853
    {
1854
      // ----- Create the file header
1855
      if ($v_header_list[$i]['status'] == 'ok') {
1856
        if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
1857
          fclose($v_zip_temp_fd);
1858
          $this->privCloseFd();
1859
          @unlink($v_zip_temp_name);
1860

    
1861
          // ----- Return
1862
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1863
          return $v_result;
1864
        }
1865
        $v_count++;
1866
      }
1867

    
1868
      // ----- Transform the header to a 'usable' info
1869
      $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
1870
    }
1871

    
1872
    // ----- Zip file comment
1873
    $v_comment = $v_central_dir['comment'];
1874
    if (isset($p_options[PCLZIP_OPT_COMMENT])) {
1875
      $v_comment = $p_options[PCLZIP_OPT_COMMENT];
1876
    }
1877
    if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
1878
      $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
1879
    }
1880
    if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
1881
      $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
1882
    }
1883

    
1884
    // ----- Calculate the size of the central header
1885
    $v_size = @ftell($this->zip_fd)-$v_offset;
1886

    
1887
    // ----- Create the central dir footer
1888
    if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
1889
    {
1890
      // ----- Reset the file list
1891
      unset($v_header_list);
1892

    
1893
      // ----- Return
1894
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1895
      return $v_result;
1896
    }
1897

    
1898
    // ----- Swap back the file descriptor
1899
    $v_swap = $this->zip_fd;
1900
    $this->zip_fd = $v_zip_temp_fd;
1901
    $v_zip_temp_fd = $v_swap;
1902

    
1903
    // ----- Close
1904
    $this->privCloseFd();
1905

    
1906
    // ----- Close the temporary file
1907
    @fclose($v_zip_temp_fd);
1908

    
1909
    // ----- Delete the zip file
1910
    // TBC : I should test the result ...
1911
    @unlink($this->zipname);
1912

    
1913
    // ----- Rename the temporary file
1914
    // TBC : I should test the result ...
1915
    //@rename($v_zip_temp_name, $this->zipname);
1916
    PclZipUtilRename($v_zip_temp_name, $this->zipname);
1917

    
1918
    // ----- Return
1919
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1920
    return $v_result;
1921
  }
1922
  // --------------------------------------------------------------------------------
1923

    
1924
  // --------------------------------------------------------------------------------
1925
  // Function : privOpenFd()
1926
  // Description :
1927
  // Parameters :
1928
  // --------------------------------------------------------------------------------
1929
  function privOpenFd($p_mode)
1930
  {
1931
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOpenFd", 'mode='.$p_mode);
1932
    $v_result=1;
1933

    
1934
    // ----- Look if already open
1935
    if ($this->zip_fd != 0)
1936
    {
1937
      // ----- Error log
1938
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
1939

    
1940
      // ----- Return
1941
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
1942
      return PclZip::errorCode();
1943
    }
1944

    
1945
    // ----- Open the zip file
1946
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Open file in '.$p_mode.' mode');
1947
    if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
1948
    {
1949
      // ----- Error log
1950
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
1951

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

    
1957
    // ----- Return
1958
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1959
    return $v_result;
1960
  }
1961
  // --------------------------------------------------------------------------------
1962

    
1963
  // --------------------------------------------------------------------------------
1964
  // Function : privCloseFd()
1965
  // Description :
1966
  // Parameters :
1967
  // --------------------------------------------------------------------------------
1968
  function privCloseFd()
1969
  {
1970
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCloseFd", "");
1971
    $v_result=1;
1972

    
1973
    if ($this->zip_fd != 0)
1974
      @fclose($this->zip_fd);
1975
    $this->zip_fd = 0;
1976

    
1977
    // ----- Return
1978
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
1979
    return $v_result;
1980
  }
1981
  // --------------------------------------------------------------------------------
1982

    
1983
  // --------------------------------------------------------------------------------
1984
  // Function : privAddList()
1985
  // Description :
1986
  //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
1987
  //   different from the real path of the file. This is usefull if you want to have PclTar
1988
  //   running in any directory, and memorize relative path from an other directory.
1989
  // Parameters :
1990
  //   $p_list : An array containing the file or directory names to add in the tar
1991
  //   $p_result_list : list of added files with their properties (specially the status field)
1992
  //   $p_add_dir : Path to add in the filename path archived
1993
  //   $p_remove_dir : Path to remove in the filename path archived
1994
  // Return Values :
1995
  // --------------------------------------------------------------------------------
1996
  function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
1997
  {
1998
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddList", "list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1999
    $v_result=1;
2000

    
2001
    // ----- Add the files
2002
    $v_header_list = array();
2003
    if (($v_result = $this->privAddFileList($p_list, $v_header_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
2004
    {
2005
      // ----- Return
2006
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2007
      return $v_result;
2008
    }
2009

    
2010
    // ----- Store the offset of the central dir
2011
    $v_offset = @ftell($this->zip_fd);
2012

    
2013
    // ----- Create the Central Dir files header
2014
    for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
2015
    {
2016
      // ----- Create the file header
2017
      if ($v_header_list[$i]['status'] == 'ok') {
2018
        if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2019
          // ----- Return
2020
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2021
          return $v_result;
2022
        }
2023
        $v_count++;
2024
      }
2025

    
2026
      // ----- Transform the header to a 'usable' info
2027
      $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2028
    }
2029

    
2030
    // ----- Zip file comment
2031
    $v_comment = '';
2032
    if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2033
      $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2034
    }
2035

    
2036
    // ----- Calculate the size of the central header
2037
    $v_size = @ftell($this->zip_fd)-$v_offset;
2038

    
2039
    // ----- Create the central dir footer
2040
    if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
2041
    {
2042
      // ----- Reset the file list
2043
      unset($v_header_list);
2044

    
2045
      // ----- Return
2046
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2047
      return $v_result;
2048
    }
2049

    
2050
    // ----- Return
2051
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2052
    return $v_result;
2053
  }
2054
  // --------------------------------------------------------------------------------
2055

    
2056
  // --------------------------------------------------------------------------------
2057
  // Function : privAddFileList()
2058
  // Description :
2059
  //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2060
  //   different from the real path of the file. This is usefull if you want to
2061
  //   run the lib in any directory, and memorize relative path from an other directory.
2062
  // Parameters :
2063
  //   $p_list : An array containing the file or directory names to add in the tar
2064
  //   $p_result_list : list of added files with their properties (specially the status field)
2065
  //   $p_add_dir : Path to add in the filename path archived
2066
  //   $p_remove_dir : Path to remove in the filename path archived
2067
  // Return Values :
2068
  // --------------------------------------------------------------------------------
2069
  function privAddFileList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2070
  {
2071
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileList", "list, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
2072
    $v_result=1;
2073
    $v_header = array();
2074

    
2075
    // ----- Recuperate the current number of elt in list
2076
    $v_nb = sizeof($p_result_list);
2077
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Before add, list have $v_nb elements");
2078

    
2079
    // ----- Loop on the files
2080
    for ($j=0; ($j<count($p_list)) && ($v_result==1); $j++)
2081
    {
2082
      // ----- Recuperate the filename
2083
      $p_filename = PclZipUtilTranslateWinPath($p_list[$j], false);
2084

    
2085
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for file [$p_filename]");
2086

    
2087
      // ----- Skip empty file names
2088
      if ($p_filename == "")
2089
      {
2090
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Skip empty filename");
2091
        continue;
2092
      }
2093

    
2094
      // ----- Check the filename
2095
      if (!file_exists($p_filename))
2096
      {
2097
        // ----- Error log
2098
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '$p_filename' does not exists");
2099
        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '$p_filename' does not exists");
2100

    
2101
        // ----- Return
2102
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2103
        return PclZip::errorCode();
2104
      }
2105

    
2106
      /* This test is done later
2107
      // ----- Check the path length
2108
      if (strlen($p_filename) > 0xFF)
2109
      {
2110
        // ----- Error log
2111
        PclZip::privErrorLog(-5, "File name is too long (max. 255) : '$p_filename'");
2112

    
2113
        // ----- Return
2114
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2115
        return PclZip::errorCode();
2116
      }
2117
      */
2118

    
2119
      // ----- Look if it is a file or a dir with no all pathnre move
2120
      if ((is_file($p_filename)) || ((is_dir($p_filename)) && !$p_remove_all_dir)) {
2121
        // ----- Add the file
2122
        if (($v_result = $this->privAddFile($p_filename, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
2123
        {
2124
          // ----- Return status
2125
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2126
          return $v_result;
2127
        }
2128

    
2129
        // ----- Store the file infos
2130
        $p_result_list[$v_nb++] = $v_header;
2131
      }
2132

    
2133
      // ----- Look for directory
2134
      if (is_dir($p_filename))
2135
      {
2136
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "$p_filename is a directory");
2137

    
2138
        // ----- Look for path
2139
        if ($p_filename != ".")
2140
          $v_path = $p_filename."/";
2141
        else
2142
          $v_path = "";
2143

    
2144
        // ----- Read the directory for files and sub-directories
2145
        $p_hdir = opendir($p_filename);
2146
        $p_hitem = readdir($p_hdir); // '.' directory
2147
        $p_hitem = readdir($p_hdir); // '..' directory
2148
        while (($p_hitem = readdir($p_hdir)) !== false)
2149
        {
2150
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for $p_hitem in the directory");
2151

    
2152
          // ----- Look for a file
2153
          if (is_file($v_path.$p_hitem))
2154
          {
2155
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Add the file '".$v_path.$p_hitem."'");
2156

    
2157
            // ----- Add the file
2158
            if (($v_result = $this->privAddFile($v_path.$p_hitem, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options)) != 1)
2159
            {
2160
              // ----- Return status
2161
              //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2162
              return $v_result;
2163
            }
2164

    
2165
            // ----- Store the file infos
2166
            $p_result_list[$v_nb++] = $v_header;
2167
          }
2168

    
2169
          // ----- Recursive call to privAddFileList()
2170
          else
2171
          {
2172
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Add the directory '".$v_path.$p_hitem."'");
2173

    
2174
            // ----- Need an array as parameter
2175
            $p_temp_list[0] = $v_path.$p_hitem;
2176
            $v_result = $this->privAddFileList($p_temp_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_options);
2177

    
2178
            // ----- Update the number of elements of the list
2179
            $v_nb = sizeof($p_result_list);
2180
          }
2181
        }
2182

    
2183
        // ----- Free memory for the recursive loop
2184
        unset($p_temp_list);
2185
        unset($p_hdir);
2186
        unset($p_hitem);
2187
      }
2188
    }
2189

    
2190
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "After add, list have $v_nb elements");
2191

    
2192
    // ----- Return
2193
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2194
    return $v_result;
2195
  }
2196
  // --------------------------------------------------------------------------------
2197

    
2198
  // --------------------------------------------------------------------------------
2199
  // Function : privAddFile()
2200
  // Description :
2201
  // Parameters :
2202
  // Return Values :
2203
  // --------------------------------------------------------------------------------
2204
  function privAddFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2205
  {
2206
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFile", "filename='$p_filename', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
2207
    $v_result=1;
2208

    
2209
    if ($p_filename == "")
2210
    {
2211
      // ----- Error log
2212
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
2213

    
2214
      // ----- Return
2215
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2216
      return PclZip::errorCode();
2217
    }
2218

    
2219
    // ----- Calculate the stored filename
2220
    $v_stored_filename = $p_filename;
2221

    
2222
    // ----- Look for all path to remove
2223
    if ($p_remove_all_dir) {
2224
      $v_stored_filename = basename($p_filename);
2225
    }
2226
    // ----- Look for partial path remove
2227
    else if ($p_remove_dir != "")
2228
    {
2229
      if (substr($p_remove_dir, -1) != '/')
2230
        $p_remove_dir .= "/";
2231

    
2232
      if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./"))
2233
      {
2234
        if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./"))
2235
          $p_remove_dir = "./".$p_remove_dir;
2236
        if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./"))
2237
          $p_remove_dir = substr($p_remove_dir, 2);
2238
      }
2239

    
2240
      $v_compare = PclZipUtilPathInclusion($p_remove_dir, $p_filename);
2241
      if ($v_compare > 0)
2242
//      if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
2243
      {
2244

    
2245
        if ($v_compare == 2) {
2246
          $v_stored_filename = "";
2247
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Path to remove is the current folder");
2248
        }
2249
        else {
2250
          $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
2251
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove path '$p_remove_dir' in file '$p_filename' = '$v_stored_filename'");
2252
        }
2253
      }
2254
    }
2255
    // ----- Look for path to add
2256
    if ($p_add_dir != "")
2257
    {
2258
      if (substr($p_add_dir, -1) == "/")
2259
        $v_stored_filename = $p_add_dir.$v_stored_filename;
2260
      else
2261
        $v_stored_filename = $p_add_dir."/".$v_stored_filename;
2262
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
2263
    }
2264

    
2265
    // ----- Filename (reduce the path of stored name)
2266
    $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
2267

    
2268
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Filename (reduced) '$v_stored_filename', strlen ".strlen($v_stored_filename));
2269

    
2270
    /* filename length moved after call-back in release 1.3
2271
    // ----- Check the path length
2272
    if (strlen($v_stored_filename) > 0xFF)
2273
    {
2274
      // ----- Error log
2275
      PclZip::privErrorLog(-5, "Stored file name is too long (max. 255) : '$v_stored_filename'");
2276

    
2277
      // ----- Return
2278
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2279
      return PclZip::errorCode();
2280
    }
2281
    */
2282

    
2283
    // ----- Set the file properties
2284
    clearstatcache();
2285
    $p_header['version'] = 20;
2286
    $p_header['version_extracted'] = 10;
2287
    $p_header['flag'] = 0;
2288
    $p_header['compression'] = 0;
2289
    $p_header['mtime'] = filemtime($p_filename);
2290
    $p_header['crc'] = 0;
2291
    $p_header['compressed_size'] = 0;
2292
    $p_header['size'] = filesize($p_filename);
2293
    $p_header['filename_len'] = strlen($p_filename);
2294
    $p_header['extra_len'] = 0;
2295
    $p_header['comment_len'] = 0;
2296
    $p_header['disk'] = 0;
2297
    $p_header['internal'] = 0;
2298
    $p_header['external'] = (is_file($p_filename)?0xFE49FFE0:0x41FF0010);
2299
    $p_header['offset'] = 0;
2300
    $p_header['filename'] = $p_filename;
2301
    $p_header['stored_filename'] = $v_stored_filename;
2302
    $p_header['extra'] = '';
2303
    $p_header['comment'] = '';
2304
    $p_header['status'] = 'ok';
2305
    $p_header['index'] = -1;
2306

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

    
2311
      // ----- Generate a local information
2312
      $v_local_header = array();
2313
      $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2314

    
2315
      // ----- Call the callback
2316
      // Here I do not use call_user_func() because I need to send a reference to the
2317
      // header.
2318
      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
2319
      if ($v_result == 0) {
2320
        // ----- Change the file status
2321
        $p_header['status'] = "skipped";
2322
        $v_result = 1;
2323
      }
2324

    
2325
      // ----- Update the informations
2326
      // Only some fields can be modified
2327
      if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2328
        $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
2329
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New stored filename is '".$p_header['stored_filename']."'");
2330
      }
2331
    }
2332

    
2333
    // ----- Look for empty stored filename
2334
    if ($p_header['stored_filename'] == "") {
2335
      $p_header['status'] = "filtered";
2336
    }
2337
    
2338
    // ----- Check the path length
2339
    if (strlen($p_header['stored_filename']) > 0xFF) {
2340
      $p_header['status'] = 'filename_too_long';
2341
    }
2342

    
2343
    // ----- Look if no error, or file not skipped
2344
    if ($p_header['status'] == 'ok') {
2345

    
2346
      // ----- Look for a file
2347
      if (is_file($p_filename))
2348
      {
2349
        // ----- Open the source file
2350
        if (($v_file = @fopen($p_filename, "rb")) == 0) {
2351
          PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2352
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2353
          return PclZip::errorCode();
2354
        }
2355

    
2356
        if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2357
          // ----- Read the file content
2358
          $v_content_compressed = @fread($v_file, $p_header['size']);
2359

    
2360
          // ----- Calculate the CRC
2361
          $p_header['crc'] = crc32($v_content_compressed);
2362
        }
2363
        else {
2364
          // ----- Read the file content
2365
          $v_content = @fread($v_file, $p_header['size']);
2366

    
2367
          // ----- Calculate the CRC
2368
          $p_header['crc'] = crc32($v_content);
2369

    
2370
          // ----- Compress the file
2371
          $v_content_compressed = gzdeflate($v_content);
2372
        }
2373

    
2374
        // ----- Set header parameters
2375
        $p_header['compressed_size'] = strlen($v_content_compressed);
2376
        $p_header['compression'] = 8;
2377

    
2378
        // ----- Call the header generation
2379
        if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2380
          @fclose($v_file);
2381
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2382
          return $v_result;
2383
        }
2384

    
2385
        // ----- Write the compressed content
2386
        $v_binary_data = pack('a'.$p_header['compressed_size'], $v_content_compressed);
2387
        @fwrite($this->zip_fd, $v_binary_data, $p_header['compressed_size']);
2388
        
2389
        // ----- Close the file
2390
        @fclose($v_file);
2391
      }
2392

    
2393
      // ----- Look for a directory
2394
      else
2395
      {
2396
        // ----- Set the file properties
2397
        $p_header['filename'] .= '/';
2398
        $p_header['filename_len']++;
2399
        $p_header['size'] = 0;
2400
        $p_header['external'] = 0x41FF0010;   // Value for a folder : to be checked
2401

    
2402
        // ----- Call the header generation
2403
        if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
2404
        {
2405
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2406
          return $v_result;
2407
        }
2408
      }
2409
    }
2410

    
2411
    // ----- Look for pre-add callback
2412
    if (isset($p_options[PCLZIP_CB_POST_ADD])) {
2413
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_ADD]."()') is defined for the extraction");
2414

    
2415
      // ----- Generate a local information
2416
      $v_local_header = array();
2417
      $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2418

    
2419
      // ----- Call the callback
2420
      // Here I do not use call_user_func() because I need to send a reference to the
2421
      // header.
2422
      eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
2423
      if ($v_result == 0) {
2424
        // ----- Ignored
2425
        $v_result = 1;
2426
      }
2427

    
2428
      // ----- Update the informations
2429
      // Nothing can be modified
2430
    }
2431

    
2432
    // ----- Return
2433
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2434
    return $v_result;
2435
  }
2436
  // --------------------------------------------------------------------------------
2437

    
2438
  // --------------------------------------------------------------------------------
2439
  // Function : privWriteFileHeader()
2440
  // Description :
2441
  // Parameters :
2442
  // Return Values :
2443
  // --------------------------------------------------------------------------------
2444
  function privWriteFileHeader(&$p_header)
2445
  {
2446
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
2447
    $v_result=1;
2448

    
2449
    // TBC
2450
    //for(reset($p_header); $key = key($p_header); next($p_header)) {
2451
    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
2452
    //}
2453

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

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

    
2464
    // ----- Packed data
2465
    $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, $p_header['version'], $p_header['flag'],
2466
                          $p_header['compression'], $v_mtime, $v_mdate,
2467
                          $p_header['crc'], $p_header['compressed_size'], $p_header['size'],
2468
                          strlen($p_header['stored_filename']), $p_header['extra_len']);
2469

    
2470
    // ----- Write the first 148 bytes of the header in the archive
2471
    fputs($this->zip_fd, $v_binary_data, 30);
2472

    
2473
    // ----- Write the variable fields
2474
    if (strlen($p_header['stored_filename']) != 0)
2475
    {
2476
      fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
2477
    }
2478
    if ($p_header['extra_len'] != 0)
2479
    {
2480
      fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
2481
    }
2482

    
2483
    // ----- Return
2484
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2485
    return $v_result;
2486
  }
2487
  // --------------------------------------------------------------------------------
2488

    
2489
  // --------------------------------------------------------------------------------
2490
  // Function : privWriteCentralFileHeader()
2491
  // Description :
2492
  // Parameters :
2493
  // Return Values :
2494
  // --------------------------------------------------------------------------------
2495
  function privWriteCentralFileHeader(&$p_header)
2496
  {
2497
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
2498
    $v_result=1;
2499

    
2500
    // TBC
2501
    //for(reset($p_header); $key = key($p_header); next($p_header)) {
2502
    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
2503
    //}
2504

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

    
2511
    // ----- Packed data
2512
    $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, $p_header['version'], $p_header['version_extracted'],
2513
                          $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'],
2514
                          $p_header['compressed_size'], $p_header['size'],
2515
                          strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'],
2516
                          $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']);
2517

    
2518
    // ----- Write the 42 bytes of the header in the zip file
2519
    fputs($this->zip_fd, $v_binary_data, 46);
2520

    
2521
    // ----- Write the variable fields
2522
    if (strlen($p_header['stored_filename']) != 0)
2523
    {
2524
      fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
2525
    }
2526
    if ($p_header['extra_len'] != 0)
2527
    {
2528
      fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
2529
    }
2530
    if ($p_header['comment_len'] != 0)
2531
    {
2532
      fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
2533
    }
2534

    
2535
    // ----- Return
2536
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2537
    return $v_result;
2538
  }
2539
  // --------------------------------------------------------------------------------
2540

    
2541
  // --------------------------------------------------------------------------------
2542
  // Function : privWriteCentralHeader()
2543
  // Description :
2544
  // Parameters :
2545
  // Return Values :
2546
  // --------------------------------------------------------------------------------
2547
  function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
2548
  {
2549
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralHeader", 'nb_entries='.$p_nb_entries.', size='.$p_size.', offset='.$p_offset.', comment="'.$p_comment.'"');
2550
    $v_result=1;
2551

    
2552
    // ----- Packed data
2553
    $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment));
2554

    
2555
    // ----- Write the 22 bytes of the header in the zip file
2556
    fputs($this->zip_fd, $v_binary_data, 22);
2557

    
2558
    // ----- Write the variable fields
2559
    if (strlen($p_comment) != 0)
2560
    {
2561
      fputs($this->zip_fd, $p_comment, strlen($p_comment));
2562
    }
2563

    
2564
    // ----- Return
2565
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2566
    return $v_result;
2567
  }
2568
  // --------------------------------------------------------------------------------
2569

    
2570
  // --------------------------------------------------------------------------------
2571
  // Function : privList()
2572
  // Description :
2573
  // Parameters :
2574
  // Return Values :
2575
  // --------------------------------------------------------------------------------
2576
  function privList(&$p_list)
2577
  {
2578
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privList", "list");
2579
    $v_result=1;
2580

    
2581
    // ----- Open the zip file
2582
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2583
    if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
2584
    {
2585
      // ----- Error log
2586
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
2587

    
2588
      // ----- Return
2589
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2590
      return PclZip::errorCode();
2591
    }
2592

    
2593
    // ----- Read the central directory informations
2594
    $v_central_dir = array();
2595
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
2596
    {
2597
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2598
      return $v_result;
2599
    }
2600

    
2601
    // ----- Go to beginning of Central Dir
2602
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset : ".$v_central_dir['offset']."'");
2603
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
2604
    @rewind($this->zip_fd);
2605
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
2606
    if (@fseek($this->zip_fd, $v_central_dir['offset']))
2607
    {
2608
      // ----- Error log
2609
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
2610

    
2611
      // ----- Return
2612
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2613
      return PclZip::errorCode();
2614
    }
2615
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
2616

    
2617
    // ----- Read each entry
2618
    for ($i=0; $i<$v_central_dir['entries']; $i++)
2619
    {
2620
      // ----- Read the file header
2621
      if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
2622
      {
2623
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2624
        return $v_result;
2625
      }
2626
      $v_header['index'] = $i;
2627

    
2628
      // ----- Get the only interesting attributes
2629
      $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
2630
      unset($v_header);
2631
    }
2632

    
2633
    // ----- Close the zip file
2634
    $this->privCloseFd();
2635

    
2636
    // ----- Return
2637
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2638
    return $v_result;
2639
  }
2640
  // --------------------------------------------------------------------------------
2641

    
2642
  // --------------------------------------------------------------------------------
2643
  // Function : privConvertHeader2FileInfo()
2644
  // Description :
2645
  //   This function takes the file informations from the central directory
2646
  //   entries and extract the interesting parameters that will be given back.
2647
  //   The resulting file infos are set in the array $p_info
2648
  //     $p_info['filename'] : Filename with full path. Given by user (add),
2649
  //                           extracted in the filesystem (extract).
2650
  //     $p_info['stored_filename'] : Stored filename in the archive.
2651
  //     $p_info['size'] = Size of the file.
2652
  //     $p_info['compressed_size'] = Compressed size of the file.
2653
  //     $p_info['mtime'] = Last modification date of the file.
2654
  //     $p_info['comment'] = Comment associated with the file.
2655
  //     $p_info['folder'] = true/false : indicates if the entry is a folder or not.
2656
  //     $p_info['status'] = status of the action on the file.
2657
  // Parameters :
2658
  // Return Values :
2659
  // --------------------------------------------------------------------------------
2660
  function privConvertHeader2FileInfo($p_header, &$p_info)
2661
  {
2662
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privConvertHeader2FileInfo", "Filename='".$p_header['filename']."'");
2663
    $v_result=1;
2664

    
2665
    // ----- Get the interesting attributes
2666
    $p_info['filename'] = $p_header['filename'];
2667
    $p_info['stored_filename'] = $p_header['stored_filename'];
2668
    $p_info['size'] = $p_header['size'];
2669
    $p_info['compressed_size'] = $p_header['compressed_size'];
2670
    $p_info['mtime'] = $p_header['mtime'];
2671
    $p_info['comment'] = $p_header['comment'];
2672
    $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
2673
    $p_info['index'] = $p_header['index'];
2674
    $p_info['status'] = $p_header['status'];
2675

    
2676
    // ----- Return
2677
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2678
    return $v_result;
2679
  }
2680
  // --------------------------------------------------------------------------------
2681

    
2682
  // --------------------------------------------------------------------------------
2683
  // Function : privExtractByRule()
2684
  // Description :
2685
  //   Extract a file or directory depending of rules (by index, by name, ...)
2686
  // Parameters :
2687
  //   $p_file_list : An array where will be placed the properties of each
2688
  //                  extracted file
2689
  //   $p_path : Path to add while writing the extracted files
2690
  //   $p_remove_path : Path to remove (from the file memorized path) while writing the
2691
  //                    extracted files. If the path does not match the file path,
2692
  //                    the file is extracted with its memorized path.
2693
  //                    $p_remove_path does not apply to 'list' mode.
2694
  //                    $p_path and $p_remove_path are commulative.
2695
  // Return Values :
2696
  //   1 on success,0 or less on error (see error code list)
2697
  // --------------------------------------------------------------------------------
2698
  function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
2699
  {
2700
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtractByRule", "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
2701
    $v_result=1;
2702

    
2703
    // ----- Check the path
2704
    if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../") && (substr($p_path,1,2)!=":/")))
2705
      $p_path = "./".$p_path;
2706

    
2707
    // ----- Reduce the path last (and duplicated) '/'
2708
    if (($p_path != "./") && ($p_path != "/"))
2709
    {
2710
      // ----- Look for the path end '/'
2711
      while (substr($p_path, -1) == "/")
2712
      {
2713
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
2714
        $p_path = substr($p_path, 0, strlen($p_path)-1);
2715
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
2716
      }
2717
    }
2718

    
2719
    // ----- Look for path to remove format (should end by /)
2720
    if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
2721
    {
2722
      $p_remove_path .= '/';
2723
    }
2724
    $p_remove_path_size = strlen($p_remove_path);
2725

    
2726
    // ----- Open the zip file
2727
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
2728
    if (($v_result = $this->privOpenFd('rb')) != 1)
2729
    {
2730
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2731
      return $v_result;
2732
    }
2733

    
2734
    // ----- Read the central directory informations
2735
    $v_central_dir = array();
2736
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
2737
    {
2738
      // ----- Close the zip file
2739
      $this->privCloseFd();
2740

    
2741
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2742
      return $v_result;
2743
    }
2744

    
2745
    // ----- Start at beginning of Central Dir
2746
    $v_pos_entry = $v_central_dir['offset'];
2747

    
2748
    // ----- Read each entry
2749
    $j_start = 0;
2750
    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
2751
    {
2752
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : '$i'");
2753

    
2754
      // ----- Read next Central dir entry
2755
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position before rewind : ".ftell($this->zip_fd)."'");
2756
      @rewind($this->zip_fd);
2757
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position after rewind : ".ftell($this->zip_fd)."'");
2758
      if (@fseek($this->zip_fd, $v_pos_entry))
2759
      {
2760
        // ----- Close the zip file
2761
        $this->privCloseFd();
2762

    
2763
        // ----- Error log
2764
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
2765

    
2766
        // ----- Return
2767
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2768
        return PclZip::errorCode();
2769
      }
2770
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");
2771

    
2772
      // ----- Read the file header
2773
      $v_header = array();
2774
      if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
2775
      {
2776
        // ----- Close the zip file
2777
        $this->privCloseFd();
2778

    
2779
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2780
        return $v_result;
2781
      }
2782

    
2783
      // ----- Store the index
2784
      $v_header['index'] = $i;
2785

    
2786
      // ----- Store the file position
2787
      $v_pos_entry = ftell($this->zip_fd);
2788

    
2789
      // ----- Look for the specific extract rules
2790
      $v_extract = false;
2791

    
2792
      // ----- Look for extract by name rule
2793
      if (   (isset($p_options[PCLZIP_OPT_BY_NAME]))
2794
          && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
2795
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
2796

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

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

    
2805
                  // ----- Look if the directory is in the filename path
2806
                  if (   (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
2807
                      && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
2808
                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
2809
                      $v_extract = true;
2810
                  }
2811
              }
2812
              // ----- Look for a filename
2813
              elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
2814
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
2815
                  $v_extract = true;
2816
              }
2817
          }
2818
      }
2819

    
2820
      // ----- Look for extract by ereg rule
2821
      else if (   (isset($p_options[PCLZIP_OPT_BY_EREG]))
2822
               && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
2823
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
2824

    
2825
          if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
2826
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
2827
              $v_extract = true;
2828
          }
2829
      }
2830

    
2831
      // ----- Look for extract by preg rule
2832
      else if (   (isset($p_options[PCLZIP_OPT_BY_PREG]))
2833
               && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
2834
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
2835

    
2836
          if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
2837
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
2838
              $v_extract = true;
2839
          }
2840
      }
2841

    
2842
      // ----- Look for extract by index rule
2843
      else if (   (isset($p_options[PCLZIP_OPT_BY_INDEX]))
2844
               && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
2845
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
2846
          
2847
          // ----- Look if the index is in the list
2848
          for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
2849
              //--(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']."]");
2850

    
2851
              if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
2852
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
2853
                  $v_extract = true;
2854
              }
2855
              if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
2856
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
2857
                  $j_start = $j+1;
2858
              }
2859

    
2860
              if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
2861
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
2862
                  break;
2863
              }
2864
          }
2865
      }
2866

    
2867
      // ----- Look for no rule, which means extract all the archive
2868
      else {
2869
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with no rule (extract all)");
2870
          $v_extract = true;
2871
      }
2872
      
2873

    
2874
      // ----- Look for real extraction
2875
      if ($v_extract)
2876
      {
2877
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file '".$v_header['filename']."', index '$i'");
2878

    
2879
        // ----- Go to the file position
2880
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
2881
        @rewind($this->zip_fd);
2882
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
2883
        if (@fseek($this->zip_fd, $v_header['offset']))
2884
        {
2885
          // ----- Close the zip file
2886
          $this->privCloseFd();
2887

    
2888
          // ----- Error log
2889
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
2890

    
2891
          // ----- Return
2892
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
2893
          return PclZip::errorCode();
2894
        }
2895
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
2896

    
2897
        // ----- Look for extraction as string
2898
        if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
2899

    
2900
          // ----- Extracting the file
2901
          $v_result1 = $this->privExtractFileAsString($v_header, $v_string);
2902
          if ($v_result1 < 1) {
2903
            $this->privCloseFd();
2904
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
2905
            return $v_result1;
2906
          }
2907

    
2908
          // ----- Get the only interesting attributes
2909
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
2910
          {
2911
            // ----- Close the zip file
2912
            $this->privCloseFd();
2913

    
2914
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2915
            return $v_result;
2916
          }
2917

    
2918
          // ----- Set the file content
2919
          $p_file_list[$v_nb_extracted]['content'] = $v_string;
2920

    
2921
          // ----- Next extracted file
2922
          $v_nb_extracted++;
2923
          
2924
          // ----- Look for user callback abort
2925
          if ($v_result1 == 2) {
2926
          	break;
2927
          }
2928
        }
2929
        // ----- Look for extraction in standard output
2930
        elseif (   (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
2931
		        && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
2932
          // ----- Extracting the file in standard output
2933
          $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
2934
          if ($v_result1 < 1) {
2935
            $this->privCloseFd();
2936
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
2937
            return $v_result1;
2938
          }
2939

    
2940
          // ----- Get the only interesting attributes
2941
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
2942
            $this->privCloseFd();
2943
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2944
            return $v_result;
2945
          }
2946

    
2947
          // ----- Look for user callback abort
2948
          if ($v_result1 == 2) {
2949
          	break;
2950
          }
2951
        }
2952
        // ----- Look for normal extraction
2953
        else {
2954
          // ----- Extracting the file
2955
          $v_result1 = $this->privExtractFile($v_header,
2956
		                                      $p_path, $p_remove_path,
2957
											  $p_remove_all_path,
2958
											  $p_options);
2959
          if ($v_result1 < 1) {
2960
            $this->privCloseFd();
2961
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
2962
            return $v_result1;
2963
          }
2964

    
2965
          // ----- Get the only interesting attributes
2966
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
2967
          {
2968
            // ----- Close the zip file
2969
            $this->privCloseFd();
2970

    
2971
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2972
            return $v_result;
2973
          }
2974

    
2975
          // ----- Look for user callback abort
2976
          if ($v_result1 == 2) {
2977
          	break;
2978
          }
2979
        }
2980
      }
2981
    }
2982

    
2983
    // ----- Close the zip file
2984
    $this->privCloseFd();
2985

    
2986
    // ----- Return
2987
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
2988
    return $v_result;
2989
  }
2990
  // --------------------------------------------------------------------------------
2991

    
2992
  // --------------------------------------------------------------------------------
2993
  // Function : privExtractFile()
2994
  // Description :
2995
  // Parameters :
2996
  // Return Values :
2997
  // --------------------------------------------------------------------------------
2998
  function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
2999
  {
3000
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFile', "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
3001
    $v_result=1;
3002

    
3003
    // ----- Read the file header
3004
    if (($v_result = $this->privReadFileHeader($v_header)) != 1)
3005
    {
3006
      // ----- Return
3007
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3008
      return $v_result;
3009
    }
3010

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

    
3013
    // ----- Check that the file header is coherent with $p_entry info
3014
    // TBC
3015

    
3016
    // ----- Look for all path to remove
3017
    if ($p_remove_all_path == true) {
3018
        // ----- Get the basename of the path
3019
        $p_entry['filename'] = basename($p_entry['filename']);
3020
    }
3021

    
3022
    // ----- Look for path to remove
3023
    else if ($p_remove_path != "")
3024
    {
3025
      //if (strcmp($p_remove_path, $p_entry['filename'])==0)
3026
      if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
3027
      {
3028
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The folder is the same as the removed path '".$p_entry['filename']."'");
3029

    
3030
        // ----- Change the file status
3031
        $p_entry['status'] = "filtered";
3032

    
3033
        // ----- Return
3034
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3035
        return $v_result;
3036
      }
3037

    
3038
      $p_remove_path_size = strlen($p_remove_path);
3039
      if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
3040
      {
3041
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '".$p_entry['filename']."'");
3042

    
3043
        // ----- Remove the path
3044
        $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
3045

    
3046
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Resulting file is '".$p_entry['filename']."'");
3047
      }
3048
    }
3049

    
3050
    // ----- Add the path
3051
    if ($p_path != '')
3052
    {
3053
      $p_entry['filename'] = $p_path."/".$p_entry['filename'];
3054
    }
3055

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

    
3060
      // ----- Generate a local information
3061
      $v_local_header = array();
3062
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3063

    
3064
      // ----- Call the callback
3065
      // Here I do not use call_user_func() because I need to send a reference to the
3066
      // header.
3067
      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
3068
      if ($v_result == 0) {
3069
        // ----- Change the file status
3070
        $p_entry['status'] = "skipped";
3071
        $v_result = 1;
3072
      }
3073
      
3074
      // ----- Look for abort result
3075
      if ($v_result == 2) {
3076
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
3077
        // ----- This status is internal and will be changed in 'skipped'
3078
        $p_entry['status'] = "aborted";
3079
      	$v_result = PCLZIP_ERR_USER_ABORTED;
3080
      }
3081

    
3082
      // ----- Update the informations
3083
      // Only some fields can be modified
3084
      $p_entry['filename'] = $v_local_header['filename'];
3085
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
3086
    }
3087

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

    
3091
    // ----- Look if extraction should be done
3092
    if ($p_entry['status'] == 'ok') {
3093

    
3094
    // ----- Look for specific actions while the file exist
3095
    if (file_exists($p_entry['filename']))
3096
    {
3097
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_entry['filename']."' already exists");
3098

    
3099
      // ----- Look if file is a directory
3100
      if (is_dir($p_entry['filename']))
3101
      {
3102
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is a directory");
3103

    
3104
        // ----- Change the file status
3105
        $p_entry['status'] = "already_a_directory";
3106

    
3107
        // ----- Return
3108
        ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3109
        //return $v_result;
3110
      }
3111
      // ----- Look if file is write protected
3112
      else if (!is_writeable($p_entry['filename']))
3113
      {
3114
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is write protected");
3115

    
3116
        // ----- Change the file status
3117
        $p_entry['status'] = "write_protected";
3118

    
3119
        // ----- Return
3120
        ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3121
        //return $v_result;
3122
      }
3123

    
3124
      // ----- Look if the extracted file is older
3125
      else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
3126
      {
3127
        //--(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']).")");
3128

    
3129
        // ----- Change the file status
3130
        $p_entry['status'] = "newer_exist";
3131

    
3132
        // ----- Return
3133
        ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3134
        //return $v_result;
3135
      }
3136
    }
3137

    
3138
    // ----- Check the directory availability and create it if necessary
3139
    else {
3140
      if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
3141
        $v_dir_to_check = $p_entry['filename'];
3142
      else if (!strstr($p_entry['filename'], "/"))
3143
        $v_dir_to_check = "";
3144
      else
3145
        $v_dir_to_check = dirname($p_entry['filename']);
3146

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

    
3150
        // ----- Change the file status
3151
        $p_entry['status'] = "path_creation_fail";
3152

    
3153
        // ----- Return
3154
        ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3155
        //return $v_result;
3156
        $v_result = 1;
3157
      }
3158
    }
3159
    }
3160

    
3161
    // ----- Look if extraction should be done
3162
    if ($p_entry['status'] == 'ok') {
3163

    
3164
      // ----- Do the extraction (if not a folder)
3165
      if (!(($p_entry['external']&0x00000010)==0x00000010))
3166
      {
3167

    
3168
        // ----- Look for not compressed file
3169
        if ($p_entry['compressed_size'] == $p_entry['size'])
3170
        {
3171
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
3172

    
3173
          // ----- Opening destination file
3174
          if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
3175
          {
3176
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
3177

    
3178
            // ----- Change the file status
3179
            $p_entry['status'] = "write_error";
3180

    
3181
            // ----- Return
3182
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3183
            return $v_result;
3184
          }
3185

    
3186
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
3187

    
3188
          // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3189
          $v_size = $p_entry['compressed_size'];
3190
          while ($v_size != 0)
3191
          {
3192
            $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3193
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
3194
            $v_buffer = fread($this->zip_fd, $v_read_size);
3195
            $v_binary_data = pack('a'.$v_read_size, $v_buffer);
3196
            @fwrite($v_dest_file, $v_binary_data, $v_read_size);
3197
            $v_size -= $v_read_size;
3198
          }
3199

    
3200
          // ----- Closing the destination file
3201
          fclose($v_dest_file);
3202

    
3203
          // ----- Change the file mtime
3204
          touch($p_entry['filename'], $p_entry['mtime']);
3205
        }
3206
        else
3207
        {
3208
          // ----- Trace
3209
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
3210

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

    
3215
            // ----- Change the file status
3216
            $p_entry['status'] = "write_error";
3217

    
3218
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3219
            return $v_result;
3220
          }
3221

    
3222
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Reading '".$p_entry['size']."' bytes");
3223

    
3224
          // ----- Read the compressed file in a buffer (one shot)
3225
          $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3226

    
3227
          // ----- Decompress the file
3228
          $v_file_content = gzinflate($v_buffer);
3229
          unset($v_buffer);
3230

    
3231
          // ----- Write the uncompressed data
3232
          @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
3233
          unset($v_file_content);
3234

    
3235
          // ----- Closing the destination file
3236
          @fclose($v_dest_file);
3237

    
3238
          // ----- Change the file mtime
3239
          touch($p_entry['filename'], $p_entry['mtime']);
3240
        }
3241

    
3242
        // ----- Look for chmod option
3243
        if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
3244
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "chmod option activated '".$p_options[PCLZIP_OPT_SET_CHMOD]."'");
3245

    
3246
          // ----- Change the mode of the file
3247
          chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
3248
        }
3249

    
3250
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
3251
      }
3252
    }
3253

    
3254
	// ----- Change abort status
3255
	if ($p_entry['status'] == "aborted") {
3256
      $p_entry['status'] = "skipped";
3257
	}
3258
	
3259
    // ----- Look for post-extract callback
3260
    elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
3261
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
3262

    
3263
      // ----- Generate a local information
3264
      $v_local_header = array();
3265
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3266

    
3267
      // ----- Call the callback
3268
      // Here I do not use call_user_func() because I need to send a reference to the
3269
      // header.
3270
      eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
3271

    
3272
      // ----- Look for abort result
3273
      if ($v_result == 2) {
3274
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
3275
      	$v_result = PCLZIP_ERR_USER_ABORTED;
3276
      }
3277
    }
3278

    
3279
    // ----- Return
3280
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3281
    return $v_result;
3282
  }
3283
  // --------------------------------------------------------------------------------
3284

    
3285
  // --------------------------------------------------------------------------------
3286
  // Function : privExtractFileInOutput()
3287
  // Description :
3288
  // Parameters :
3289
  // Return Values :
3290
  // --------------------------------------------------------------------------------
3291
  function privExtractFileInOutput(&$p_entry, &$p_options)
3292
  {
3293
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileInOutput', "");
3294
    $v_result=1;
3295

    
3296
    // ----- Read the file header
3297
    if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
3298
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3299
      return $v_result;
3300
    }
3301

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

    
3304
    // ----- Check that the file header is coherent with $p_entry info
3305
    // TBC
3306

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

    
3311
      // ----- Generate a local information
3312
      $v_local_header = array();
3313
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3314

    
3315
      // ----- Call the callback
3316
      // Here I do not use call_user_func() because I need to send a reference to the
3317
      // header.
3318
      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
3319
      if ($v_result == 0) {
3320
        // ----- Change the file status
3321
        $p_entry['status'] = "skipped";
3322
        $v_result = 1;
3323
      }
3324

    
3325
      // ----- Look for abort result
3326
      if ($v_result == 2) {
3327
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
3328
        // ----- This status is internal and will be changed in 'skipped'
3329
        $p_entry['status'] = "aborted";
3330
      	$v_result = PCLZIP_ERR_USER_ABORTED;
3331
      }
3332

    
3333
      // ----- Update the informations
3334
      // Only some fields can be modified
3335
      $p_entry['filename'] = $v_local_header['filename'];
3336
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
3337
    }
3338

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

    
3342
    // ----- Look if extraction should be done
3343
    if ($p_entry['status'] == 'ok') {
3344

    
3345
      // ----- Do the extraction (if not a folder)
3346
      if (!(($p_entry['external']&0x00000010)==0x00000010)) {
3347
        // ----- Look for not compressed file
3348
        if ($p_entry['compressed_size'] == $p_entry['size']) {
3349
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
3350
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
3351

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

    
3355
          // ----- Send the file to the output
3356
          echo $v_buffer;
3357
          unset($v_buffer);
3358
        }
3359
        else {
3360
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
3361
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Reading '".$p_entry['size']."' bytes");
3362

    
3363
          // ----- Read the compressed file in a buffer (one shot)
3364
          $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3365
          
3366
          // ----- Decompress the file
3367
          $v_file_content = gzinflate($v_buffer);
3368
          unset($v_buffer);
3369

    
3370
          // ----- Send the file to the output
3371
          echo $v_file_content;
3372
          unset($v_file_content);
3373
        }
3374
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
3375
      }
3376
    }
3377

    
3378
	// ----- Change abort status
3379
	if ($p_entry['status'] == "aborted") {
3380
      $p_entry['status'] = "skipped";
3381
	}
3382

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

    
3387
      // ----- Generate a local information
3388
      $v_local_header = array();
3389
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3390

    
3391
      // ----- Call the callback
3392
      // Here I do not use call_user_func() because I need to send a reference to the
3393
      // header.
3394
      eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
3395

    
3396
      // ----- Look for abort result
3397
      if ($v_result == 2) {
3398
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
3399
      	$v_result = PCLZIP_ERR_USER_ABORTED;
3400
      }
3401
    }
3402

    
3403
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3404
    return $v_result;
3405
  }
3406
  // --------------------------------------------------------------------------------
3407

    
3408
  // --------------------------------------------------------------------------------
3409
  // Function : privExtractFileAsString()
3410
  // Description :
3411
  // Parameters :
3412
  // Return Values :
3413
  // --------------------------------------------------------------------------------
3414
  function privExtractFileAsString(&$p_entry, &$p_string)
3415
  {
3416
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileAsString', "p_entry['filename']='".$p_entry['filename']."'");
3417
    $v_result=1;
3418

    
3419
    // ----- Read the file header
3420
    $v_header = array();
3421
    if (($v_result = $this->privReadFileHeader($v_header)) != 1)
3422
    {
3423
      // ----- Return
3424
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3425
      return $v_result;
3426
    }
3427

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

    
3430
    // ----- Check that the file header is coherent with $p_entry info
3431
    // TBC
3432

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

    
3436
    // ----- Do the extraction (if not a folder)
3437
    if (!(($p_entry['external']&0x00000010)==0x00000010))
3438
    {
3439
      // ----- Look for not compressed file
3440
      if ($p_entry['compressed_size'] == $p_entry['size'])
3441
      {
3442
        // ----- Trace
3443
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
3444
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
3445

    
3446
        // ----- Reading the file
3447
        $p_string = fread($this->zip_fd, $p_entry['compressed_size']);
3448
      }
3449
      else
3450
      {
3451
        // ----- Trace
3452
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
3453

    
3454
        // ----- Reading the file
3455
        $v_data = fread($this->zip_fd, $p_entry['compressed_size']);
3456
        
3457
        // ----- Decompress the file
3458
        $p_string = gzinflate($v_data);
3459
      }
3460

    
3461
      // ----- Trace
3462
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
3463
    }
3464
    else {
3465
        // TBC : error : can not extract a folder in a string
3466
    }
3467

    
3468
    // ----- Return
3469
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3470
    return $v_result;
3471
  }
3472
  // --------------------------------------------------------------------------------
3473

    
3474
  // --------------------------------------------------------------------------------
3475
  // Function : privReadFileHeader()
3476
  // Description :
3477
  // Parameters :
3478
  // Return Values :
3479
  // --------------------------------------------------------------------------------
3480
  function privReadFileHeader(&$p_header)
3481
  {
3482
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadFileHeader", "");
3483
    $v_result=1;
3484

    
3485
    // ----- Read the 4 bytes signature
3486
    $v_binary_data = @fread($this->zip_fd, 4);
3487
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
3488
    $v_data = unpack('Vid', $v_binary_data);
3489
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
3490

    
3491
    // ----- Check signature
3492
    if ($v_data['id'] != 0x04034b50)
3493
    {
3494
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid File header");
3495

    
3496
      // ----- Error log
3497
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
3498

    
3499
      // ----- Return
3500
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3501
      return PclZip::errorCode();
3502
    }
3503

    
3504
    // ----- Read the first 42 bytes of the header
3505
    $v_binary_data = fread($this->zip_fd, 26);
3506

    
3507
    // ----- Look for invalid block size
3508
    if (strlen($v_binary_data) != 26)
3509
    {
3510
      $p_header['filename'] = "";
3511
      $p_header['status'] = "invalid_header";
3512
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
3513

    
3514
      // ----- Error log
3515
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
3516

    
3517
      // ----- Return
3518
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3519
      return PclZip::errorCode();
3520
    }
3521

    
3522
    // ----- Extract the values
3523
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'");
3524
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'");
3525
    $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
3526

    
3527
    // ----- Get filename
3528
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$v_data['filename_len']);
3529
    $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
3530
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\'');
3531

    
3532
    // ----- Get extra_fields
3533
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra field length : ".$v_data['extra_len']);
3534
    if ($v_data['extra_len'] != 0) {
3535
      $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
3536
    }
3537
    else {
3538
      $p_header['extra'] = '';
3539
    }
3540
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra field : \''.bin2hex($p_header['extra']).'\'');
3541

    
3542
    // ----- Extract properties
3543
    $p_header['compression'] = $v_data['compression'];
3544
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compression method : \''.bin2hex($p_header['compression']).'\'');
3545
    $p_header['size'] = $v_data['size'];
3546
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\'');
3547
    $p_header['compressed_size'] = $v_data['compressed_size'];
3548
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
3549
    $p_header['crc'] = $v_data['crc'];
3550
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.$p_header['crc'].'\'');
3551
    $p_header['flag'] = $v_data['flag'];
3552
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\'');
3553

    
3554
    // ----- Recuperate date in UNIX format
3555
    $p_header['mdate'] = $v_data['mdate'];
3556
    $p_header['mtime'] = $v_data['mtime'];
3557
    if ($p_header['mdate'] && $p_header['mtime'])
3558
    {
3559
      // ----- Extract time
3560
      $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
3561
      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
3562
      $v_seconde = ($p_header['mtime'] & 0x001F)*2;
3563

    
3564
      // ----- Extract date
3565
      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
3566
      $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
3567
      $v_day = $p_header['mdate'] & 0x001F;
3568

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

    
3572
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
3573
    }
3574
    else
3575
    {
3576
      $p_header['mtime'] = time();
3577
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
3578
    }
3579

    
3580
    // ----- Other informations
3581
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compression type : ".$v_data['compression']);
3582
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Version : ".$v_data['version']);
3583

    
3584
    // TBC
3585
    //for(reset($v_data); $key = key($v_data); next($v_data)) {
3586
    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Attribut[$key] = ".$v_data[$key]);
3587
    //}
3588

    
3589
    // ----- Set the stored filename
3590
    $p_header['stored_filename'] = $p_header['filename'];
3591

    
3592
    // ----- Set the status field
3593
    $p_header['status'] = "ok";
3594

    
3595
    // ----- Return
3596
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3597
    return $v_result;
3598
  }
3599
  // --------------------------------------------------------------------------------
3600

    
3601
  // --------------------------------------------------------------------------------
3602
  // Function : privReadCentralFileHeader()
3603
  // Description :
3604
  // Parameters :
3605
  // Return Values :
3606
  // --------------------------------------------------------------------------------
3607
  function privReadCentralFileHeader(&$p_header)
3608
  {
3609
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadCentralFileHeader", "");
3610
    $v_result=1;
3611

    
3612
    // ----- Read the 4 bytes signature
3613
    $v_binary_data = @fread($this->zip_fd, 4);
3614
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
3615
    $v_data = unpack('Vid', $v_binary_data);
3616
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
3617

    
3618
    // ----- Check signature
3619
    if ($v_data['id'] != 0x02014b50)
3620
    {
3621
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid Central Dir File signature");
3622

    
3623
      // ----- Error log
3624
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
3625

    
3626
      // ----- Return
3627
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3628
      return PclZip::errorCode();
3629
    }
3630

    
3631
    // ----- Read the first 42 bytes of the header
3632
    $v_binary_data = fread($this->zip_fd, 42);
3633

    
3634
    // ----- Look for invalid block size
3635
    if (strlen($v_binary_data) != 42)
3636
    {
3637
      $p_header['filename'] = "";
3638
      $p_header['status'] = "invalid_header";
3639
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
3640

    
3641
      // ----- Error log
3642
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
3643

    
3644
      // ----- Return
3645
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3646
      return PclZip::errorCode();
3647
    }
3648

    
3649
    // ----- Extract the values
3650
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header : '".$v_binary_data."'");
3651
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header (Hex) : '".bin2hex($v_binary_data)."'");
3652
    $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);
3653

    
3654
    // ----- Get filename
3655
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File name length : ".$p_header['filename_len']);
3656
    if ($p_header['filename_len'] != 0)
3657
      $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
3658
    else
3659
      $p_header['filename'] = '';
3660
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Filename : \''.$p_header['filename'].'\'');
3661

    
3662
    // ----- Get extra
3663
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Extra length : ".$p_header['extra_len']);
3664
    if ($p_header['extra_len'] != 0)
3665
      $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
3666
    else
3667
      $p_header['extra'] = '';
3668
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Extra : \''.$p_header['extra'].'\'');
3669

    
3670
    // ----- Get comment
3671
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Comment length : ".$p_header['comment_len']);
3672
    if ($p_header['comment_len'] != 0)
3673
      $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
3674
    else
3675
      $p_header['comment'] = '';
3676
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Comment : \''.$p_header['comment'].'\'');
3677

    
3678
    // ----- Extract properties
3679
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version : \''.($p_header['version']/10).'.'.($p_header['version']%10).'\'');
3680
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
3681
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Size : \''.$p_header['size'].'\'');
3682
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
3683
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'CRC : \''.$p_header['crc'].'\'');
3684
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Flag : \''.$p_header['flag'].'\'');
3685
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Offset : \''.$p_header['offset'].'\'');
3686

    
3687
    // ----- Recuperate date in UNIX format
3688
    if ($p_header['mdate'] && $p_header['mtime'])
3689
    {
3690
      // ----- Extract time
3691
      $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
3692
      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
3693
      $v_seconde = ($p_header['mtime'] & 0x001F)*2;
3694

    
3695
      // ----- Extract date
3696
      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
3697
      $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
3698
      $v_day = $p_header['mdate'] & 0x001F;
3699

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

    
3703
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
3704
    }
3705
    else
3706
    {
3707
      $p_header['mtime'] = time();
3708
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
3709
    }
3710

    
3711
    // ----- Set the stored filename
3712
    $p_header['stored_filename'] = $p_header['filename'];
3713

    
3714
    // ----- Set default status to ok
3715
    $p_header['status'] = 'ok';
3716

    
3717
    // ----- Look if it is a directory
3718
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Internal (Hex) : '".sprintf("Ox%04X", $p_header['internal'])."'");
3719
    //--(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').')');
3720
    if (substr($p_header['filename'], -1) == '/')
3721
    {
3722
      $p_header['external'] = 0x41FF0010;
3723
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Force folder external : \''.$p_header['external'].'\'');
3724
    }
3725

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

    
3728
    // ----- Return
3729
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3730
    return $v_result;
3731
  }
3732
  // --------------------------------------------------------------------------------
3733

    
3734
  // --------------------------------------------------------------------------------
3735
  // Function : privReadEndCentralDir()
3736
  // Description :
3737
  // Parameters :
3738
  // Return Values :
3739
  // --------------------------------------------------------------------------------
3740
  function privReadEndCentralDir(&$p_central_dir)
3741
  {
3742
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadEndCentralDir", "");
3743
    $v_result=1;
3744

    
3745
    // ----- Go to the end of the zip file
3746
    $v_size = filesize($this->zipname);
3747
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size of the file :$v_size");
3748
    @fseek($this->zip_fd, $v_size);
3749
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position at end of zip file : \''.ftell($this->zip_fd).'\'');
3750
    if (@ftell($this->zip_fd) != $v_size)
3751
    {
3752
      // ----- Error log
3753
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
3754

    
3755
      // ----- Return
3756
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3757
      return PclZip::errorCode();
3758
    }
3759

    
3760
    // ----- First try : look if this is an archive with no commentaries (most of the time)
3761
    // in this case the end of central dir is at 22 bytes of the file end
3762
    $v_found = 0;
3763
    if ($v_size > 26) {
3764
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Look for central dir with no comment');
3765
      @fseek($this->zip_fd, $v_size-22);
3766
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after min central position : \''.ftell($this->zip_fd).'\'');
3767
      if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
3768
      {
3769
        // ----- Error log
3770
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
3771

    
3772
        // ----- Return
3773
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3774
        return PclZip::errorCode();
3775
      }
3776

    
3777
      // ----- Read for bytes
3778
      $v_binary_data = @fread($this->zip_fd, 4);
3779
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
3780
      $v_data = @unpack('Vid', $v_binary_data);
3781
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
3782

    
3783
      // ----- Check signature
3784
      if ($v_data['id'] == 0x06054b50) {
3785
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found central dir at the default position.");
3786
        $v_found = 1;
3787
      }
3788

    
3789
      $v_pos = ftell($this->zip_fd);
3790
    }
3791

    
3792
    // ----- Go back to the maximum possible size of the Central Dir End Record
3793
    if (!$v_found) {
3794
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Start extended search of end central dir');
3795
      $v_maximum_size = 65557; // 0xFFFF + 22;
3796
      if ($v_maximum_size > $v_size)
3797
        $v_maximum_size = $v_size;
3798
      @fseek($this->zip_fd, $v_size-$v_maximum_size);
3799
      if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
3800
      {
3801
        // ----- Error log
3802
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
3803

    
3804
        // ----- Return
3805
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3806
        return PclZip::errorCode();
3807
      }
3808
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');
3809

    
3810
      // ----- Read byte per byte in order to find the signature
3811
      $v_pos = ftell($this->zip_fd);
3812
      $v_bytes = 0x00000000;
3813
      while ($v_pos < $v_size)
3814
      {
3815
        // ----- Read a byte
3816
        $v_byte = @fread($this->zip_fd, 1);
3817

    
3818
        // -----  Add the byte
3819
        $v_bytes = ($v_bytes << 8) | Ord($v_byte);
3820

    
3821
        // ----- Compare the bytes
3822
        if ($v_bytes == 0x504b0506)
3823
        {
3824
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Found End Central Dir signature at position : \''.ftell($this->zip_fd).'\'');
3825
          $v_pos++;
3826
          break;
3827
        }
3828

    
3829
        $v_pos++;
3830
      }
3831

    
3832
      // ----- Look if not found end of central dir
3833
      if ($v_pos == $v_size)
3834
      {
3835
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to find End of Central Dir Record signature");
3836

    
3837
        // ----- Error log
3838
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
3839

    
3840
        // ----- Return
3841
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3842
        return PclZip::errorCode();
3843
      }
3844
    }
3845

    
3846
    // ----- Read the first 18 bytes of the header
3847
    $v_binary_data = fread($this->zip_fd, 18);
3848

    
3849
    // ----- Look for invalid block size
3850
    if (strlen($v_binary_data) != 18)
3851
    {
3852
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
3853

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

    
3857
      // ----- Return
3858
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3859
      return PclZip::errorCode();
3860
    }
3861

    
3862
    // ----- Extract the values
3863
    ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record : '".$v_binary_data."'");
3864
    ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record (Hex) : '".bin2hex($v_binary_data)."'");
3865
    $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
3866

    
3867
    // ----- Check the global size
3868
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$v_data['comment_size']);
3869
    if (($v_pos + $v_data['comment_size'] + 18) != $v_size)
3870
    {
3871
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Fail to find the right signature");
3872

    
3873
      // ----- Error log
3874
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Fail to find the right signature");
3875

    
3876
      // ----- Return
3877
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3878
      return PclZip::errorCode();
3879
    }
3880

    
3881
    // ----- Get comment
3882
    if ($v_data['comment_size'] != 0)
3883
      $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
3884
    else
3885
      $p_central_dir['comment'] = '';
3886
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_central_dir['comment'].'\'');
3887

    
3888
    $p_central_dir['entries'] = $v_data['entries'];
3889
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries : \''.$p_central_dir['entries'].'\'');
3890
    $p_central_dir['disk_entries'] = $v_data['disk_entries'];
3891
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries for this disk : \''.$p_central_dir['disk_entries'].'\'');
3892
    $p_central_dir['offset'] = $v_data['offset'];
3893
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset of Central Dir : \''.$p_central_dir['offset'].'\'');
3894
    $p_central_dir['size'] = $v_data['size'];
3895
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size of Central Dir : \''.$p_central_dir['size'].'\'');
3896
    $p_central_dir['disk'] = $v_data['disk'];
3897
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Disk number : \''.$p_central_dir['disk'].'\'');
3898
    $p_central_dir['disk_start'] = $v_data['disk_start'];
3899
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Start disk number : \''.$p_central_dir['disk_start'].'\'');
3900

    
3901
    // TBC
3902
    //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
3903
    //  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "central_dir[$key] = ".$p_central_dir[$key]);
3904
    //}
3905

    
3906
    // ----- Return
3907
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3908
    return $v_result;
3909
  }
3910
  // --------------------------------------------------------------------------------
3911

    
3912
  // --------------------------------------------------------------------------------
3913
  // Function : privDeleteByRule()
3914
  // Description :
3915
  // Parameters :
3916
  // Return Values :
3917
  // --------------------------------------------------------------------------------
3918
  function privDeleteByRule(&$p_result_list, &$p_options)
3919
  {
3920
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDeleteByRule", "");
3921
    $v_result=1;
3922
    $v_list_detail = array();
3923

    
3924
    // ----- Open the zip file
3925
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
3926
    if (($v_result=$this->privOpenFd('rb')) != 1)
3927
    {
3928
      // ----- Return
3929
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3930
      return $v_result;
3931
    }
3932

    
3933
    // ----- Read the central directory informations
3934
    $v_central_dir = array();
3935
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3936
    {
3937
      $this->privCloseFd();
3938
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3939
      return $v_result;
3940
    }
3941

    
3942
    // ----- Go to beginning of File
3943
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
3944
    @rewind($this->zip_fd);
3945
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
3946

    
3947
    // ----- Scan all the files
3948
    // ----- Start at beginning of Central Dir
3949
    $v_pos_entry = $v_central_dir['offset'];
3950
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
3951
    @rewind($this->zip_fd);
3952
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
3953
    if (@fseek($this->zip_fd, $v_pos_entry))
3954
    {
3955
      // ----- Close the zip file
3956
      $this->privCloseFd();
3957

    
3958
      // ----- Error log
3959
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3960

    
3961
      // ----- Return
3962
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
3963
      return PclZip::errorCode();
3964
    }
3965
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
3966

    
3967
    // ----- Read each entry
3968
    $v_header_list = array();
3969
    $j_start = 0;
3970
    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
3971
    {
3972
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry (index '$i')");
3973

    
3974
      // ----- Read the file header
3975
      $v_header_list[$v_nb_extracted] = array();
3976
      if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
3977
      {
3978
        // ----- Close the zip file
3979
        $this->privCloseFd();
3980

    
3981
        //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
3982
        return $v_result;
3983
      }
3984

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

    
3987
      // ----- Store the index
3988
      $v_header_list[$v_nb_extracted]['index'] = $i;
3989

    
3990
      // ----- Look for the specific extract rules
3991
      $v_found = false;
3992

    
3993
      // ----- Look for extract by name rule
3994
      if (   (isset($p_options[PCLZIP_OPT_BY_NAME]))
3995
          && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
3996
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
3997

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

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

    
4006
                  // ----- Look if the directory is in the filename path
4007
                  if (   (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
4008
                      && (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])) {
4009
                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
4010
                      $v_found = true;
4011
                  }
4012
                  elseif (   (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
4013
                          && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4014
                      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The entry is the searched directory");
4015
                      $v_found = true;
4016
                  }
4017
              }
4018
              // ----- Look for a filename
4019
              elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
4020
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
4021
                  $v_found = true;
4022
              }
4023
          }
4024
      }
4025

    
4026
      // ----- Look for extract by ereg rule
4027
      else if (   (isset($p_options[PCLZIP_OPT_BY_EREG]))
4028
               && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
4029
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
4030

    
4031
          if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4032
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
4033
              $v_found = true;
4034
          }
4035
      }
4036

    
4037
      // ----- Look for extract by preg rule
4038
      else if (   (isset($p_options[PCLZIP_OPT_BY_PREG]))
4039
               && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
4040
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
4041

    
4042
          if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4043
              //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
4044
              $v_found = true;
4045
          }
4046
      }
4047

    
4048
      // ----- Look for extract by index rule
4049
      else if (   (isset($p_options[PCLZIP_OPT_BY_INDEX]))
4050
               && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
4051
          //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
4052

    
4053
          // ----- Look if the index is in the list
4054
          for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
4055
              //--(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']."]");
4056

    
4057
              if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
4058
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
4059
                  $v_found = true;
4060
              }
4061
              if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
4062
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
4063
                  $j_start = $j+1;
4064
              }
4065

    
4066
              if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
4067
                  //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
4068
                  break;
4069
              }
4070
          }
4071
      }
4072

    
4073
      // ----- Look for deletion
4074
      if ($v_found)
4075
      {
4076
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' need to be deleted");
4077
        unset($v_header_list[$v_nb_extracted]);
4078
      }
4079
      else
4080
      {
4081
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' will not be deleted");
4082
        $v_nb_extracted++;
4083
      }
4084
    }
4085

    
4086
    // ----- Look if something need to be deleted
4087
    if ($v_nb_extracted > 0) {
4088

    
4089
        // ----- Creates a temporay file
4090
        $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
4091

    
4092
        // ----- Creates a temporary zip archive
4093
        $v_temp_zip = new PclZip($v_zip_temp_name);
4094

    
4095
        // ----- Open the temporary zip file in write mode
4096
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary write mode");
4097
        if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
4098
            $this->privCloseFd();
4099

    
4100
            // ----- Return
4101
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4102
            return $v_result;
4103
        }
4104

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

    
4109
            // ----- Calculate the position of the header
4110
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset='". $v_header_list[$i]['offset']."'");
4111
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
4112
            @rewind($this->zip_fd);
4113
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
4114
            if (@fseek($this->zip_fd,  $v_header_list[$i]['offset'])) {
4115
                // ----- Close the zip file
4116
                $this->privCloseFd();
4117
                $v_temp_zip->privCloseFd();
4118
                @unlink($v_zip_temp_name);
4119

    
4120
                // ----- Error log
4121
                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4122

    
4123
                // ----- Return
4124
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4125
                return PclZip::errorCode();
4126
            }
4127
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
4128

    
4129
            // ----- Read the file header
4130
            if (($v_result = $this->privReadFileHeader($v_header_list[$i])) != 1) {
4131
                // ----- Close the zip file
4132
                $this->privCloseFd();
4133
                $v_temp_zip->privCloseFd();
4134
                @unlink($v_zip_temp_name);
4135

    
4136
                // ----- Return
4137
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4138
                return $v_result;
4139
            }
4140

    
4141
            // ----- Write the file header
4142
            if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
4143
                // ----- Close the zip file
4144
                $this->privCloseFd();
4145
                $v_temp_zip->privCloseFd();
4146
                @unlink($v_zip_temp_name);
4147

    
4148
                // ----- Return
4149
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4150
                return $v_result;
4151
            }
4152
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset for this file is '".$v_header_list[$i]['offset']."'");
4153

    
4154
            // ----- Read/write the data block
4155
            if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
4156
                // ----- Close the zip file
4157
                $this->privCloseFd();
4158
                $v_temp_zip->privCloseFd();
4159
                @unlink($v_zip_temp_name);
4160

    
4161
                // ----- Return
4162
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4163
                return $v_result;
4164
            }
4165
        }
4166

    
4167
        // ----- Store the offset of the central dir
4168
        $v_offset = @ftell($v_temp_zip->zip_fd);
4169
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "New offset of central dir : $v_offset");
4170

    
4171
        // ----- Re-Create the Central Dir files header
4172
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the new central directory");
4173
        for ($i=0; $i<sizeof($v_header_list); $i++) {
4174
            // ----- Create the file header
4175
            //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset of file : ".$v_header_list[$i]['offset']);
4176
            if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
4177
                $v_temp_zip->privCloseFd();
4178
                $this->privCloseFd();
4179
                @unlink($v_zip_temp_name);
4180

    
4181
                // ----- Return
4182
                //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4183
                return $v_result;
4184
            }
4185

    
4186
            // ----- Transform the header to a 'usable' info
4187
            $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
4188
        }
4189

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

    
4192
        // ----- Zip file comment
4193
        $v_comment = '';
4194
        if (isset($p_options[PCLZIP_OPT_COMMENT])) {
4195
          $v_comment = $p_options[PCLZIP_OPT_COMMENT];
4196
        }
4197

    
4198
        // ----- Calculate the size of the central header
4199
        $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
4200

    
4201
        // ----- Create the central dir footer
4202
        if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
4203
            // ----- Reset the file list
4204
            unset($v_header_list);
4205
            $v_temp_zip->privCloseFd();
4206
            $this->privCloseFd();
4207
            @unlink($v_zip_temp_name);
4208

    
4209
            // ----- Return
4210
            //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4211
            return $v_result;
4212
        }
4213

    
4214
        // ----- Close
4215
        $v_temp_zip->privCloseFd();
4216
        $this->privCloseFd();
4217

    
4218
        // ----- Delete the zip file
4219
        // TBC : I should test the result ...
4220
        @unlink($this->zipname);
4221

    
4222
        // ----- Rename the temporary file
4223
        // TBC : I should test the result ...
4224
        //@rename($v_zip_temp_name, $this->zipname);
4225
        PclZipUtilRename($v_zip_temp_name, $this->zipname);
4226
    
4227
        // ----- Destroy the temporary archive
4228
        unset($v_temp_zip);
4229
    }
4230
    
4231
    // ----- Remove every files : reset the file
4232
    else if ($v_central_dir['entries'] != 0) {
4233
        $this->privCloseFd();
4234

    
4235
        if (($v_result = $this->privOpenFd('wb')) != 1) {
4236
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4237
          return $v_result;
4238
        }
4239

    
4240
        if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
4241
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4242
          return $v_result;
4243
        }
4244

    
4245
        $this->privCloseFd();
4246
    }
4247

    
4248
    // ----- Return
4249
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4250
    return $v_result;
4251
  }
4252
  // --------------------------------------------------------------------------------
4253

    
4254
  // --------------------------------------------------------------------------------
4255
  // Function : privDirCheck()
4256
  // Description :
4257
  //   Check if a directory exists, if not it creates it and all the parents directory
4258
  //   which may be useful.
4259
  // Parameters :
4260
  //   $p_dir : Directory path to check.
4261
  // Return Values :
4262
  //    1 : OK
4263
  //   -1 : Unable to create directory
4264
  // --------------------------------------------------------------------------------
4265
  function privDirCheck($p_dir, $p_is_dir=false)
4266
  {
4267
    $v_result = 1;
4268

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

    
4271
    // ----- Remove the final '/'
4272
    if (($p_is_dir) && (substr($p_dir, -1)=='/'))
4273
    {
4274
      $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
4275
    }
4276
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for entry '$p_dir'");
4277

    
4278
    // ----- Check the directory availability
4279
    if ((is_dir($p_dir)) || ($p_dir == ""))
4280
    {
4281
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
4282
      return 1;
4283
    }
4284

    
4285
    // ----- Extract parent directory
4286
    $p_parent_dir = dirname($p_dir);
4287
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
4288

    
4289
    // ----- Just a check
4290
    if ($p_parent_dir != $p_dir)
4291
    {
4292
      // ----- Look for parent directory
4293
      if ($p_parent_dir != "")
4294
      {
4295
        if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
4296
        {
4297
          //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4298
          return $v_result;
4299
        }
4300
      }
4301
    }
4302

    
4303
    // ----- Create the directory
4304
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
4305
    if (!@mkdir($p_dir, 0777))
4306
    {
4307
      // ----- Error log
4308
      PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
4309

    
4310
      // ----- Return
4311
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4312
      return PclZip::errorCode();
4313
    }
4314

    
4315
    // ----- Return
4316
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
4317
    return $v_result;
4318
  }
4319
  // --------------------------------------------------------------------------------
4320

    
4321
  // --------------------------------------------------------------------------------
4322
  // Function : privMerge()
4323
  // Description :
4324
  //   If $p_archive_to_add does not exist, the function exit with a success result.
4325
  // Parameters :
4326
  // Return Values :
4327
  // --------------------------------------------------------------------------------
4328
  function privMerge(&$p_archive_to_add)
4329
  {
4330
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privMerge", "archive='".$p_archive_to_add->zipname."'");
4331
    $v_result=1;
4332

    
4333
    // ----- Look if the archive_to_add exists
4334
    if (!is_file($p_archive_to_add->zipname))
4335
    {
4336
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to add does not exist. End of merge.");
4337

    
4338
      // ----- Nothing to merge, so merge is a success
4339
      $v_result = 1;
4340

    
4341
      // ----- Return
4342
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4343
      return $v_result;
4344
    }
4345

    
4346
    // ----- Look if the archive exists
4347
    if (!is_file($this->zipname))
4348
    {
4349
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, duplicate the archive_to_add.");
4350

    
4351
      // ----- Do a duplicate
4352
      $v_result = $this->privDuplicate($p_archive_to_add->zipname);
4353

    
4354
      // ----- Return
4355
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4356
      return $v_result;
4357
    }
4358

    
4359
    // ----- Open the zip file
4360
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
4361
    if (($v_result=$this->privOpenFd('rb')) != 1)
4362
    {
4363
      // ----- Return
4364
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4365
      return $v_result;
4366
    }
4367

    
4368
    // ----- Read the central directory informations
4369
    $v_central_dir = array();
4370
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
4371
    {
4372
      $this->privCloseFd();
4373
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4374
      return $v_result;
4375
    }
4376

    
4377
    // ----- Go to beginning of File
4378
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
4379
    @rewind($this->zip_fd);
4380
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
4381

    
4382
    // ----- Open the archive_to_add file
4383
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open archive_to_add in binary read mode");
4384
    if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
4385
    {
4386
      $this->privCloseFd();
4387

    
4388
      // ----- Return
4389
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4390
      return $v_result;
4391
    }
4392

    
4393
    // ----- Read the central directory informations
4394
    $v_central_dir_to_add = array();
4395
    if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
4396
    {
4397
      $this->privCloseFd();
4398
      $p_archive_to_add->privCloseFd();
4399

    
4400
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4401
      return $v_result;
4402
    }
4403

    
4404
    // ----- Go to beginning of File
4405
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
4406
    @rewind($p_archive_to_add->zip_fd);
4407
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
4408

    
4409
    // ----- Creates a temporay file
4410
    $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
4411

    
4412
    // ----- Open the temporary file in write mode
4413
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
4414
    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
4415
    {
4416
      $this->privCloseFd();
4417
      $p_archive_to_add->privCloseFd();
4418

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

    
4421
      // ----- Return
4422
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4423
      return PclZip::errorCode();
4424
    }
4425

    
4426
    // ----- Copy the files from the archive to the temporary file
4427
    // TBC : Here I should better append the file and go back to erase the central dir
4428
    $v_size = $v_central_dir['offset'];
4429
    while ($v_size != 0)
4430
    {
4431
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4432
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
4433
      $v_buffer = fread($this->zip_fd, $v_read_size);
4434
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
4435
      $v_size -= $v_read_size;
4436
    }
4437

    
4438
    // ----- Copy the files from the archive_to_add into the temporary file
4439
    $v_size = $v_central_dir_to_add['offset'];
4440
    while ($v_size != 0)
4441
    {
4442
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4443
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
4444
      $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
4445
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
4446
      $v_size -= $v_read_size;
4447
    }
4448

    
4449
    // ----- Store the offset of the central dir
4450
    $v_offset = @ftell($v_zip_temp_fd);
4451
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
4452

    
4453
    // ----- Copy the block of file headers from the old archive
4454
    $v_size = $v_central_dir['size'];
4455
    while ($v_size != 0)
4456
    {
4457
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4458
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
4459
      $v_buffer = @fread($this->zip_fd, $v_read_size);
4460
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
4461
      $v_size -= $v_read_size;
4462
    }
4463

    
4464
    // ----- Copy the block of file headers from the archive_to_add
4465
    $v_size = $v_central_dir_to_add['size'];
4466
    while ($v_size != 0)
4467
    {
4468
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4469
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
4470
      $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
4471
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
4472
      $v_size -= $v_read_size;
4473
    }
4474

    
4475
    // ----- Merge the file comments
4476
    $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
4477

    
4478
    // ----- Calculate the size of the (new) central header
4479
    $v_size = @ftell($v_zip_temp_fd)-$v_offset;
4480

    
4481
    // ----- Swap the file descriptor
4482
    // Here is a trick : I swap the temporary fd with the zip fd, in order to use
4483
    // the following methods on the temporary fil and not the real archive fd
4484
    $v_swap = $this->zip_fd;
4485
    $this->zip_fd = $v_zip_temp_fd;
4486
    $v_zip_temp_fd = $v_swap;
4487

    
4488
    // ----- Create the central dir footer
4489
    if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
4490
    {
4491
      $this->privCloseFd();
4492
      $p_archive_to_add->privCloseFd();
4493
      @fclose($v_zip_temp_fd);
4494
      $this->zip_fd = null;
4495

    
4496
      // ----- Reset the file list
4497
      unset($v_header_list);
4498

    
4499
      // ----- Return
4500
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4501
      return $v_result;
4502
    }
4503

    
4504
    // ----- Swap back the file descriptor
4505
    $v_swap = $this->zip_fd;
4506
    $this->zip_fd = $v_zip_temp_fd;
4507
    $v_zip_temp_fd = $v_swap;
4508

    
4509
    // ----- Close
4510
    $this->privCloseFd();
4511
    $p_archive_to_add->privCloseFd();
4512

    
4513
    // ----- Close the temporary file
4514
    @fclose($v_zip_temp_fd);
4515

    
4516
    // ----- Delete the zip file
4517
    // TBC : I should test the result ...
4518
    @unlink($this->zipname);
4519

    
4520
    // ----- Rename the temporary file
4521
    // TBC : I should test the result ...
4522
    //@rename($v_zip_temp_name, $this->zipname);
4523
    PclZipUtilRename($v_zip_temp_name, $this->zipname);
4524

    
4525
    // ----- Return
4526
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4527
    return $v_result;
4528
  }
4529
  // --------------------------------------------------------------------------------
4530

    
4531
  // --------------------------------------------------------------------------------
4532
  // Function : privDuplicate()
4533
  // Description :
4534
  // Parameters :
4535
  // Return Values :
4536
  // --------------------------------------------------------------------------------
4537
  function privDuplicate($p_archive_filename)
4538
  {
4539
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDuplicate", "archive_filename='$p_archive_filename'");
4540
    $v_result=1;
4541

    
4542
    // ----- Look if the $p_archive_filename exists
4543
    if (!is_file($p_archive_filename))
4544
    {
4545
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to duplicate does not exist. End of duplicate.");
4546

    
4547
      // ----- Nothing to duplicate, so duplicate is a success.
4548
      $v_result = 1;
4549

    
4550
      // ----- Return
4551
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4552
      return $v_result;
4553
    }
4554

    
4555
    // ----- Open the zip file
4556
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
4557
    if (($v_result=$this->privOpenFd('wb')) != 1)
4558
    {
4559
      // ----- Return
4560
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4561
      return $v_result;
4562
    }
4563

    
4564
    // ----- Open the temporary file in write mode
4565
    //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
4566
    if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
4567
    {
4568
      $this->privCloseFd();
4569

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

    
4572
      // ----- Return
4573
      //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
4574
      return PclZip::errorCode();
4575
    }
4576

    
4577
    // ----- Copy the files from the archive to the temporary file
4578
    // TBC : Here I should better append the file and go back to erase the central dir
4579
    $v_size = filesize($p_archive_filename);
4580
    while ($v_size != 0)
4581
    {
4582
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4583
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read $v_read_size bytes");
4584
      $v_buffer = fread($v_zip_temp_fd, $v_read_size);
4585
      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
4586
      $v_size -= $v_read_size;
4587
    }
4588

    
4589
    // ----- Close
4590
    $this->privCloseFd();
4591

    
4592
    // ----- Close the temporary file
4593
    @fclose($v_zip_temp_fd);
4594

    
4595
    // ----- Return
4596
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4597
    return $v_result;
4598
  }
4599
  // --------------------------------------------------------------------------------
4600

    
4601
  // --------------------------------------------------------------------------------
4602
  // Function : privErrorLog()
4603
  // Description :
4604
  // Parameters :
4605
  // --------------------------------------------------------------------------------
4606
  function privErrorLog($p_error_code=0, $p_error_string='')
4607
  {
4608
    if (PCLZIP_ERROR_EXTERNAL == 1) {
4609
      PclError($p_error_code, $p_error_string);
4610
    }
4611
    else {
4612
      $this->error_code = $p_error_code;
4613
      $this->error_string = $p_error_string;
4614
    }
4615
  }
4616
  // --------------------------------------------------------------------------------
4617

    
4618
  // --------------------------------------------------------------------------------
4619
  // Function : privErrorReset()
4620
  // Description :
4621
  // Parameters :
4622
  // --------------------------------------------------------------------------------
4623
  function privErrorReset()
4624
  {
4625
    if (PCLZIP_ERROR_EXTERNAL == 1) {
4626
      PclErrorReset();
4627
    }
4628
    else {
4629
      $this->error_code = 1;
4630
      $this->error_string = '';
4631
    }
4632
  }
4633
  // --------------------------------------------------------------------------------
4634

    
4635
  }
4636
  // End of class
4637
  // --------------------------------------------------------------------------------
4638

    
4639
  // --------------------------------------------------------------------------------
4640
  // Function : PclZipUtilPathReduction()
4641
  // Description :
4642
  // Parameters :
4643
  // Return Values :
4644
  // --------------------------------------------------------------------------------
4645
  function PclZipUtilPathReduction($p_dir)
4646
  {
4647
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathReduction", "dir='$p_dir'");
4648
    $v_result = "";
4649

    
4650
    // ----- Look for not empty path
4651
    if ($p_dir != "")
4652
    {
4653
      // ----- Explode path by directory names
4654
      $v_list = explode("/", $p_dir);
4655

    
4656
      // ----- Study directories from last to first
4657
      for ($i=sizeof($v_list)-1; $i>=0; $i--)
4658
      {
4659
        // ----- Look for current path
4660
        if ($v_list[$i] == ".")
4661
        {
4662
          // ----- Ignore this directory
4663
          // Should be the first $i=0, but no check is done
4664
        }
4665
        else if ($v_list[$i] == "..")
4666
        {
4667
          // ----- Ignore it and ignore the $i-1
4668
          $i--;
4669
        }
4670
        else if (($v_list[$i] == "") && ($i!=(sizeof($v_list)-1)) && ($i!=0))
4671
        {
4672
          // ----- Ignore only the double '//' in path,
4673
          // but not the first and last '/'
4674
        }
4675
        else
4676
        {
4677
          $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
4678
        }
4679
      }
4680
    }
4681

    
4682
    // ----- Return
4683
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4684
    return $v_result;
4685
  }
4686
  // --------------------------------------------------------------------------------
4687

    
4688
  // --------------------------------------------------------------------------------
4689
  // Function : PclZipUtilPathInclusion()
4690
  // Description :
4691
  //   This function indicates if the path $p_path is under the $p_dir tree. Or,
4692
  //   said in an other way, if the file or sub-dir $p_path is inside the dir
4693
  //   $p_dir.
4694
  //   The function indicates also if the path is exactly the same as the dir.
4695
  //   This function supports path with duplicated '/' like '//', but does not
4696
  //   support '.' or '..' statements.
4697
  // Parameters :
4698
  // Return Values :
4699
  //   0 if $p_path is not inside directory $p_dir
4700
  //   1 if $p_path is inside directory $p_dir
4701
  //   2 if $p_path is exactly the same as $p_dir
4702
  // --------------------------------------------------------------------------------
4703
  function PclZipUtilPathInclusion($p_dir, $p_path)
4704
  {
4705
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathInclusion", "dir='$p_dir', path='$p_path'");
4706
    $v_result = 1;
4707

    
4708
    // ----- Explode dir and path by directory separator
4709
    $v_list_dir = explode("/", $p_dir);
4710
    $v_list_dir_size = sizeof($v_list_dir);
4711
    $v_list_path = explode("/", $p_path);
4712
    $v_list_path_size = sizeof($v_list_path);
4713

    
4714
    // ----- Study directories paths
4715
    $i = 0;
4716
    $j = 0;
4717
    while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
4718
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Working on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'");
4719

    
4720
      // ----- Look for empty dir (path reduction)
4721
      if ($v_list_dir[$i] == '') {
4722
        $i++;
4723
        continue;
4724
      }
4725
      if ($v_list_path[$j] == '') {
4726
        $j++;
4727
        continue;
4728
      }
4729

    
4730
      // ----- Compare the items
4731
      if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != ''))  {
4732
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Items ($i,$j) are different");
4733
        $v_result = 0;
4734
      }
4735

    
4736
      // ----- Next items
4737
      $i++;
4738
      $j++;
4739
    }
4740

    
4741
    // ----- Look if everything seems to be the same
4742
    if ($v_result) {
4743
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Look for tie break");
4744
      // ----- Skip all the empty items
4745
      while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
4746
      while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
4747
      //--(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]:'')."'");
4748

    
4749
      if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
4750
        // ----- There are exactly the same
4751
        $v_result = 2;
4752
      }
4753
      else if ($i < $v_list_dir_size) {
4754
        // ----- The path is shorter than the dir
4755
        $v_result = 0;
4756
      }
4757
    }
4758

    
4759
    // ----- Return
4760
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4761
    return $v_result;
4762
  }
4763
  // --------------------------------------------------------------------------------
4764

    
4765
  // --------------------------------------------------------------------------------
4766
  // Function : PclZipUtilCopyBlock()
4767
  // Description :
4768
  // Parameters :
4769
  //   $p_mode : read/write compression mode
4770
  //             0 : src & dest normal
4771
  //             1 : src gzip, dest normal
4772
  //             2 : src normal, dest gzip
4773
  //             3 : src & dest gzip
4774
  // Return Values :
4775
  // --------------------------------------------------------------------------------
4776
  function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
4777
  {
4778
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilCopyBlock", "size=$p_size, mode=$p_mode");
4779
    $v_result = 1;
4780

    
4781
    if ($p_mode==0)
4782
    {
4783
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset before read :".(@ftell($p_src)));
4784
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset before write :".(@ftell($p_dest)));
4785
      while ($p_size != 0)
4786
      {
4787
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
4788
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
4789
        $v_buffer = @fread($p_src, $v_read_size);
4790
        @fwrite($p_dest, $v_buffer, $v_read_size);
4791
        $p_size -= $v_read_size;
4792
      }
4793
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset after read :".(@ftell($p_src)));
4794
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset after write :".(@ftell($p_dest)));
4795
    }
4796
    else if ($p_mode==1)
4797
    {
4798
      while ($p_size != 0)
4799
      {
4800
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
4801
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
4802
        $v_buffer = @gzread($p_src, $v_read_size);
4803
        @fwrite($p_dest, $v_buffer, $v_read_size);
4804
        $p_size -= $v_read_size;
4805
      }
4806
    }
4807
    else if ($p_mode==2)
4808
    {
4809
      while ($p_size != 0)
4810
      {
4811
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
4812
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
4813
        $v_buffer = @fread($p_src, $v_read_size);
4814
        @gzwrite($p_dest, $v_buffer, $v_read_size);
4815
        $p_size -= $v_read_size;
4816
      }
4817
    }
4818
    else if ($p_mode==3)
4819
    {
4820
      while ($p_size != 0)
4821
      {
4822
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
4823
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
4824
        $v_buffer = @gzread($p_src, $v_read_size);
4825
        @gzwrite($p_dest, $v_buffer, $v_read_size);
4826
        $p_size -= $v_read_size;
4827
      }
4828
    }
4829

    
4830
    // ----- Return
4831
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4832
    return $v_result;
4833
  }
4834
  // --------------------------------------------------------------------------------
4835

    
4836
  // --------------------------------------------------------------------------------
4837
  // Function : PclZipUtilRename()
4838
  // Description :
4839
  //   This function tries to do a simple rename() function. If it fails, it
4840
  //   tries to copy the $p_src file in a new $p_dest file and then unlink the
4841
  //   first one.
4842
  // Parameters :
4843
  //   $p_src : Old filename
4844
  //   $p_dest : New filename
4845
  // Return Values :
4846
  //   1 on success, 0 on failure.
4847
  // --------------------------------------------------------------------------------
4848
  function PclZipUtilRename($p_src, $p_dest)
4849
  {
4850
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilRename", "source=$p_src, destination=$p_dest");
4851
    $v_result = 1;
4852

    
4853
    // ----- Try to rename the files
4854
    if (!@rename($p_src, $p_dest)) {
4855
      //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to rename file, try copy+unlink");
4856

    
4857
      // ----- Try to copy & unlink the src
4858
      if (!@copy($p_src, $p_dest)) {
4859
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to copy file");
4860
        $v_result = 0;
4861
      }
4862
      else if (!@unlink($p_src)) {
4863
        //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to unlink old filename");
4864
        $v_result = 0;
4865
      }
4866
    }
4867

    
4868
    // ----- Return
4869
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4870
    return $v_result;
4871
  }
4872
  // --------------------------------------------------------------------------------
4873

    
4874
  // --------------------------------------------------------------------------------
4875
  // Function : PclZipUtilOptionText()
4876
  // Description :
4877
  //   Translate option value in text. Mainly for debug purpose.
4878
  // Parameters :
4879
  //   $p_option : the option value.
4880
  // Return Values :
4881
  //   The option text value.
4882
  // --------------------------------------------------------------------------------
4883
  function PclZipUtilOptionText($p_option)
4884
  {
4885
    //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilOptionText", "option='".$p_option."'");
4886

    
4887
    switch ($p_option) {
4888
      case PCLZIP_OPT_PATH :
4889
        $v_result = 'PCLZIP_OPT_PATH';
4890
      break;
4891
      case PCLZIP_OPT_ADD_PATH :
4892
        $v_result = 'PCLZIP_OPT_ADD_PATH';
4893
      break;
4894
      case PCLZIP_OPT_REMOVE_PATH :
4895
        $v_result = 'PCLZIP_OPT_REMOVE_PATH';
4896
      break;
4897
      case PCLZIP_OPT_REMOVE_ALL_PATH :
4898
        $v_result = 'PCLZIP_OPT_REMOVE_ALL_PATH';
4899
      break;
4900
      case PCLZIP_OPT_EXTRACT_AS_STRING :
4901
        $v_result = 'PCLZIP_OPT_EXTRACT_AS_STRING';
4902
      break;
4903
      case PCLZIP_OPT_SET_CHMOD :
4904
        $v_result = 'PCLZIP_OPT_SET_CHMOD';
4905
      break;
4906
      case PCLZIP_OPT_BY_NAME :
4907
        $v_result = 'PCLZIP_OPT_BY_NAME';
4908
      break;
4909
      case PCLZIP_OPT_BY_INDEX :
4910
        $v_result = 'PCLZIP_OPT_BY_INDEX';
4911
      break;
4912
      case PCLZIP_OPT_BY_EREG :
4913
        $v_result = 'PCLZIP_OPT_BY_EREG';
4914
      break;
4915
      case PCLZIP_OPT_BY_PREG :
4916
        $v_result = 'PCLZIP_OPT_BY_PREG';
4917
      break;
4918

    
4919

    
4920
      case PCLZIP_CB_PRE_EXTRACT :
4921
        $v_result = 'PCLZIP_CB_PRE_EXTRACT';
4922
      break;
4923
      case PCLZIP_CB_POST_EXTRACT :
4924
        $v_result = 'PCLZIP_CB_POST_EXTRACT';
4925
      break;
4926
      case PCLZIP_CB_PRE_ADD :
4927
        $v_result = 'PCLZIP_CB_PRE_ADD';
4928
      break;
4929
      case PCLZIP_CB_POST_ADD :
4930
        $v_result = 'PCLZIP_CB_POST_ADD';
4931
      break;
4932

    
4933
      default :
4934
        $v_result = 'Unknown';
4935
    }
4936

    
4937
    // ----- Return
4938
    //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
4939
    return $v_result;
4940
  }
4941
  // --------------------------------------------------------------------------------
4942

    
4943
  // --------------------------------------------------------------------------------
4944
  // Function : PclZipUtilTranslateWinPath()
4945
  // Description :
4946
  //   Translate windows path by replacing '\' by '/' and optionally removing
4947
  //   drive letter.
4948
  // Parameters :
4949
  //   $p_path : path to translate.
4950
  //   $p_remove_disk_letter : true | false
4951
  // Return Values :
4952
  //   The path translated.
4953
  // --------------------------------------------------------------------------------
4954
  function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
4955
  {
4956
    if (stristr(php_uname(), 'windows')) {
4957
      // ----- Look for potential disk letter
4958
      if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
4959
          $p_path = substr($p_path, $v_position+1);
4960
      }
4961
      // ----- Change potential windows directory separator
4962
      if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
4963
          $p_path = strtr($p_path, '\\', '/');
4964
      }
4965
    }
4966
    return $p_path;
4967
  }
4968
  // --------------------------------------------------------------------------------
4969

    
4970
?>
(2-2/3)