Ignore:
Timestamp:
Mar 9, 2010, 12:39:53 AM (14 years ago)
Author:
plg
Message:

feature 1489: integrate UploadForm into Piwigo core. The integration is not
100% done, I just "made it work" on trunk.

pclzip library was updated to version 2.8.2 for memory usage improvement.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/admin/include/pclzip.lib.php

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