[ Index ]

PHP Cross Reference of Wordpress 2.7.1

title

Body

[close]

/wp-admin/includes/ -> class-pclzip.php (source)

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


Generated: Mon Mar 23 16:23:02 2009 Cross-referenced by PHPXref 0.7