[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/phpexcel/PHPExcel/Shared/PCLZip/ -> pclzip.lib.php (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1