Changeset 125322 in spip-zone


Ignore:
Timestamp:
Jun 25, 2020, 5:49:33 PM (3 weeks ago)
Author:
Matthieu Marcillaud
Message:

Indentation…

Location:
_outils_/spip_loader/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • _outils_/spip_loader/trunk

    • Property subgit:lock:0e93074c83190d06c5f73756b9af93fe76459d89 deleted
    • Property subgit:lock:108de5375f91b390962c9b2b26e5c0111572ea01 set to 2020-06-25T19:50:43.296
  • _outils_/spip_loader/trunk/pclzip.php

    r125320 r125322  
    2626// personnalisations spip
    2727if (!defined('PCLZIP_TEMPORARY_DIR')) {
    28   define('PCLZIP_TEMPORARY_DIR', _DIR_TMP);
     28        define('PCLZIP_TEMPORARY_DIR', _DIR_TMP);
    2929}
    3030if (!function_exists('gzopen') && function_exists('gzopen64')) {
    31   function gzopen($filename, $mode, $use_include_path = 0) {
    32     return gzopen64($filename, $mode, $use_include_path);
    33   }
     31        function gzopen($filename, $mode, $use_include_path = 0) {
     32                return gzopen64($filename, $mode, $use_include_path);
     33        }
    3434}
    3535// fin personnalisations spip
     
    3737// ----- Constants
    3838if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
    39   define('PCLZIP_READ_BLOCK_SIZE', 2048);
     39        define('PCLZIP_READ_BLOCK_SIZE', 2048);
    4040}
    4141
     
    5151// Recommanded values for smart separation of filenames.
    5252if (!defined('PCLZIP_SEPARATOR')) {
    53   define('PCLZIP_SEPARATOR', ',');
     53        define('PCLZIP_SEPARATOR', ',');
    5454}
    5555
     
    6060// [2,...] : reserved for futur use
    6161if (!defined('PCLZIP_ERROR_EXTERNAL')) {
    62   define('PCLZIP_ERROR_EXTERNAL', 0);
     62        define('PCLZIP_ERROR_EXTERNAL', 0);
    6363}
    6464
     
    7373// define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
    7474if (!defined('PCLZIP_TEMPORARY_DIR')) {
    75   define('PCLZIP_TEMPORARY_DIR', '');
     75        define('PCLZIP_TEMPORARY_DIR', '');
    7676}
    7777
     
    8585// define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 );
    8686if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) {
    87   define('PCLZIP_TEMPORARY_FILE_RATIO', 0.47);
     87        define('PCLZIP_TEMPORARY_FILE_RATIO', 0.47);
    8888}
    8989
     
    198198// --------------------------------------------------------------------------------
    199199class PclZip {
    200   // ----- Filename of the zip file
    201   public $zipname = '';
    202 
    203   // ----- File descriptor of the zip file
    204   public $zip_fd = 0;
    205 
    206   // ----- Internal error handling
    207   public $error_code = 1;
    208   public $error_string = '';
    209 
    210   // ----- Current status of the magic_quotes_runtime
    211   // This value store the php configuration for magic_quotes
    212   // The class can then disable the magic_quotes and reset it after
    213   public $magic_quotes_status;
    214 
    215   // --------------------------------------------------------------------------------
    216   // Function : PclZip()
    217   // Description :
    218   //   Creates a PclZip object and set the name of the associated Zip archive
    219   //   filename.
    220   //   Note that no real action is taken, if the archive does not exist it is not
    221   //   created. Use create() for that.
    222   // --------------------------------------------------------------------------------
    223   public function __construct($p_zipname) {
    224 
    225     // ----- Tests the zlib
    226     if (!function_exists('gzopen')) {
    227       die('Abort ' . basename(__FILE__) . ' : Missing zlib extensions');
    228     }
    229 
    230     // ----- Set the attributes
    231     $this->zipname = $p_zipname;
    232     $this->zip_fd = 0;
    233     $this->magic_quotes_status = -1;
    234 
    235     // ----- Return
    236     return;
    237   }
    238   // --------------------------------------------------------------------------------
    239 
    240   // --------------------------------------------------------------------------------
    241   // Function :
    242   //   create($p_filelist, $p_add_dir="", $p_remove_dir="")
    243   //   create($p_filelist, $p_option, $p_option_value, ...)
    244   // Description :
    245   //   This method supports two different synopsis. The first one is historical.
    246   //   This method creates a Zip Archive. The Zip file is created in the
    247   //   filesystem. The files and directories indicated in $p_filelist
    248   //   are added in the archive. See the parameters description for the
    249   //   supported format of $p_filelist.
    250   //   When a directory is in the list, the directory and its content is added
    251   //   in the archive.
    252   //   In this synopsis, the function takes an optional variable list of
    253   //   options. See bellow the supported options.
    254   // Parameters :
    255   //   $p_filelist : An array containing file or directory names, or
    256   //                 a string containing one filename or one directory name, or
    257   //                 a string containing a list of filenames and/or directory
    258   //                 names separated by spaces.
    259   //   $p_add_dir : A path to add before the real path of the archived file,
    260   //                in order to have it memorized in the archive.
    261   //   $p_remove_dir : A path to remove from the real path of the file to archive,
    262   //                   in order to have a shorter path memorized in the archive.
    263   //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
    264   //                   is removed first, before $p_add_dir is added.
    265   // Options :
    266   //   PCLZIP_OPT_ADD_PATH :
    267   //   PCLZIP_OPT_REMOVE_PATH :
    268   //   PCLZIP_OPT_REMOVE_ALL_PATH :
    269   //   PCLZIP_OPT_COMMENT :
    270   //   PCLZIP_CB_PRE_ADD :
    271   //   PCLZIP_CB_POST_ADD :
    272   // Return Values :
    273   //   0 on failure,
    274   //   The list of the added files, with a status of the add action.
    275   //   (see PclZip::listContent() for list entry format)
    276   // --------------------------------------------------------------------------------
    277   public function create($p_filelist) {
    278     $v_result = 1;
    279 
    280     // ----- Reset the error handler
    281     $this->privErrorReset();
    282 
    283     // ----- Set default values
    284     $v_options = array();
    285     $v_options[PCLZIP_OPT_NO_COMPRESSION] = false;
    286 
    287     // ----- Look for variable options arguments
    288     $v_size = func_num_args();
    289 
    290     // ----- Look for arguments
    291     if ($v_size > 1) {
    292       // ----- Get the arguments
    293       $v_arg_list = func_get_args();
    294 
    295       // ----- Remove from the options list the first argument
    296       array_shift($v_arg_list);
    297       $v_size--;
    298 
    299       // ----- Look for first arg
    300       if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
    301 
    302         // ----- Parse the options
    303         $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
    304             array(
    305                 PCLZIP_OPT_REMOVE_PATH => 'optional',
    306                 PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
    307                 PCLZIP_OPT_ADD_PATH => 'optional',
    308                 PCLZIP_CB_PRE_ADD => 'optional',
    309                 PCLZIP_CB_POST_ADD => 'optional',
    310                 PCLZIP_OPT_NO_COMPRESSION => 'optional',
    311                 PCLZIP_OPT_COMMENT => 'optional',
    312                 PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
    313                 PCLZIP_OPT_TEMP_FILE_ON => 'optional',
    314                 PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
    315               //, PCLZIP_OPT_CRYPT => 'optional'
    316             ));
    317         if ($v_result != 1) {
    318           return 0;
    319         }
    320       }
    321 
    322       // ----- Look for 2 args
    323       // Here we need to support the first historic synopsis of the
    324       // method.
    325       else {
    326 
    327         // ----- Get the first argument
    328         $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
    329 
    330         // ----- Look for the optional second argument
    331         if ($v_size == 2) {
    332           $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
    333         } else {
    334           if ($v_size > 2) {
    335             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    336                 "Invalid number / type of arguments");
    337 
    338             return 0;
    339           }
    340         }
    341       }
    342     }
    343 
    344     // ----- Look for default option values
    345     $this->privOptionDefaultThreshold($v_options);
    346 
    347     // ----- Init
    348     $v_string_list = array();
    349     $v_att_list = array();
    350     $v_filedescr_list = array();
    351     $p_result_list = array();
    352 
    353     // ----- Look if the $p_filelist is really an array
    354     if (is_array($p_filelist)) {
    355 
    356       // ----- Look if the first element is also an array
    357       //       This will mean that this is a file description entry
    358       if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
    359         $v_att_list = $p_filelist;
    360       } // ----- The list is a list of string names
    361       else {
    362         $v_string_list = $p_filelist;
    363       }
    364     } // ----- Look if the $p_filelist is a string
    365     else {
    366       if (is_string($p_filelist)) {
    367         // ----- Create a list from the string
    368         $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
    369       } // ----- Invalid variable type for $p_filelist
    370       else {
    371         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
    372 
    373         return 0;
    374       }
    375     }
    376 
    377     // ----- Reformat the string list
    378     if (sizeof($v_string_list) != 0) {
    379       foreach ($v_string_list as $v_string) {
    380         if ($v_string != '') {
    381           $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
    382         } else {
    383         }
    384       }
    385     }
    386 
    387     // ----- For each file in the list check the attributes
    388     $v_supported_attributes
    389         = array(
    390         PCLZIP_ATT_FILE_NAME => 'mandatory',
    391         PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional',
    392         PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional',
    393         PCLZIP_ATT_FILE_MTIME => 'optional',
    394         PCLZIP_ATT_FILE_CONTENT => 'optional',
    395         PCLZIP_ATT_FILE_COMMENT => 'optional'
    396     );
    397     foreach ($v_att_list as $v_entry) {
    398       $v_result = $this->privFileDescrParseAtt($v_entry,
    399           $v_filedescr_list[],
    400           $v_options,
    401           $v_supported_attributes);
    402       if ($v_result != 1) {
    403         return 0;
    404       }
    405     }
    406 
    407     // ----- Expand the filelist (expand directories)
    408     $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
    409     if ($v_result != 1) {
    410       return 0;
    411     }
    412 
    413     // ----- Call the create fct
    414     $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
    415     if ($v_result != 1) {
    416       return 0;
    417     }
    418 
    419     // ----- Return
    420     return $p_result_list;
    421   }
    422   // --------------------------------------------------------------------------------
    423 
    424   // --------------------------------------------------------------------------------
    425   // Function :
    426   //   add($p_filelist, $p_add_dir="", $p_remove_dir="")
    427   //   add($p_filelist, $p_option, $p_option_value, ...)
    428   // Description :
    429   //   This method supports two synopsis. The first one is historical.
    430   //   This methods add the list of files in an existing archive.
    431   //   If a file with the same name already exists, it is added at the end of the
    432   //   archive, the first one is still present.
    433   //   If the archive does not exist, it is created.
    434   // Parameters :
    435   //   $p_filelist : An array containing file or directory names, or
    436   //                 a string containing one filename or one directory name, or
    437   //                 a string containing a list of filenames and/or directory
    438   //                 names separated by spaces.
    439   //   $p_add_dir : A path to add before the real path of the archived file,
    440   //                in order to have it memorized in the archive.
    441   //   $p_remove_dir : A path to remove from the real path of the file to archive,
    442   //                   in order to have a shorter path memorized in the archive.
    443   //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
    444   //                   is removed first, before $p_add_dir is added.
    445   // Options :
    446   //   PCLZIP_OPT_ADD_PATH :
    447   //   PCLZIP_OPT_REMOVE_PATH :
    448   //   PCLZIP_OPT_REMOVE_ALL_PATH :
    449   //   PCLZIP_OPT_COMMENT :
    450   //   PCLZIP_OPT_ADD_COMMENT :
    451   //   PCLZIP_OPT_PREPEND_COMMENT :
    452   //   PCLZIP_CB_PRE_ADD :
    453   //   PCLZIP_CB_POST_ADD :
    454   // Return Values :
    455   //   0 on failure,
    456   //   The list of the added files, with a status of the add action.
    457   //   (see PclZip::listContent() for list entry format)
    458   // --------------------------------------------------------------------------------
    459   public function add($p_filelist) {
    460     $v_result = 1;
    461 
    462     // ----- Reset the error handler
    463     $this->privErrorReset();
    464 
    465     // ----- Set default values
    466     $v_options = array();
    467     $v_options[PCLZIP_OPT_NO_COMPRESSION] = false;
    468 
    469     // ----- Look for variable options arguments
    470     $v_size = func_num_args();
    471 
    472     // ----- Look for arguments
    473     if ($v_size > 1) {
    474       // ----- Get the arguments
    475       $v_arg_list = func_get_args();
    476 
    477       // ----- Remove form the options list the first argument
    478       array_shift($v_arg_list);
    479       $v_size--;
    480 
    481       // ----- Look for first arg
    482       if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
    483 
    484         // ----- Parse the options
    485         $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
    486             array(
    487                 PCLZIP_OPT_REMOVE_PATH => 'optional',
    488                 PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
    489                 PCLZIP_OPT_ADD_PATH => 'optional',
    490                 PCLZIP_CB_PRE_ADD => 'optional',
    491                 PCLZIP_CB_POST_ADD => 'optional',
    492                 PCLZIP_OPT_NO_COMPRESSION => 'optional',
    493                 PCLZIP_OPT_COMMENT => 'optional',
    494                 PCLZIP_OPT_ADD_COMMENT => 'optional',
    495                 PCLZIP_OPT_PREPEND_COMMENT => 'optional',
    496                 PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
    497                 PCLZIP_OPT_TEMP_FILE_ON => 'optional',
    498                 PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
    499               //, PCLZIP_OPT_CRYPT => 'optional'
    500             ));
    501         if ($v_result != 1) {
    502           return 0;
    503         }
    504       }
    505 
    506       // ----- Look for 2 args
    507       // Here we need to support the first historic synopsis of the
    508       // method.
    509       else {
    510 
    511         // ----- Get the first argument
    512         $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
    513 
    514         // ----- Look for the optional second argument
    515         if ($v_size == 2) {
    516           $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
    517         } else {
    518           if ($v_size > 2) {
    519             // ----- Error log
    520             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
    521 
    522             // ----- Return
    523             return 0;
    524           }
    525         }
    526       }
    527     }
    528 
    529     // ----- Look for default option values
    530     $this->privOptionDefaultThreshold($v_options);
    531 
    532     // ----- Init
    533     $v_string_list = array();
    534     $v_att_list = array();
    535     $v_filedescr_list = array();
    536     $p_result_list = array();
    537 
    538     // ----- Look if the $p_filelist is really an array
    539     if (is_array($p_filelist)) {
    540 
    541       // ----- Look if the first element is also an array
    542       //       This will mean that this is a file description entry
    543       if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
    544         $v_att_list = $p_filelist;
    545       } // ----- The list is a list of string names
    546       else {
    547         $v_string_list = $p_filelist;
    548       }
    549     } // ----- Look if the $p_filelist is a string
    550     else {
    551       if (is_string($p_filelist)) {
    552         // ----- Create a list from the string
    553         $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
    554       } // ----- Invalid variable type for $p_filelist
    555       else {
    556         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    557             "Invalid variable type '" . gettype($p_filelist) . "' for p_filelist");
    558 
    559         return 0;
    560       }
    561     }
    562 
    563     // ----- Reformat the string list
    564     if (sizeof($v_string_list) != 0) {
    565       foreach ($v_string_list as $v_string) {
    566         $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
    567       }
    568     }
    569 
    570     // ----- For each file in the list check the attributes
    571     $v_supported_attributes
    572         = array(
    573         PCLZIP_ATT_FILE_NAME => 'mandatory',
    574         PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional',
    575         PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional',
    576         PCLZIP_ATT_FILE_MTIME => 'optional',
    577         PCLZIP_ATT_FILE_CONTENT => 'optional',
    578         PCLZIP_ATT_FILE_COMMENT => 'optional'
    579     );
    580     foreach ($v_att_list as $v_entry) {
    581       $v_result = $this->privFileDescrParseAtt($v_entry,
    582           $v_filedescr_list[],
    583           $v_options,
    584           $v_supported_attributes);
    585       if ($v_result != 1) {
    586         return 0;
    587       }
    588     }
    589 
    590     // ----- Expand the filelist (expand directories)
    591     $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
    592     if ($v_result != 1) {
    593       return 0;
    594     }
    595 
    596     // ----- Call the create fct
    597     $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
    598     if ($v_result != 1) {
    599       return 0;
    600     }
    601 
    602     // ----- Return
    603     return $p_result_list;
    604   }
    605   // --------------------------------------------------------------------------------
    606 
    607   // --------------------------------------------------------------------------------
    608   // Function : listContent()
    609   // Description :
    610   //   This public method, gives the list of the files and directories, with their
    611   //   properties.
    612   //   The properties of each entries in the list are (used also in other functions) :
    613   //     filename : Name of the file. For a create or add action it is the filename
    614   //                given by the user. For an extract function it is the filename
    615   //                of the extracted file.
    616   //     stored_filename : Name of the file / directory stored in the archive.
    617   //     size : Size of the stored file.
    618   //     compressed_size : Size of the file's data compressed in the archive
    619   //                       (without the headers overhead)
    620   //     mtime : Last known modification date of the file (UNIX timestamp)
    621   //     comment : Comment associated with the file
    622   //     folder : true | false
    623   //     index : index of the file in the archive
    624   //     status : status of the action (depending of the action) :
    625   //              Values are :
    626   //                ok : OK !
    627   //                filtered : the file / dir is not extracted (filtered by user)
    628   //                already_a_directory : the file can not be extracted because a
    629   //                                      directory with the same name already exists
    630   //                write_protected : the file can not be extracted because a file
    631   //                                  with the same name already exists and is
    632   //                                  write protected
    633   //                newer_exist : the file was not extracted because a newer file exists
    634   //                path_creation_fail : the file is not extracted because the folder
    635   //                                     does not exist and can not be created
    636   //                write_error : the file was not extracted because there was a
    637   //                              error while writing the file
    638   //                read_error : the file was not extracted because there was a error
    639   //                             while reading the file
    640   //                invalid_header : the file was not extracted because of an archive
    641   //                                 format error (bad file header)
    642   //   Note that each time a method can continue operating when there
    643   //   is an action error on a file, the error is only logged in the file status.
    644   // Return Values :
    645   //   0 on an unrecoverable failure,
    646   //   The list of the files in the archive.
    647   // --------------------------------------------------------------------------------
    648   public function listContent() {
    649     $v_result = 1;
    650 
    651     // ----- Reset the error handler
    652     $this->privErrorReset();
    653 
    654     // ----- Check archive
    655     if (!$this->privCheckFormat()) {
    656       return (0);
    657     }
    658 
    659     // ----- Call the extracting fct
    660     $p_list = array();
    661     if (($v_result = $this->privList($p_list)) != 1) {
    662       unset($p_list);
    663 
    664       return (0);
    665     }
    666 
    667     // ----- Return
    668     return $p_list;
    669   }
    670   // --------------------------------------------------------------------------------
    671 
    672   // --------------------------------------------------------------------------------
    673   // Function :
    674   //   extract($p_path="./", $p_remove_path="")
    675   //   extract([$p_option, $p_option_value, ...])
    676   // Description :
    677   //   This method supports two synopsis. The first one is historical.
    678   //   This method extract all the files / directories from the archive to the
    679   //   folder indicated in $p_path.
    680   //   If you want to ignore the 'root' part of path of the memorized files
    681   //   you can indicate this in the optional $p_remove_path parameter.
    682   //   By default, if a newer file with the same name already exists, the
    683   //   file is not extracted.
    684   //
    685   //   If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
    686   //   are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
    687   //   at the end of the path value of PCLZIP_OPT_PATH.
    688   // Parameters :
    689   //   $p_path : Path where the files and directories are to be extracted
    690   //   $p_remove_path : First part ('root' part) of the memorized path
    691   //                    (if any similar) to remove while extracting.
    692   // Options :
    693   //   PCLZIP_OPT_PATH :
    694   //   PCLZIP_OPT_ADD_PATH :
    695   //   PCLZIP_OPT_REMOVE_PATH :
    696   //   PCLZIP_OPT_REMOVE_ALL_PATH :
    697   //   PCLZIP_CB_PRE_EXTRACT :
    698   //   PCLZIP_CB_POST_EXTRACT :
    699   // Return Values :
    700   //   0 or a negative value on failure,
    701   //   The list of the extracted files, with a status of the action.
    702   //   (see PclZip::listContent() for list entry format)
    703   // --------------------------------------------------------------------------------
    704   public function extract() {
    705     $v_result = 1;
    706 
    707     // ----- Reset the error handler
    708     $this->privErrorReset();
    709 
    710     // ----- Check archive
    711     if (!$this->privCheckFormat()) {
    712       return (0);
    713     }
    714 
    715     // ----- Set default values
    716     $v_options = array();
     200        // ----- Filename of the zip file
     201        public $zipname = '';
     202
     203        // ----- File descriptor of the zip file
     204        public $zip_fd = 0;
     205
     206        // ----- Internal error handling
     207        public $error_code = 1;
     208        public $error_string = '';
     209
     210        // ----- Current status of the magic_quotes_runtime
     211        // This value store the php configuration for magic_quotes
     212        // The class can then disable the magic_quotes and reset it after
     213        public $magic_quotes_status;
     214
     215        // --------------------------------------------------------------------------------
     216        // Function : PclZip()
     217        // Description :
     218        //   Creates a PclZip object and set the name of the associated Zip archive
     219        //   filename.
     220        //   Note that no real action is taken, if the archive does not exist it is not
     221        //   created. Use create() for that.
     222        // --------------------------------------------------------------------------------
     223        public function __construct($p_zipname) {
     224
     225                // ----- Tests the zlib
     226                if (!function_exists('gzopen')) {
     227                        die('Abort ' . basename(__FILE__) . ' : Missing zlib extensions');
     228                }
     229
     230                // ----- Set the attributes
     231                $this->zipname = $p_zipname;
     232                $this->zip_fd = 0;
     233                $this->magic_quotes_status = -1;
     234
     235                // ----- Return
     236                return;
     237        }
     238        // --------------------------------------------------------------------------------
     239
     240        // --------------------------------------------------------------------------------
     241        // Function :
     242        //   create($p_filelist, $p_add_dir="", $p_remove_dir="")
     243        //   create($p_filelist, $p_option, $p_option_value, ...)
     244        // Description :
     245        //   This method supports two different synopsis. The first one is historical.
     246        //   This method creates a Zip Archive. The Zip file is created in the
     247        //   filesystem. The files and directories indicated in $p_filelist
     248        //   are added in the archive. See the parameters description for the
     249        //   supported format of $p_filelist.
     250        //   When a directory is in the list, the directory and its content is added
     251        //   in the archive.
     252        //   In this synopsis, the function takes an optional variable list of
     253        //   options. See bellow the supported options.
     254        // Parameters :
     255        //   $p_filelist : An array containing file or directory names, or
     256        //                 a string containing one filename or one directory name, or
     257        //                 a string containing a list of filenames and/or directory
     258        //                 names separated by spaces.
     259        //   $p_add_dir : A path to add before the real path of the archived file,
     260        //                in order to have it memorized in the archive.
     261        //   $p_remove_dir : A path to remove from the real path of the file to archive,
     262        //                   in order to have a shorter path memorized in the archive.
     263        //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
     264        //                   is removed first, before $p_add_dir is added.
     265        // Options :
     266        //   PCLZIP_OPT_ADD_PATH :
     267        //   PCLZIP_OPT_REMOVE_PATH :
     268        //   PCLZIP_OPT_REMOVE_ALL_PATH :
     269        //   PCLZIP_OPT_COMMENT :
     270        //   PCLZIP_CB_PRE_ADD :
     271        //   PCLZIP_CB_POST_ADD :
     272        // Return Values :
     273        //   0 on failure,
     274        //   The list of the added files, with a status of the add action.
     275        //   (see PclZip::listContent() for list entry format)
     276        // --------------------------------------------------------------------------------
     277        public function create($p_filelist) {
     278                $v_result = 1;
     279
     280                // ----- Reset the error handler
     281                $this->privErrorReset();
     282
     283                // ----- Set default values
     284                $v_options = array();
     285                $v_options[PCLZIP_OPT_NO_COMPRESSION] = false;
     286
     287                // ----- Look for variable options arguments
     288                $v_size = func_num_args();
     289
     290                // ----- Look for arguments
     291                if ($v_size > 1) {
     292                        // ----- Get the arguments
     293                        $v_arg_list = func_get_args();
     294
     295                        // ----- Remove from the options list the first argument
     296                        array_shift($v_arg_list);
     297                        $v_size--;
     298
     299                        // ----- Look for first arg
     300                        if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
     301
     302                                // ----- Parse the options
     303                                $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
     304                                        array(
     305                                                PCLZIP_OPT_REMOVE_PATH => 'optional',
     306                                                PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
     307                                                PCLZIP_OPT_ADD_PATH => 'optional',
     308                                                PCLZIP_CB_PRE_ADD => 'optional',
     309                                                PCLZIP_CB_POST_ADD => 'optional',
     310                                                PCLZIP_OPT_NO_COMPRESSION => 'optional',
     311                                                PCLZIP_OPT_COMMENT => 'optional',
     312                                                PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
     313                                                PCLZIP_OPT_TEMP_FILE_ON => 'optional',
     314                                                PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
     315                                                //, PCLZIP_OPT_CRYPT => 'optional'
     316                                        ));
     317                                if ($v_result != 1) {
     318                                        return 0;
     319                                }
     320                        }
     321
     322                        // ----- Look for 2 args
     323                        // Here we need to support the first historic synopsis of the
     324                        // method.
     325                        else {
     326
     327                                // ----- Get the first argument
     328                                $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
     329
     330                                // ----- Look for the optional second argument
     331                                if ($v_size == 2) {
     332                                        $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
     333                                } else {
     334                                        if ($v_size > 2) {
     335                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     336                                                        "Invalid number / type of arguments");
     337
     338                                                return 0;
     339                                        }
     340                                }
     341                        }
     342                }
     343
     344                // ----- Look for default option values
     345                $this->privOptionDefaultThreshold($v_options);
     346
     347                // ----- Init
     348                $v_string_list = array();
     349                $v_att_list = array();
     350                $v_filedescr_list = array();
     351                $p_result_list = array();
     352
     353                // ----- Look if the $p_filelist is really an array
     354                if (is_array($p_filelist)) {
     355
     356                        // ----- Look if the first element is also an array
     357                        //       This will mean that this is a file description entry
     358                        if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
     359                                $v_att_list = $p_filelist;
     360                        } // ----- The list is a list of string names
     361                        else {
     362                                $v_string_list = $p_filelist;
     363                        }
     364                } // ----- Look if the $p_filelist is a string
     365                else {
     366                        if (is_string($p_filelist)) {
     367                                // ----- Create a list from the string
     368                                $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
     369                        } // ----- Invalid variable type for $p_filelist
     370                        else {
     371                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
     372
     373                                return 0;
     374                        }
     375                }
     376
     377                // ----- Reformat the string list
     378                if (sizeof($v_string_list) != 0) {
     379                        foreach ($v_string_list as $v_string) {
     380                                if ($v_string != '') {
     381                                        $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
     382                                } else {
     383                                }
     384                        }
     385                }
     386
     387                // ----- For each file in the list check the attributes
     388                $v_supported_attributes
     389                        = array(
     390                        PCLZIP_ATT_FILE_NAME => 'mandatory',
     391                        PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional',
     392                        PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional',
     393                        PCLZIP_ATT_FILE_MTIME => 'optional',
     394                        PCLZIP_ATT_FILE_CONTENT => 'optional',
     395                        PCLZIP_ATT_FILE_COMMENT => 'optional'
     396                );
     397                foreach ($v_att_list as $v_entry) {
     398                        $v_result = $this->privFileDescrParseAtt($v_entry,
     399                                $v_filedescr_list[],
     400                                $v_options,
     401                                $v_supported_attributes);
     402                        if ($v_result != 1) {
     403                                return 0;
     404                        }
     405                }
     406
     407                // ----- Expand the filelist (expand directories)
     408                $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
     409                if ($v_result != 1) {
     410                        return 0;
     411                }
     412
     413                // ----- Call the create fct
     414                $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
     415                if ($v_result != 1) {
     416                        return 0;
     417                }
     418
     419                // ----- Return
     420                return $p_result_list;
     421        }
     422        // --------------------------------------------------------------------------------
     423
     424        // --------------------------------------------------------------------------------
     425        // Function :
     426        //   add($p_filelist, $p_add_dir="", $p_remove_dir="")
     427        //   add($p_filelist, $p_option, $p_option_value, ...)
     428        // Description :
     429        //   This method supports two synopsis. The first one is historical.
     430        //   This methods add the list of files in an existing archive.
     431        //   If a file with the same name already exists, it is added at the end of the
     432        //   archive, the first one is still present.
     433        //   If the archive does not exist, it is created.
     434        // Parameters :
     435        //   $p_filelist : An array containing file or directory names, or
     436        //                 a string containing one filename or one directory name, or
     437        //                 a string containing a list of filenames and/or directory
     438        //                 names separated by spaces.
     439        //   $p_add_dir : A path to add before the real path of the archived file,
     440        //                in order to have it memorized in the archive.
     441        //   $p_remove_dir : A path to remove from the real path of the file to archive,
     442        //                   in order to have a shorter path memorized in the archive.
     443        //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
     444        //                   is removed first, before $p_add_dir is added.
     445        // Options :
     446        //   PCLZIP_OPT_ADD_PATH :
     447        //   PCLZIP_OPT_REMOVE_PATH :
     448        //   PCLZIP_OPT_REMOVE_ALL_PATH :
     449        //   PCLZIP_OPT_COMMENT :
     450        //   PCLZIP_OPT_ADD_COMMENT :
     451        //   PCLZIP_OPT_PREPEND_COMMENT :
     452        //   PCLZIP_CB_PRE_ADD :
     453        //   PCLZIP_CB_POST_ADD :
     454        // Return Values :
     455        //   0 on failure,
     456        //   The list of the added files, with a status of the add action.
     457        //   (see PclZip::listContent() for list entry format)
     458        // --------------------------------------------------------------------------------
     459        public function add($p_filelist) {
     460                $v_result = 1;
     461
     462                // ----- Reset the error handler
     463                $this->privErrorReset();
     464
     465                // ----- Set default values
     466                $v_options = array();
     467                $v_options[PCLZIP_OPT_NO_COMPRESSION] = false;
     468
     469                // ----- Look for variable options arguments
     470                $v_size = func_num_args();
     471
     472                // ----- Look for arguments
     473                if ($v_size > 1) {
     474                        // ----- Get the arguments
     475                        $v_arg_list = func_get_args();
     476
     477                        // ----- Remove form the options list the first argument
     478                        array_shift($v_arg_list);
     479                        $v_size--;
     480
     481                        // ----- Look for first arg
     482                        if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
     483
     484                                // ----- Parse the options
     485                                $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
     486                                        array(
     487                                                PCLZIP_OPT_REMOVE_PATH => 'optional',
     488                                                PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
     489                                                PCLZIP_OPT_ADD_PATH => 'optional',
     490                                                PCLZIP_CB_PRE_ADD => 'optional',
     491                                                PCLZIP_CB_POST_ADD => 'optional',
     492                                                PCLZIP_OPT_NO_COMPRESSION => 'optional',
     493                                                PCLZIP_OPT_COMMENT => 'optional',
     494                                                PCLZIP_OPT_ADD_COMMENT => 'optional',
     495                                                PCLZIP_OPT_PREPEND_COMMENT => 'optional',
     496                                                PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
     497                                                PCLZIP_OPT_TEMP_FILE_ON => 'optional',
     498                                                PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
     499                                                //, PCLZIP_OPT_CRYPT => 'optional'
     500                                        ));
     501                                if ($v_result != 1) {
     502                                        return 0;
     503                                }
     504                        }
     505
     506                        // ----- Look for 2 args
     507                        // Here we need to support the first historic synopsis of the
     508                        // method.
     509                        else {
     510
     511                                // ----- Get the first argument
     512                                $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
     513
     514                                // ----- Look for the optional second argument
     515                                if ($v_size == 2) {
     516                                        $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
     517                                } else {
     518                                        if ($v_size > 2) {
     519                                                // ----- Error log
     520                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
     521
     522                                                // ----- Return
     523                                                return 0;
     524                                        }
     525                                }
     526                        }
     527                }
     528
     529                // ----- Look for default option values
     530                $this->privOptionDefaultThreshold($v_options);
     531
     532                // ----- Init
     533                $v_string_list = array();
     534                $v_att_list = array();
     535                $v_filedescr_list = array();
     536                $p_result_list = array();
     537
     538                // ----- Look if the $p_filelist is really an array
     539                if (is_array($p_filelist)) {
     540
     541                        // ----- Look if the first element is also an array
     542                        //       This will mean that this is a file description entry
     543                        if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
     544                                $v_att_list = $p_filelist;
     545                        } // ----- The list is a list of string names
     546                        else {
     547                                $v_string_list = $p_filelist;
     548                        }
     549                } // ----- Look if the $p_filelist is a string
     550                else {
     551                        if (is_string($p_filelist)) {
     552                                // ----- Create a list from the string
     553                                $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
     554                        } // ----- Invalid variable type for $p_filelist
     555                        else {
     556                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     557                                        "Invalid variable type '" . gettype($p_filelist) . "' for p_filelist");
     558
     559                                return 0;
     560                        }
     561                }
     562
     563                // ----- Reformat the string list
     564                if (sizeof($v_string_list) != 0) {
     565                        foreach ($v_string_list as $v_string) {
     566                                $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
     567                        }
     568                }
     569
     570                // ----- For each file in the list check the attributes
     571                $v_supported_attributes
     572                        = array(
     573                        PCLZIP_ATT_FILE_NAME => 'mandatory',
     574                        PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional',
     575                        PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional',
     576                        PCLZIP_ATT_FILE_MTIME => 'optional',
     577                        PCLZIP_ATT_FILE_CONTENT => 'optional',
     578                        PCLZIP_ATT_FILE_COMMENT => 'optional'
     579                );
     580                foreach ($v_att_list as $v_entry) {
     581                        $v_result = $this->privFileDescrParseAtt($v_entry,
     582                                $v_filedescr_list[],
     583                                $v_options,
     584                                $v_supported_attributes);
     585                        if ($v_result != 1) {
     586                                return 0;
     587                        }
     588                }
     589
     590                // ----- Expand the filelist (expand directories)
     591                $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
     592                if ($v_result != 1) {
     593                        return 0;
     594                }
     595
     596                // ----- Call the create fct
     597                $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
     598                if ($v_result != 1) {
     599                        return 0;
     600                }
     601
     602                // ----- Return
     603                return $p_result_list;
     604        }
     605        // --------------------------------------------------------------------------------
     606
     607        // --------------------------------------------------------------------------------
     608        // Function : listContent()
     609        // Description :
     610        //   This public method, gives the list of the files and directories, with their
     611        //   properties.
     612        //   The properties of each entries in the list are (used also in other functions) :
     613        //     filename : Name of the file. For a create or add action it is the filename
     614        //                given by the user. For an extract function it is the filename
     615        //                of the extracted file.
     616        //     stored_filename : Name of the file / directory stored in the archive.
     617        //     size : Size of the stored file.
     618        //     compressed_size : Size of the file's data compressed in the archive
     619        //                       (without the headers overhead)
     620        //     mtime : Last known modification date of the file (UNIX timestamp)
     621        //     comment : Comment associated with the file
     622        //     folder : true | false
     623        //     index : index of the file in the archive
     624        //     status : status of the action (depending of the action) :
     625        //              Values are :
     626        //                ok : OK !
     627        //                filtered : the file / dir is not extracted (filtered by user)
     628        //                already_a_directory : the file can not be extracted because a
     629        //                                      directory with the same name already exists
     630        //                write_protected : the file can not be extracted because a file
     631        //                                  with the same name already exists and is
     632        //                                  write protected
     633        //                newer_exist : the file was not extracted because a newer file exists
     634        //                path_creation_fail : the file is not extracted because the folder
     635        //                                     does not exist and can not be created
     636        //                write_error : the file was not extracted because there was a
     637        //                              error while writing the file
     638        //                read_error : the file was not extracted because there was a error
     639        //                             while reading the file
     640        //                invalid_header : the file was not extracted because of an archive
     641        //                                 format error (bad file header)
     642        //   Note that each time a method can continue operating when there
     643        //   is an action error on a file, the error is only logged in the file status.
     644        // Return Values :
     645        //   0 on an unrecoverable failure,
     646        //   The list of the files in the archive.
     647        // --------------------------------------------------------------------------------
     648        public function listContent() {
     649                $v_result = 1;
     650
     651                // ----- Reset the error handler
     652                $this->privErrorReset();
     653
     654                // ----- Check archive
     655                if (!$this->privCheckFormat()) {
     656                        return (0);
     657                }
     658
     659                // ----- Call the extracting fct
     660                $p_list = array();
     661                if (($v_result = $this->privList($p_list)) != 1) {
     662                        unset($p_list);
     663
     664                        return (0);
     665                }
     666
     667                // ----- Return
     668                return $p_list;
     669        }
     670        // --------------------------------------------------------------------------------
     671
     672        // --------------------------------------------------------------------------------
     673        // Function :
     674        //   extract($p_path="./", $p_remove_path="")
     675        //   extract([$p_option, $p_option_value, ...])
     676        // Description :
     677        //   This method supports two synopsis. The first one is historical.
     678        //   This method extract all the files / directories from the archive to the
     679        //   folder indicated in $p_path.
     680        //   If you want to ignore the 'root' part of path of the memorized files
     681        //   you can indicate this in the optional $p_remove_path parameter.
     682        //   By default, if a newer file with the same name already exists, the
     683        //   file is not extracted.
     684        //
     685        //   If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
     686        //   are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
     687        //   at the end of the path value of PCLZIP_OPT_PATH.
     688        // Parameters :
     689        //   $p_path : Path where the files and directories are to be extracted
     690        //   $p_remove_path : First part ('root' part) of the memorized path
     691        //                    (if any similar) to remove while extracting.
     692        // Options :
     693        //   PCLZIP_OPT_PATH :
     694        //   PCLZIP_OPT_ADD_PATH :
     695        //   PCLZIP_OPT_REMOVE_PATH :
     696        //   PCLZIP_OPT_REMOVE_ALL_PATH :
     697        //   PCLZIP_CB_PRE_EXTRACT :
     698        //   PCLZIP_CB_POST_EXTRACT :
     699        // Return Values :
     700        //   0 or a negative value on failure,
     701        //   The list of the extracted files, with a status of the action.
     702        //   (see PclZip::listContent() for list entry format)
     703        // --------------------------------------------------------------------------------
     704        public function extract() {
     705                $v_result = 1;
     706
     707                // ----- Reset the error handler
     708                $this->privErrorReset();
     709
     710                // ----- Check archive
     711                if (!$this->privCheckFormat()) {
     712                        return (0);
     713                }
     714
     715                // ----- Set default values
     716                $v_options = array();
    717717//    $v_path = "./";
    718     $v_path = '';
    719     $v_remove_path = "";
    720     $v_remove_all_path = false;
    721 
    722     // ----- Look for variable options arguments
    723     $v_size = func_num_args();
    724 
    725     // ----- Default values for option
    726     $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
    727 
    728     // ----- Look for arguments
    729     if ($v_size > 0) {
    730       // ----- Get the arguments
    731       $v_arg_list = func_get_args();
    732 
    733       // ----- Look for first arg
    734       if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
    735 
    736         // ----- Parse the options
    737         $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
    738             array(
    739                 PCLZIP_OPT_PATH => 'optional',
    740                 PCLZIP_OPT_REMOVE_PATH => 'optional',
    741                 PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
    742                 PCLZIP_OPT_ADD_PATH => 'optional',
    743                 PCLZIP_CB_PRE_EXTRACT => 'optional',
    744                 PCLZIP_CB_POST_EXTRACT => 'optional',
    745                 PCLZIP_OPT_SET_CHMOD => 'optional',
    746                 PCLZIP_OPT_BY_NAME => 'optional',
    747                 PCLZIP_OPT_BY_EREG => 'optional',
    748                 PCLZIP_OPT_BY_PREG => 'optional',
    749                 PCLZIP_OPT_BY_INDEX => 'optional',
    750                 PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
    751                 PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
    752                 PCLZIP_OPT_REPLACE_NEWER => 'optional',
    753                 PCLZIP_OPT_STOP_ON_ERROR => 'optional',
    754                 PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
    755                 PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
    756                 PCLZIP_OPT_TEMP_FILE_ON => 'optional',
    757                 PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
    758             ));
    759         if ($v_result != 1) {
    760           return 0;
    761         }
    762 
    763         // ----- Set the arguments
    764         if (isset($v_options[PCLZIP_OPT_PATH])) {
    765           $v_path = $v_options[PCLZIP_OPT_PATH];
    766         }
    767         if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
    768           $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
    769         }
    770         if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
    771           $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
    772         }
    773         if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
    774           // ----- Check for '/' in last path char
    775           if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
    776             $v_path .= '/';
    777           }
    778           $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
    779         }
    780       }
    781 
    782       // ----- Look for 2 args
    783       // Here we need to support the first historic synopsis of the
    784       // method.
    785       else {
    786 
    787         // ----- Get the first argument
    788         $v_path = $v_arg_list[0];
    789 
    790         // ----- Look for the optional second argument
    791         if ($v_size == 2) {
    792           $v_remove_path = $v_arg_list[1];
    793         } else {
    794           if ($v_size > 2) {
    795             // ----- Error log
    796             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
    797 
    798             // ----- Return
    799             return 0;
    800           }
    801         }
    802       }
    803     }
    804 
    805     // ----- Look for default option values
    806     $this->privOptionDefaultThreshold($v_options);
    807 
    808     // ----- Trace
    809 
    810     // ----- Call the extracting fct
    811     $p_list = array();
    812     $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
    813         $v_remove_all_path, $v_options);
    814     if ($v_result < 1) {
    815       unset($p_list);
    816 
    817       return (0);
    818     }
    819 
    820     // ----- Return
    821     return $p_list;
    822   }
    823   // --------------------------------------------------------------------------------
    824 
    825 
    826   // --------------------------------------------------------------------------------
    827   // Function :
    828   //   extractByIndex($p_index, $p_path="./", $p_remove_path="")
    829   //   extractByIndex($p_index, [$p_option, $p_option_value, ...])
    830   // Description :
    831   //   This method supports two synopsis. The first one is historical.
    832   //   This method is doing a partial extract of the archive.
    833   //   The extracted files or folders are identified by their index in the
    834   //   archive (from 0 to n).
    835   //   Note that if the index identify a folder, only the folder entry is
    836   //   extracted, not all the files included in the archive.
    837   // Parameters :
    838   //   $p_index : A single index (integer) or a string of indexes of files to
    839   //              extract. The form of the string is "0,4-6,8-12" with only numbers
    840   //              and '-' for range or ',' to separate ranges. No spaces or ';'
    841   //              are allowed.
    842   //   $p_path : Path where the files and directories are to be extracted
    843   //   $p_remove_path : First part ('root' part) of the memorized path
    844   //                    (if any similar) to remove while extracting.
    845   // Options :
    846   //   PCLZIP_OPT_PATH :
    847   //   PCLZIP_OPT_ADD_PATH :
    848   //   PCLZIP_OPT_REMOVE_PATH :
    849   //   PCLZIP_OPT_REMOVE_ALL_PATH :
    850   //   PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
    851   //     not as files.
    852   //     The resulting content is in a new field 'content' in the file
    853   //     structure.
    854   //     This option must be used alone (any other options are ignored).
    855   //   PCLZIP_CB_PRE_EXTRACT :
    856   //   PCLZIP_CB_POST_EXTRACT :
    857   // Return Values :
    858   //   0 on failure,
    859   //   The list of the extracted files, with a status of the action.
    860   //   (see PclZip::listContent() for list entry format)
    861   // --------------------------------------------------------------------------------
    862   //function extractByIndex($p_index, options...)
    863   public function extractByIndex($p_index) {
    864     $v_result = 1;
    865 
    866     // ----- Reset the error handler
    867     $this->privErrorReset();
    868 
    869     // ----- Check archive
    870     if (!$this->privCheckFormat()) {
    871       return (0);
    872     }
    873 
    874     // ----- Set default values
    875     $v_options = array();
     718                $v_path = '';
     719                $v_remove_path = "";
     720                $v_remove_all_path = false;
     721
     722                // ----- Look for variable options arguments
     723                $v_size = func_num_args();
     724
     725                // ----- Default values for option
     726                $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
     727
     728                // ----- Look for arguments
     729                if ($v_size > 0) {
     730                        // ----- Get the arguments
     731                        $v_arg_list = func_get_args();
     732
     733                        // ----- Look for first arg
     734                        if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
     735
     736                                // ----- Parse the options
     737                                $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
     738                                        array(
     739                                                PCLZIP_OPT_PATH => 'optional',
     740                                                PCLZIP_OPT_REMOVE_PATH => 'optional',
     741                                                PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
     742                                                PCLZIP_OPT_ADD_PATH => 'optional',
     743                                                PCLZIP_CB_PRE_EXTRACT => 'optional',
     744                                                PCLZIP_CB_POST_EXTRACT => 'optional',
     745                                                PCLZIP_OPT_SET_CHMOD => 'optional',
     746                                                PCLZIP_OPT_BY_NAME => 'optional',
     747                                                PCLZIP_OPT_BY_EREG => 'optional',
     748                                                PCLZIP_OPT_BY_PREG => 'optional',
     749                                                PCLZIP_OPT_BY_INDEX => 'optional',
     750                                                PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
     751                                                PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
     752                                                PCLZIP_OPT_REPLACE_NEWER => 'optional',
     753                                                PCLZIP_OPT_STOP_ON_ERROR => 'optional',
     754                                                PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
     755                                                PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
     756                                                PCLZIP_OPT_TEMP_FILE_ON => 'optional',
     757                                                PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
     758                                        ));
     759                                if ($v_result != 1) {
     760                                        return 0;
     761                                }
     762
     763                                // ----- Set the arguments
     764                                if (isset($v_options[PCLZIP_OPT_PATH])) {
     765                                        $v_path = $v_options[PCLZIP_OPT_PATH];
     766                                }
     767                                if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
     768                                        $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
     769                                }
     770                                if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
     771                                        $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
     772                                }
     773                                if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
     774                                        // ----- Check for '/' in last path char
     775                                        if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
     776                                                $v_path .= '/';
     777                                        }
     778                                        $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
     779                                }
     780                        }
     781
     782                        // ----- Look for 2 args
     783                        // Here we need to support the first historic synopsis of the
     784                        // method.
     785                        else {
     786
     787                                // ----- Get the first argument
     788                                $v_path = $v_arg_list[0];
     789
     790                                // ----- Look for the optional second argument
     791                                if ($v_size == 2) {
     792                                        $v_remove_path = $v_arg_list[1];
     793                                } else {
     794                                        if ($v_size > 2) {
     795                                                // ----- Error log
     796                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
     797
     798                                                // ----- Return
     799                                                return 0;
     800                                        }
     801                                }
     802                        }
     803                }
     804
     805                // ----- Look for default option values
     806                $this->privOptionDefaultThreshold($v_options);
     807
     808                // ----- Trace
     809
     810                // ----- Call the extracting fct
     811                $p_list = array();
     812                $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
     813                        $v_remove_all_path, $v_options);
     814                if ($v_result < 1) {
     815                        unset($p_list);
     816
     817                        return (0);
     818                }
     819
     820                // ----- Return
     821                return $p_list;
     822        }
     823        // --------------------------------------------------------------------------------
     824
     825
     826        // --------------------------------------------------------------------------------
     827        // Function :
     828        //   extractByIndex($p_index, $p_path="./", $p_remove_path="")
     829        //   extractByIndex($p_index, [$p_option, $p_option_value, ...])
     830        // Description :
     831        //   This method supports two synopsis. The first one is historical.
     832        //   This method is doing a partial extract of the archive.
     833        //   The extracted files or folders are identified by their index in the
     834        //   archive (from 0 to n).
     835        //   Note that if the index identify a folder, only the folder entry is
     836        //   extracted, not all the files included in the archive.
     837        // Parameters :
     838        //   $p_index : A single index (integer) or a string of indexes of files to
     839        //              extract. The form of the string is "0,4-6,8-12" with only numbers
     840        //              and '-' for range or ',' to separate ranges. No spaces or ';'
     841        //              are allowed.
     842        //   $p_path : Path where the files and directories are to be extracted
     843        //   $p_remove_path : First part ('root' part) of the memorized path
     844        //                    (if any similar) to remove while extracting.
     845        // Options :
     846        //   PCLZIP_OPT_PATH :
     847        //   PCLZIP_OPT_ADD_PATH :
     848        //   PCLZIP_OPT_REMOVE_PATH :
     849        //   PCLZIP_OPT_REMOVE_ALL_PATH :
     850        //   PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
     851        //     not as files.
     852        //     The resulting content is in a new field 'content' in the file
     853        //     structure.
     854        //     This option must be used alone (any other options are ignored).
     855        //   PCLZIP_CB_PRE_EXTRACT :
     856        //   PCLZIP_CB_POST_EXTRACT :
     857        // Return Values :
     858        //   0 on failure,
     859        //   The list of the extracted files, with a status of the action.
     860        //   (see PclZip::listContent() for list entry format)
     861        // --------------------------------------------------------------------------------
     862        //function extractByIndex($p_index, options...)
     863        public function extractByIndex($p_index) {
     864                $v_result = 1;
     865
     866                // ----- Reset the error handler
     867                $this->privErrorReset();
     868
     869                // ----- Check archive
     870                if (!$this->privCheckFormat()) {
     871                        return (0);
     872                }
     873
     874                // ----- Set default values
     875                $v_options = array();
    876876//    $v_path = "./";
    877     $v_path = '';
    878     $v_remove_path = "";
    879     $v_remove_all_path = false;
    880 
    881     // ----- Look for variable options arguments
    882     $v_size = func_num_args();
    883 
    884     // ----- Default values for option
    885     $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
    886 
    887     // ----- Look for arguments
    888     if ($v_size > 1) {
    889       // ----- Get the arguments
    890       $v_arg_list = func_get_args();
    891 
    892       // ----- Remove form the options list the first argument
    893       array_shift($v_arg_list);
    894       $v_size--;
    895 
    896       // ----- Look for first arg
    897       if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
    898 
    899         // ----- Parse the options
    900         $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
    901             array(
    902                 PCLZIP_OPT_PATH => 'optional',
    903                 PCLZIP_OPT_REMOVE_PATH => 'optional',
    904                 PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
    905                 PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
    906                 PCLZIP_OPT_ADD_PATH => 'optional',
    907                 PCLZIP_CB_PRE_EXTRACT => 'optional',
    908                 PCLZIP_CB_POST_EXTRACT => 'optional',
    909                 PCLZIP_OPT_SET_CHMOD => 'optional',
    910                 PCLZIP_OPT_REPLACE_NEWER => 'optional',
    911                 PCLZIP_OPT_STOP_ON_ERROR => 'optional',
    912                 PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
    913                 PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
    914                 PCLZIP_OPT_TEMP_FILE_ON => 'optional',
    915                 PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
    916             ));
    917         if ($v_result != 1) {
    918           return 0;
    919         }
    920 
    921         // ----- Set the arguments
    922         if (isset($v_options[PCLZIP_OPT_PATH])) {
    923           $v_path = $v_options[PCLZIP_OPT_PATH];
    924         }
    925         if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
    926           $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
    927         }
    928         if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
    929           $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
    930         }
    931         if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
    932           // ----- Check for '/' in last path char
    933           if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
    934             $v_path .= '/';
    935           }
    936           $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
    937         }
    938         if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
    939           $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
    940         } else {
    941         }
    942       }
    943 
    944       // ----- Look for 2 args
    945       // Here we need to support the first historic synopsis of the
    946       // method.
    947       else {
    948 
    949         // ----- Get the first argument
    950         $v_path = $v_arg_list[0];
    951 
    952         // ----- Look for the optional second argument
    953         if ($v_size == 2) {
    954           $v_remove_path = $v_arg_list[1];
    955         } else {
    956           if ($v_size > 2) {
    957             // ----- Error log
    958             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
    959 
    960             // ----- Return
    961             return 0;
    962           }
    963         }
    964       }
    965     }
    966 
    967     // ----- Trace
    968 
    969     // ----- Trick
    970     // Here I want to reuse extractByRule(), so I need to parse the $p_index
    971     // with privParseOptions()
    972     $v_arg_trick = array(PCLZIP_OPT_BY_INDEX, $p_index);
    973     $v_options_trick = array();
    974     $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
    975         array(PCLZIP_OPT_BY_INDEX => 'optional'));
    976     if ($v_result != 1) {
    977       return 0;
    978     }
    979     $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
    980 
    981     // ----- Look for default option values
    982     $this->privOptionDefaultThreshold($v_options);
    983 
    984     // ----- Call the extracting fct
    985     if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
    986       return (0);
    987     }
    988 
    989     // ----- Return
    990     return $p_list;
    991   }
    992   // --------------------------------------------------------------------------------
    993 
    994   // --------------------------------------------------------------------------------
    995   // Function :
    996   //   delete([$p_option, $p_option_value, ...])
    997   // Description :
    998   //   This method removes files from the archive.
    999   //   If no parameters are given, then all the archive is emptied.
    1000   // Parameters :
    1001   //   None or optional arguments.
    1002   // Options :
    1003   //   PCLZIP_OPT_BY_INDEX :
    1004   //   PCLZIP_OPT_BY_NAME :
    1005   //   PCLZIP_OPT_BY_EREG :
    1006   //   PCLZIP_OPT_BY_PREG :
    1007   // Return Values :
    1008   //   0 on failure,
    1009   //   The list of the files which are still present in the archive.
    1010   //   (see PclZip::listContent() for list entry format)
    1011   // --------------------------------------------------------------------------------
    1012   public function delete() {
    1013     $v_result = 1;
    1014 
    1015     // ----- Reset the error handler
    1016     $this->privErrorReset();
    1017 
    1018     // ----- Check archive
    1019     if (!$this->privCheckFormat()) {
    1020       return (0);
    1021     }
    1022 
    1023     // ----- Set default values
    1024     $v_options = array();
    1025 
    1026     // ----- Look for variable options arguments
    1027     $v_size = func_num_args();
    1028 
    1029     // ----- Look for arguments
    1030     if ($v_size > 0) {
    1031       // ----- Get the arguments
    1032       $v_arg_list = func_get_args();
    1033 
    1034       // ----- Parse the options
    1035       $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
    1036           array(
    1037               PCLZIP_OPT_BY_NAME => 'optional',
    1038               PCLZIP_OPT_BY_EREG => 'optional',
    1039               PCLZIP_OPT_BY_PREG => 'optional',
    1040               PCLZIP_OPT_BY_INDEX => 'optional'
    1041           ));
    1042       if ($v_result != 1) {
    1043         return 0;
    1044       }
    1045     }
    1046 
    1047     // ----- Magic quotes trick
    1048     $this->privDisableMagicQuotes();
    1049 
    1050     // ----- Call the delete fct
    1051     $v_list = array();
    1052     if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
    1053       $this->privSwapBackMagicQuotes();
    1054       unset($v_list);
    1055 
    1056       return (0);
    1057     }
    1058 
    1059     // ----- Magic quotes trick
    1060     $this->privSwapBackMagicQuotes();
    1061 
    1062     // ----- Return
    1063     return $v_list;
    1064   }
    1065   // --------------------------------------------------------------------------------
    1066 
    1067   // --------------------------------------------------------------------------------
    1068   // Function : deleteByIndex()
    1069   // Description :
    1070   //   ***** Deprecated *****
    1071   //   delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
    1072   // --------------------------------------------------------------------------------
    1073   public function deleteByIndex($p_index) {
    1074 
    1075     $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
    1076 
    1077     // ----- Return
    1078     return $p_list;
    1079   }
    1080   // --------------------------------------------------------------------------------
    1081 
    1082   // --------------------------------------------------------------------------------
    1083   // Function : properties()
    1084   // Description :
    1085   //   This method gives the properties of the archive.
    1086   //   The properties are :
    1087   //     nb : Number of files in the archive
    1088   //     comment : Comment associated with the archive file
    1089   //     status : not_exist, ok
    1090   // Parameters :
    1091   //   None
    1092   // Return Values :
    1093   //   0 on failure,
    1094   //   An array with the archive properties.
    1095   // --------------------------------------------------------------------------------
    1096   public function properties() {
    1097 
    1098     // ----- Reset the error handler
    1099     $this->privErrorReset();
    1100 
    1101     // ----- Magic quotes trick
    1102     $this->privDisableMagicQuotes();
    1103 
    1104     // ----- Check archive
    1105     if (!$this->privCheckFormat()) {
    1106       $this->privSwapBackMagicQuotes();
    1107 
    1108       return (0);
    1109     }
    1110 
    1111     // ----- Default properties
    1112     $v_prop = array();
    1113     $v_prop['comment'] = '';
    1114     $v_prop['nb'] = 0;
    1115     $v_prop['status'] = 'not_exist';
    1116 
    1117     // ----- Look if file exists
    1118     if (@is_file($this->zipname)) {
    1119       // ----- Open the zip file
    1120       if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) {
    1121         $this->privSwapBackMagicQuotes();
    1122 
    1123         // ----- Error log
    1124         PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL,
    1125             'Unable to open archive \'' . $this->zipname . '\' in binary read mode');
    1126 
    1127         // ----- Return
    1128         return 0;
    1129       }
    1130 
    1131       // ----- Read the central directory informations
    1132       $v_central_dir = array();
    1133       if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
    1134         $this->privSwapBackMagicQuotes();
    1135 
    1136         return 0;
    1137       }
    1138 
    1139       // ----- Close the zip file
    1140       $this->privCloseFd();
    1141 
    1142       // ----- Set the user attributes
    1143       $v_prop['comment'] = $v_central_dir['comment'];
    1144       $v_prop['nb'] = $v_central_dir['entries'];
    1145       $v_prop['status'] = 'ok';
    1146     }
    1147 
    1148     // ----- Magic quotes trick
    1149     $this->privSwapBackMagicQuotes();
    1150 
    1151     // ----- Return
    1152     return $v_prop;
    1153   }
    1154   // --------------------------------------------------------------------------------
    1155 
    1156   // --------------------------------------------------------------------------------
    1157   // Function : duplicate()
    1158   // Description :
    1159   //   This method creates an archive by copying the content of an other one. If
    1160   //   the archive already exist, it is replaced by the new one without any warning.
    1161   // Parameters :
    1162   //   $p_archive : The filename of a valid archive, or
    1163   //                a valid PclZip object.
    1164   // Return Values :
    1165   //   1 on success.
    1166   //   0 or a negative value on error (error code).
    1167   // --------------------------------------------------------------------------------
    1168   public function duplicate($p_archive) {
    1169     $v_result = 1;
    1170 
    1171     // ----- Reset the error handler
    1172     $this->privErrorReset();
    1173 
    1174     // ----- Look if the $p_archive is a PclZip object
    1175     if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) {
    1176 
    1177       // ----- Duplicate the archive
    1178       $v_result = $this->privDuplicate($p_archive->zipname);
    1179     } // ----- Look if the $p_archive is a string (so a filename)
    1180     else {
    1181       if (is_string($p_archive)) {
    1182 
    1183         // ----- Check that $p_archive is a valid zip file
    1184         // TBC : Should also check the archive format
    1185         if (!is_file($p_archive)) {
    1186           // ----- Error log
    1187           PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '" . $p_archive . "'");
    1188           $v_result = PCLZIP_ERR_MISSING_FILE;
    1189         } else {
    1190           // ----- Duplicate the archive
    1191           $v_result = $this->privDuplicate($p_archive);
    1192         }
    1193       } // ----- Invalid variable
    1194       else {
    1195         // ----- Error log
    1196         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
    1197         $v_result = PCLZIP_ERR_INVALID_PARAMETER;
    1198       }
    1199     }
    1200 
    1201     // ----- Return
    1202     return $v_result;
    1203   }
    1204   // --------------------------------------------------------------------------------
    1205 
    1206   // --------------------------------------------------------------------------------
    1207   // Function : merge()
    1208   // Description :
    1209   //   This method merge the $p_archive_to_add archive at the end of the current
    1210   //   one ($this).
    1211   //   If the archive ($this) does not exist, the merge becomes a duplicate.
    1212   //   If the $p_archive_to_add archive does not exist, the merge is a success.
    1213   // Parameters :
    1214   //   $p_archive_to_add : It can be directly the filename of a valid zip archive,
    1215   //                       or a PclZip object archive.
    1216   // Return Values :
    1217   //   1 on success,
    1218   //   0 or negative values on error (see below).
    1219   // --------------------------------------------------------------------------------
    1220   public function merge($p_archive_to_add) {
    1221     $v_result = 1;
    1222 
    1223     // ----- Reset the error handler
    1224     $this->privErrorReset();
    1225 
    1226     // ----- Check archive
    1227     if (!$this->privCheckFormat()) {
    1228       return (0);
    1229     }
    1230 
    1231     // ----- Look if the $p_archive_to_add is a PclZip object
    1232     if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) {
    1233 
    1234       // ----- Merge the archive
    1235       $v_result = $this->privMerge($p_archive_to_add);
    1236     } // ----- Look if the $p_archive_to_add is a string (so a filename)
    1237     else {
    1238       if (is_string($p_archive_to_add)) {
    1239 
    1240         // ----- Create a temporary archive
    1241         $v_object_archive = new PclZip($p_archive_to_add);
    1242 
    1243         // ----- Merge the archive
    1244         $v_result = $this->privMerge($v_object_archive);
    1245       } // ----- Invalid variable
    1246       else {
    1247         // ----- Error log
    1248         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
    1249         $v_result = PCLZIP_ERR_INVALID_PARAMETER;
    1250       }
    1251     }
    1252 
    1253     // ----- Return
    1254     return $v_result;
    1255   }
    1256   // --------------------------------------------------------------------------------
    1257 
    1258 
    1259   // --------------------------------------------------------------------------------
    1260   // Function : errorCode()
    1261   // Description :
    1262   // Parameters :
    1263   // --------------------------------------------------------------------------------
    1264   public function errorCode() {
    1265     if (PCLZIP_ERROR_EXTERNAL == 1) {
    1266       return (PclErrorCode());
    1267     } else {
    1268       return ($this->error_code);
    1269     }
    1270   }
    1271   // --------------------------------------------------------------------------------
    1272 
    1273   // --------------------------------------------------------------------------------
    1274   // Function : errorName()
    1275   // Description :
    1276   // Parameters :
    1277   // --------------------------------------------------------------------------------
    1278   public function errorName($p_with_code = false) {
    1279     $v_name = array(
    1280         PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
    1281         PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
    1282         PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
    1283         PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
    1284         PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
    1285         PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
    1286         PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
    1287         PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
    1288         PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
    1289         PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
    1290         PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
    1291         PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
    1292         PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
    1293         PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
    1294         PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
    1295         PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
    1296         PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
    1297         PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
    1298         PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION',
    1299         PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE',
    1300         PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
    1301     );
    1302 
    1303     if (isset($v_name[$this->error_code])) {
    1304       $v_value = $v_name[$this->error_code];
    1305     } else {
    1306       $v_value = 'NoName';
    1307     }
    1308 
    1309     if ($p_with_code) {
    1310       return ($v_value . ' (' . $this->error_code . ')');
    1311     } else {
    1312       return ($v_value);
    1313     }
    1314   }
    1315   // --------------------------------------------------------------------------------
    1316 
    1317   // --------------------------------------------------------------------------------
    1318   // Function : errorInfo()
    1319   // Description :
    1320   // Parameters :
    1321   // --------------------------------------------------------------------------------
    1322   public function errorInfo($p_full = false) {
    1323     if (PCLZIP_ERROR_EXTERNAL == 1) {
    1324       return (PclErrorString());
    1325     } else {
    1326       if ($p_full) {
    1327         return ($this->errorName(true) . " : " . $this->error_string);
    1328       } else {
    1329         return ($this->error_string . " [code " . $this->error_code . "]");
    1330       }
    1331     }
    1332   }
    1333   // --------------------------------------------------------------------------------
     877                $v_path = '';
     878                $v_remove_path = "";
     879                $v_remove_all_path = false;
     880
     881                // ----- Look for variable options arguments
     882                $v_size = func_num_args();
     883
     884                // ----- Default values for option
     885                $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
     886
     887                // ----- Look for arguments
     888                if ($v_size > 1) {
     889                        // ----- Get the arguments
     890                        $v_arg_list = func_get_args();
     891
     892                        // ----- Remove form the options list the first argument
     893                        array_shift($v_arg_list);
     894                        $v_size--;
     895
     896                        // ----- Look for first arg
     897                        if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
     898
     899                                // ----- Parse the options
     900                                $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
     901                                        array(
     902                                                PCLZIP_OPT_PATH => 'optional',
     903                                                PCLZIP_OPT_REMOVE_PATH => 'optional',
     904                                                PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
     905                                                PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
     906                                                PCLZIP_OPT_ADD_PATH => 'optional',
     907                                                PCLZIP_CB_PRE_EXTRACT => 'optional',
     908                                                PCLZIP_CB_POST_EXTRACT => 'optional',
     909                                                PCLZIP_OPT_SET_CHMOD => 'optional',
     910                                                PCLZIP_OPT_REPLACE_NEWER => 'optional',
     911                                                PCLZIP_OPT_STOP_ON_ERROR => 'optional',
     912                                                PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
     913                                                PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
     914                                                PCLZIP_OPT_TEMP_FILE_ON => 'optional',
     915                                                PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
     916                                        ));
     917                                if ($v_result != 1) {
     918                                        return 0;
     919                                }
     920
     921                                // ----- Set the arguments
     922                                if (isset($v_options[PCLZIP_OPT_PATH])) {
     923                                        $v_path = $v_options[PCLZIP_OPT_PATH];
     924                                }
     925                                if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
     926                                        $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
     927                                }
     928                                if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
     929                                        $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
     930                                }
     931                                if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
     932                                        // ----- Check for '/' in last path char
     933                                        if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
     934                                                $v_path .= '/';
     935                                        }
     936                                        $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
     937                                }
     938                                if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
     939                                        $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = false;
     940                                } else {
     941                                }
     942                        }
     943
     944                        // ----- Look for 2 args
     945                        // Here we need to support the first historic synopsis of the
     946                        // method.
     947                        else {
     948
     949                                // ----- Get the first argument
     950                                $v_path = $v_arg_list[0];
     951
     952                                // ----- Look for the optional second argument
     953                                if ($v_size == 2) {
     954                                        $v_remove_path = $v_arg_list[1];
     955                                } else {
     956                                        if ($v_size > 2) {
     957                                                // ----- Error log
     958                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
     959
     960                                                // ----- Return
     961                                                return 0;
     962                                        }
     963                                }
     964                        }
     965                }
     966
     967                // ----- Trace
     968
     969                // ----- Trick
     970                // Here I want to reuse extractByRule(), so I need to parse the $p_index
     971                // with privParseOptions()
     972                $v_arg_trick = array(PCLZIP_OPT_BY_INDEX, $p_index);
     973                $v_options_trick = array();
     974                $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
     975                        array(PCLZIP_OPT_BY_INDEX => 'optional'));
     976                if ($v_result != 1) {
     977                        return 0;
     978                }
     979                $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
     980
     981                // ----- Look for default option values
     982                $this->privOptionDefaultThreshold($v_options);
     983
     984                // ----- Call the extracting fct
     985                if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
     986                        return (0);
     987                }
     988
     989                // ----- Return
     990                return $p_list;
     991        }
     992        // --------------------------------------------------------------------------------
     993
     994        // --------------------------------------------------------------------------------
     995        // Function :
     996        //   delete([$p_option, $p_option_value, ...])
     997        // Description :
     998        //   This method removes files from the archive.
     999        //   If no parameters are given, then all the archive is emptied.
     1000        // Parameters :
     1001        //   None or optional arguments.
     1002        // Options :
     1003        //   PCLZIP_OPT_BY_INDEX :
     1004        //   PCLZIP_OPT_BY_NAME :
     1005        //   PCLZIP_OPT_BY_EREG :
     1006        //   PCLZIP_OPT_BY_PREG :
     1007        // Return Values :
     1008        //   0 on failure,
     1009        //   The list of the files which are still present in the archive.
     1010        //   (see PclZip::listContent() for list entry format)
     1011        // --------------------------------------------------------------------------------
     1012        public function delete() {
     1013                $v_result = 1;
     1014
     1015                // ----- Reset the error handler
     1016                $this->privErrorReset();
     1017
     1018                // ----- Check archive
     1019                if (!$this->privCheckFormat()) {
     1020                        return (0);
     1021                }
     1022
     1023                // ----- Set default values
     1024                $v_options = array();
     1025
     1026                // ----- Look for variable options arguments
     1027                $v_size = func_num_args();
     1028
     1029                // ----- Look for arguments
     1030                if ($v_size > 0) {
     1031                        // ----- Get the arguments
     1032                        $v_arg_list = func_get_args();
     1033
     1034                        // ----- Parse the options
     1035                        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
     1036                                array(
     1037                                        PCLZIP_OPT_BY_NAME => 'optional',
     1038                                        PCLZIP_OPT_BY_EREG => 'optional',
     1039                                        PCLZIP_OPT_BY_PREG => 'optional',
     1040                                        PCLZIP_OPT_BY_INDEX => 'optional'
     1041                                ));
     1042                        if ($v_result != 1) {
     1043                                return 0;
     1044                        }
     1045                }
     1046
     1047                // ----- Magic quotes trick
     1048                $this->privDisableMagicQuotes();
     1049
     1050                // ----- Call the delete fct
     1051                $v_list = array();
     1052                if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
     1053                        $this->privSwapBackMagicQuotes();
     1054                        unset($v_list);
     1055
     1056                        return (0);
     1057                }
     1058
     1059                // ----- Magic quotes trick
     1060                $this->privSwapBackMagicQuotes();
     1061
     1062                // ----- Return
     1063                return $v_list;
     1064        }
     1065        // --------------------------------------------------------------------------------
     1066
     1067        // --------------------------------------------------------------------------------
     1068        // Function : deleteByIndex()
     1069        // Description :
     1070        //   ***** Deprecated *****
     1071        //   delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
     1072        // --------------------------------------------------------------------------------
     1073        public function deleteByIndex($p_index) {
     1074
     1075                $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
     1076
     1077                // ----- Return
     1078                return $p_list;
     1079        }
     1080        // --------------------------------------------------------------------------------
     1081
     1082        // --------------------------------------------------------------------------------
     1083        // Function : properties()
     1084        // Description :
     1085        //   This method gives the properties of the archive.
     1086        //   The properties are :
     1087        //     nb : Number of files in the archive
     1088        //     comment : Comment associated with the archive file
     1089        //     status : not_exist, ok
     1090        // Parameters :
     1091        //   None
     1092        // Return Values :
     1093        //   0 on failure,
     1094        //   An array with the archive properties.
     1095        // --------------------------------------------------------------------------------
     1096        public function properties() {
     1097
     1098                // ----- Reset the error handler
     1099                $this->privErrorReset();
     1100
     1101                // ----- Magic quotes trick
     1102                $this->privDisableMagicQuotes();
     1103
     1104                // ----- Check archive
     1105                if (!$this->privCheckFormat()) {
     1106                        $this->privSwapBackMagicQuotes();
     1107
     1108                        return (0);
     1109                }
     1110
     1111                // ----- Default properties
     1112                $v_prop = array();
     1113                $v_prop['comment'] = '';
     1114                $v_prop['nb'] = 0;
     1115                $v_prop['status'] = 'not_exist';
     1116
     1117                // ----- Look if file exists
     1118                if (@is_file($this->zipname)) {
     1119                        // ----- Open the zip file
     1120                        if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) {
     1121                                $this->privSwapBackMagicQuotes();
     1122
     1123                                // ----- Error log
     1124                                PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL,
     1125                                        'Unable to open archive \'' . $this->zipname . '\' in binary read mode');
     1126
     1127                                // ----- Return
     1128                                return 0;
     1129                        }
     1130
     1131                        // ----- Read the central directory informations
     1132                        $v_central_dir = array();
     1133                        if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
     1134                                $this->privSwapBackMagicQuotes();
     1135
     1136                                return 0;
     1137                        }
     1138
     1139                        // ----- Close the zip file
     1140                        $this->privCloseFd();
     1141
     1142                        // ----- Set the user attributes
     1143                        $v_prop['comment'] = $v_central_dir['comment'];
     1144                        $v_prop['nb'] = $v_central_dir['entries'];
     1145                        $v_prop['status'] = 'ok';
     1146                }
     1147
     1148                // ----- Magic quotes trick
     1149                $this->privSwapBackMagicQuotes();
     1150
     1151                // ----- Return
     1152                return $v_prop;
     1153        }
     1154        // --------------------------------------------------------------------------------
     1155
     1156        // --------------------------------------------------------------------------------
     1157        // Function : duplicate()
     1158        // Description :
     1159        //   This method creates an archive by copying the content of an other one. If
     1160        //   the archive already exist, it is replaced by the new one without any warning.
     1161        // Parameters :
     1162        //   $p_archive : The filename of a valid archive, or
     1163        //                a valid PclZip object.
     1164        // Return Values :
     1165        //   1 on success.
     1166        //   0 or a negative value on error (error code).
     1167        // --------------------------------------------------------------------------------
     1168        public function duplicate($p_archive) {
     1169                $v_result = 1;
     1170
     1171                // ----- Reset the error handler
     1172                $this->privErrorReset();
     1173
     1174                // ----- Look if the $p_archive is a PclZip object
     1175                if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) {
     1176
     1177                        // ----- Duplicate the archive
     1178                        $v_result = $this->privDuplicate($p_archive->zipname);
     1179                } // ----- Look if the $p_archive is a string (so a filename)
     1180                else {
     1181                        if (is_string($p_archive)) {
     1182
     1183                                // ----- Check that $p_archive is a valid zip file
     1184                                // TBC : Should also check the archive format
     1185                                if (!is_file($p_archive)) {
     1186                                        // ----- Error log
     1187                                        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '" . $p_archive . "'");
     1188                                        $v_result = PCLZIP_ERR_MISSING_FILE;
     1189                                } else {
     1190                                        // ----- Duplicate the archive
     1191                                        $v_result = $this->privDuplicate($p_archive);
     1192                                }
     1193                        } // ----- Invalid variable
     1194                        else {
     1195                                // ----- Error log
     1196                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
     1197                                $v_result = PCLZIP_ERR_INVALID_PARAMETER;
     1198                        }
     1199                }
     1200
     1201                // ----- Return
     1202                return $v_result;
     1203        }
     1204        // --------------------------------------------------------------------------------
     1205
     1206        // --------------------------------------------------------------------------------
     1207        // Function : merge()
     1208        // Description :
     1209        //   This method merge the $p_archive_to_add archive at the end of the current
     1210        //   one ($this).
     1211        //   If the archive ($this) does not exist, the merge becomes a duplicate.
     1212        //   If the $p_archive_to_add archive does not exist, the merge is a success.
     1213        // Parameters :
     1214        //   $p_archive_to_add : It can be directly the filename of a valid zip archive,
     1215        //                       or a PclZip object archive.
     1216        // Return Values :
     1217        //   1 on success,
     1218        //   0 or negative values on error (see below).
     1219        // --------------------------------------------------------------------------------
     1220        public function merge($p_archive_to_add) {
     1221                $v_result = 1;
     1222
     1223                // ----- Reset the error handler
     1224                $this->privErrorReset();
     1225
     1226                // ----- Check archive
     1227                if (!$this->privCheckFormat()) {
     1228                        return (0);
     1229                }
     1230
     1231                // ----- Look if the $p_archive_to_add is a PclZip object
     1232                if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) {
     1233
     1234                        // ----- Merge the archive
     1235                        $v_result = $this->privMerge($p_archive_to_add);
     1236                } // ----- Look if the $p_archive_to_add is a string (so a filename)
     1237                else {
     1238                        if (is_string($p_archive_to_add)) {
     1239
     1240                                // ----- Create a temporary archive
     1241                                $v_object_archive = new PclZip($p_archive_to_add);
     1242
     1243                                // ----- Merge the archive
     1244                                $v_result = $this->privMerge($v_object_archive);
     1245                        } // ----- Invalid variable
     1246                        else {
     1247                                // ----- Error log
     1248                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
     1249                                $v_result = PCLZIP_ERR_INVALID_PARAMETER;
     1250                        }
     1251                }
     1252
     1253                // ----- Return
     1254                return $v_result;
     1255        }
     1256        // --------------------------------------------------------------------------------
     1257
     1258
     1259        // --------------------------------------------------------------------------------
     1260        // Function : errorCode()
     1261        // Description :
     1262        // Parameters :
     1263        // --------------------------------------------------------------------------------
     1264        public function errorCode() {
     1265                if (PCLZIP_ERROR_EXTERNAL == 1) {
     1266                        return (PclErrorCode());
     1267                } else {
     1268                        return ($this->error_code);
     1269                }
     1270        }
     1271        // --------------------------------------------------------------------------------
     1272
     1273        // --------------------------------------------------------------------------------
     1274        // Function : errorName()
     1275        // Description :
     1276        // Parameters :
     1277        // --------------------------------------------------------------------------------
     1278        public function errorName($p_with_code = false) {
     1279                $v_name = array(
     1280                        PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
     1281                        PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
     1282                        PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
     1283                        PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
     1284                        PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
     1285                        PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
     1286                        PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
     1287                        PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
     1288                        PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
     1289                        PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
     1290                        PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
     1291                        PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
     1292                        PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
     1293                        PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
     1294                        PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
     1295                        PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
     1296                        PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
     1297                        PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
     1298                        PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION',
     1299                        PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE',
     1300                        PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
     1301                );
     1302
     1303                if (isset($v_name[$this->error_code])) {
     1304                        $v_value = $v_name[$this->error_code];
     1305                } else {
     1306                        $v_value = 'NoName';
     1307                }
     1308
     1309                if ($p_with_code) {
     1310                        return ($v_value . ' (' . $this->error_code . ')');
     1311                } else {
     1312                        return ($v_value);
     1313                }
     1314        }
     1315        // --------------------------------------------------------------------------------
     1316
     1317        // --------------------------------------------------------------------------------
     1318        // Function : errorInfo()
     1319        // Description :
     1320        // Parameters :
     1321        // --------------------------------------------------------------------------------
     1322        public function errorInfo($p_full = false) {
     1323                if (PCLZIP_ERROR_EXTERNAL == 1) {
     1324                        return (PclErrorString());
     1325                } else {
     1326                        if ($p_full) {
     1327                                return ($this->errorName(true) . " : " . $this->error_string);
     1328                        } else {
     1329                                return ($this->error_string . " [code " . $this->error_code . "]");
     1330                        }
     1331                }
     1332        }
     1333        // --------------------------------------------------------------------------------
    13341334
    13351335
     
    13411341
    13421342
    1343   // --------------------------------------------------------------------------------
    1344   // Function : privCheckFormat()
    1345   // Description :
    1346   //   This method check that the archive exists and is a valid zip archive.
    1347   //   Several level of check exists. (futur)
    1348   // Parameters :
    1349   //   $p_level : Level of check. Default 0.
    1350   //              0 : Check the first bytes (magic codes) (default value))
    1351   //              1 : 0 + Check the central directory (futur)
    1352   //              2 : 1 + Check each file header (futur)
    1353   // Return Values :
    1354   //   true on success,
    1355   //   false on error, the error code is set.
    1356   // --------------------------------------------------------------------------------
    1357   public function privCheckFormat($p_level = 0) {
    1358     $v_result = true;
    1359 
    1360     // ----- Reset the file system cache
    1361     clearstatcache();
    1362 
    1363     // ----- Reset the error handler
    1364     $this->privErrorReset();
    1365 
    1366     // ----- Look if the file exits
    1367     if (!is_file($this->zipname)) {
    1368       // ----- Error log
    1369       PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '" . $this->zipname . "'");
    1370 
    1371       return (false);
    1372     }
    1373 
    1374     // ----- Check that the file is readeable
    1375     if (!is_readable($this->zipname)) {
    1376       // ----- Error log
    1377       PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '" . $this->zipname . "'");
    1378 
    1379       return (false);
    1380     }
    1381 
    1382     // ----- Check the magic code
    1383     // TBC
    1384 
    1385     // ----- Check the central header
    1386     // TBC
    1387 
    1388     // ----- Check each file header
    1389     // TBC
    1390 
    1391     // ----- Return
    1392     return $v_result;
    1393   }
    1394   // --------------------------------------------------------------------------------
    1395 
    1396   // --------------------------------------------------------------------------------
    1397   // Function : privParseOptions()
    1398   // Description :
    1399   //   This internal methods reads the variable list of arguments ($p_options_list,
    1400   //   $p_size) and generate an array with the options and values ($v_result_list).
    1401   //   $v_requested_options contains the options that can be present and those that
    1402   //   must be present.
    1403   //   $v_requested_options is an array, with the option value as key, and 'optional',
    1404   //   or 'mandatory' as value.
    1405   // Parameters :
    1406   //   See above.
    1407   // Return Values :
    1408   //   1 on success.
    1409   //   0 on failure.
    1410   // --------------------------------------------------------------------------------
    1411   public function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options = false) {
    1412     $v_result = 1;
    1413 
    1414     // ----- Read the options
    1415     $i = 0;
    1416     while ($i < $p_size) {
    1417 
    1418       // ----- Check if the option is supported
    1419       if (!isset($v_requested_options[$p_options_list[$i]])) {
    1420         // ----- Error log
    1421         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1422             "Invalid optional parameter '" . $p_options_list[$i] . "' for this method");
    1423 
    1424         // ----- Return
    1425         return PclZip::errorCode();
    1426       }
    1427 
    1428       // ----- Look for next option
    1429       switch ($p_options_list[$i]) {
    1430         // ----- Look for options that request a path value
    1431         case PCLZIP_OPT_PATH :
    1432         case PCLZIP_OPT_REMOVE_PATH :
    1433         case PCLZIP_OPT_ADD_PATH :
    1434           // ----- Check the number of parameters
    1435           if (($i + 1) >= $p_size) {
    1436             // ----- Error log
    1437             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1438                 "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1439 
    1440             // ----- Return
    1441             return PclZip::errorCode();
    1442           }
    1443 
    1444           // ----- Get the value
    1445           $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i + 1], false);
    1446           $i++;
    1447           break;
    1448 
    1449         case PCLZIP_OPT_TEMP_FILE_THRESHOLD :
    1450           // ----- Check the number of parameters
    1451           if (($i + 1) >= $p_size) {
    1452             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1453                 "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1454 
    1455             return PclZip::errorCode();
    1456           }
    1457 
    1458           // ----- Check for incompatible options
    1459           if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
    1460             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1461                 "Option '" . PclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
    1462 
    1463             return PclZip::errorCode();
    1464           }
    1465 
    1466           // ----- Check the value
    1467           $v_value = $p_options_list[$i + 1];
    1468           if ((!is_integer($v_value)) || ($v_value < 0)) {
    1469             PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
    1470                 "Integer expected for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1471 
    1472             return PclZip::errorCode();
    1473           }
    1474 
    1475           // ----- Get the value (and convert it in bytes)
    1476           $v_result_list[$p_options_list[$i]] = $v_value * 1048576;
    1477           $i++;
    1478           break;
    1479 
    1480         case PCLZIP_OPT_TEMP_FILE_ON :
    1481           // ----- Check for incompatible options
    1482           if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
    1483             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1484                 "Option '" . PclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
    1485 
    1486             return PclZip::errorCode();
    1487           }
    1488 
    1489           $v_result_list[$p_options_list[$i]] = true;
    1490           break;
    1491 
    1492         case PCLZIP_OPT_TEMP_FILE_OFF :
    1493           // ----- Check for incompatible options
    1494           if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
    1495             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1496                 "Option '" . PclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
    1497 
    1498             return PclZip::errorCode();
    1499           }
    1500           // ----- Check for incompatible options
    1501           if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
    1502             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1503                 "Option '" . PclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
    1504 
    1505             return PclZip::errorCode();
    1506           }
    1507 
    1508           $v_result_list[$p_options_list[$i]] = true;
    1509           break;
    1510 
    1511         case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
    1512           // ----- Check the number of parameters
    1513           if (($i + 1) >= $p_size) {
    1514             // ----- Error log
    1515             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1516                 "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1517 
    1518             // ----- Return
    1519             return PclZip::errorCode();
    1520           }
    1521 
    1522           // ----- Get the value
    1523           if (is_string($p_options_list[$i + 1])
    1524               && ($p_options_list[$i + 1] != '')
    1525           ) {
    1526             $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i + 1], false);
    1527             $i++;
    1528           } else {
    1529           }
    1530           break;
    1531 
    1532         // ----- Look for options that request an array of string for value
    1533         case PCLZIP_OPT_BY_NAME :
    1534           // ----- Check the number of parameters
    1535           if (($i + 1) >= $p_size) {
    1536             // ----- Error log
    1537             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1538                 "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           } else {
    1548             if (is_array($p_options_list[$i + 1])) {
    1549               $v_result_list[$p_options_list[$i]] = $p_options_list[$i + 1];
    1550             } else {
    1551               // ----- Error log
    1552               PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
    1553                   "Wrong parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1554 
    1555               // ----- Return
    1556               return PclZip::errorCode();
    1557             }
    1558           }
    1559           $i++;
    1560           break;
    1561 
    1562         // ----- Look for options that request an EREG or PREG expression
    1563         case PCLZIP_OPT_BY_EREG :
    1564           // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
    1565           // to PCLZIP_OPT_BY_PREG
    1566           $p_options_list[$i] = PCLZIP_OPT_BY_PREG;
    1567         case PCLZIP_OPT_BY_PREG :
    1568           //case PCLZIP_OPT_CRYPT :
    1569           // ----- Check the number of parameters
    1570           if (($i + 1) >= $p_size) {
    1571             // ----- Error log
    1572             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1573                 "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1574 
    1575             // ----- Return
    1576             return PclZip::errorCode();
    1577           }
    1578 
    1579           // ----- Get the value
    1580           if (is_string($p_options_list[$i + 1])) {
    1581             $v_result_list[$p_options_list[$i]] = $p_options_list[$i + 1];
    1582           } else {
    1583             // ----- Error log
    1584             PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
    1585                 "Wrong parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1586 
    1587             // ----- Return
    1588             return PclZip::errorCode();
    1589           }
    1590           $i++;
    1591           break;
    1592 
    1593         // ----- Look for options that takes a string
    1594         case PCLZIP_OPT_COMMENT :
    1595         case PCLZIP_OPT_ADD_COMMENT :
    1596         case PCLZIP_OPT_PREPEND_COMMENT :
    1597           // ----- Check the number of parameters
    1598           if (($i + 1) >= $p_size) {
    1599             // ----- Error log
    1600             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1601                 "Missing parameter value for option '"
    1602                 . PclZipUtilOptionText($p_options_list[$i])
    1603                 . "'");
    1604 
    1605             // ----- Return
    1606             return PclZip::errorCode();
    1607           }
    1608 
    1609           // ----- Get the value
    1610           if (is_string($p_options_list[$i + 1])) {
    1611             $v_result_list[$p_options_list[$i]] = $p_options_list[$i + 1];
    1612           } else {
    1613             // ----- Error log
    1614             PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
    1615                 "Wrong parameter value for option '"
    1616                 . PclZipUtilOptionText($p_options_list[$i])
    1617                 . "'");
    1618 
    1619             // ----- Return
    1620             return PclZip::errorCode();
    1621           }
    1622           $i++;
    1623           break;
    1624 
    1625         // ----- Look for options that request an array of index
    1626         case PCLZIP_OPT_BY_INDEX :
    1627           // ----- Check the number of parameters
    1628           if (($i + 1) >= $p_size) {
    1629             // ----- Error log
    1630             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1631                 "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1632 
    1633             // ----- Return
    1634             return PclZip::errorCode();
    1635           }
    1636 
    1637           // ----- Get the value
    1638           $v_work_list = array();
    1639           if (is_string($p_options_list[$i + 1])) {
    1640 
    1641             // ----- Remove spaces
    1642             $p_options_list[$i + 1] = strtr($p_options_list[$i + 1], ' ', '');
    1643 
    1644             // ----- Parse items
    1645             $v_work_list = explode(",", $p_options_list[$i + 1]);
    1646           } else {
    1647             if (is_integer($p_options_list[$i + 1])) {
    1648               $v_work_list[0] = $p_options_list[$i + 1] . '-' . $p_options_list[$i + 1];
    1649             } else {
    1650               if (is_array($p_options_list[$i + 1])) {
    1651                 $v_work_list = $p_options_list[$i + 1];
    1652               } else {
    1653                 // ----- Error log
    1654                 PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
    1655                     "Value must be integer, string or array for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1656 
    1657                 // ----- Return
    1658                 return PclZip::errorCode();
    1659               }
    1660             }
    1661           }
    1662 
    1663           // ----- Reduce the index list
    1664           // each index item in the list must be a couple with a start and
    1665           // an end value : [0,3], [5-5], [8-10], ...
    1666           // ----- Check the format of each item
    1667           $v_sort_flag = false;
    1668           $v_sort_value = 0;
    1669           for ($j = 0; $j < sizeof($v_work_list); $j++) {
    1670             // ----- Explode the item
    1671             $v_item_list = explode("-", $v_work_list[$j]);
    1672             $v_size_item_list = sizeof($v_item_list);
    1673 
    1674             // ----- TBC : Here we might check that each item is a
    1675             // real integer ...
    1676 
    1677             // ----- Look for single value
    1678             if ($v_size_item_list == 1) {
    1679               // ----- Set the option value
    1680               $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
    1681               $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
    1682             } elseif ($v_size_item_list == 2) {
    1683               // ----- Set the option value
    1684               $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
    1685               $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
    1686             } else {
    1687               // ----- Error log
    1688               PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
    1689                   "Too many values in index range for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1690 
    1691               // ----- Return
    1692               return PclZip::errorCode();
    1693             }
    1694 
    1695 
    1696             // ----- Look for list sort
    1697             if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
    1698               $v_sort_flag = true;
    1699 
    1700               // ----- TBC : An automatic sort should be writen ...
    1701               // ----- Error log
    1702               PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
    1703                   "Invalid order of index range for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1704 
    1705               // ----- Return
    1706               return PclZip::errorCode();
    1707             }
    1708             $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
    1709           }
    1710 
    1711           // ----- Sort the items
    1712           if ($v_sort_flag) {
    1713             // TBC : To Be Completed
    1714           }
    1715 
    1716           // ----- Next option
    1717           $i++;
    1718           break;
    1719 
    1720         // ----- Look for options that request no value
    1721         case PCLZIP_OPT_REMOVE_ALL_PATH :
    1722         case PCLZIP_OPT_EXTRACT_AS_STRING :
    1723         case PCLZIP_OPT_NO_COMPRESSION :
    1724         case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
    1725         case PCLZIP_OPT_REPLACE_NEWER :
    1726         case PCLZIP_OPT_STOP_ON_ERROR :
    1727           $v_result_list[$p_options_list[$i]] = true;
    1728           break;
    1729 
    1730         // ----- Look for options that request an octal value
    1731         case PCLZIP_OPT_SET_CHMOD :
    1732           // ----- Check the number of parameters
    1733           if (($i + 1) >= $p_size) {
    1734             // ----- Error log
    1735             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1736                 "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1737 
    1738             // ----- Return
    1739             return PclZip::errorCode();
    1740           }
    1741 
    1742           // ----- Get the value
    1743           $v_result_list[$p_options_list[$i]] = $p_options_list[$i + 1];
    1744           $i++;
    1745           break;
    1746 
    1747         // ----- Look for options that request a call-back
    1748         case PCLZIP_CB_PRE_EXTRACT :
    1749         case PCLZIP_CB_POST_EXTRACT :
    1750         case PCLZIP_CB_PRE_ADD :
    1751         case PCLZIP_CB_POST_ADD :
    1752           /* for futur use
    1753                                 case PCLZIP_CB_PRE_DELETE :
    1754                                 case PCLZIP_CB_POST_DELETE :
    1755                                 case PCLZIP_CB_PRE_LIST :
    1756                                 case PCLZIP_CB_POST_LIST :
    1757                                 */
    1758           // ----- Check the number of parameters
    1759           if (($i + 1) >= $p_size) {
    1760             // ----- Error log
    1761             PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
    1762                 "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1763 
    1764             // ----- Return
    1765             return PclZip::errorCode();
    1766           }
    1767 
    1768           // ----- Get the value
    1769           $v_function_name = $p_options_list[$i + 1];
    1770 
    1771           // ----- Check that the value is a valid existing function
    1772           if (!function_exists($v_function_name)) {
    1773             // ----- Error log
    1774             PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
    1775                 "Function '" . $v_function_name . "()' is not an existing function for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
    1776 
    1777             // ----- Return
    1778             return PclZip::errorCode();
    1779           }
    1780 
    1781           // ----- Set the attribute
    1782           $v_result_list[$p_options_list[$i]] = $v_function_name;
    1783           $i++;
    1784           break;
    1785 
    1786         default :
    1787           // ----- Error log
    1788           PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1789               "Unknown parameter '"
    1790               . $p_options_list[$i] . "'");
    1791 
    1792           // ----- Return
    1793           return PclZip::errorCode();
    1794       }
    1795 
    1796       // ----- Next options
    1797       $i++;
    1798     }
    1799 
    1800     // ----- Look for mandatory options
    1801     if ($v_requested_options !== false) {
    1802       for ($key = reset($v_requested_options); $key = key($v_requested_options); $key = next($v_requested_options)) {
    1803         // ----- Look for mandatory option
    1804         if ($v_requested_options[$key] == 'mandatory') {
    1805           // ----- Look if present
    1806           if (!isset($v_result_list[$key])) {
    1807             // ----- Error log
    1808             PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1809                 "Missing mandatory parameter " . PclZipUtilOptionText($key) . "(" . $key . ")");
    1810 
    1811             // ----- Return
    1812             return PclZip::errorCode();
    1813           }
    1814         }
    1815       }
    1816     }
    1817 
    1818     // ----- Look for default values
    1819     if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
    1820 
    1821     }
    1822 
    1823     // ----- Return
    1824     return $v_result;
    1825   }
    1826   // --------------------------------------------------------------------------------
    1827 
    1828   // --------------------------------------------------------------------------------
    1829   // Function : privOptionDefaultThreshold()
    1830   // Description :
    1831   // Parameters :
    1832   // Return Values :
    1833   // --------------------------------------------------------------------------------
    1834   public function privOptionDefaultThreshold(&$p_options) {
    1835     $v_result = 1;
    1836 
    1837     if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
    1838         || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])
    1839     ) {
    1840       return $v_result;
    1841     }
    1842 
    1843     // ----- Get 'memory_limit' configuration value
    1844     $v_memory_limit = ini_get('memory_limit');
    1845     $v_memory_limit = trim($v_memory_limit);
    1846     $last = strtolower(substr($v_memory_limit, -1));
    1847     $v_memory_limit = strtolower(substr($v_memory_limit, 0, -1));
    1848 
    1849     if ($last == 'g') //$v_memory_limit = $v_memory_limit*1024*1024*1024;
    1850     {
    1851       $v_memory_limit = $v_memory_limit * 1073741824;
    1852     }
    1853     if ($last == 'm') //$v_memory_limit = $v_memory_limit*1024*1024;
    1854     {
    1855       $v_memory_limit = $v_memory_limit * 1048576;
    1856     }
    1857     if ($last == 'k') {
    1858       $v_memory_limit = $v_memory_limit * 1024;
    1859     }
    1860 
    1861     $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit * PCLZIP_TEMPORARY_FILE_RATIO);
    1862 
    1863 
    1864     // ----- Sanity check : No threshold if value lower than 1M
    1865     if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
    1866       unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
    1867     }
    1868 
    1869     // ----- Return
    1870     return $v_result;
    1871   }
    1872   // --------------------------------------------------------------------------------
    1873 
    1874   // --------------------------------------------------------------------------------
    1875   // Function : privFileDescrParseAtt()
    1876   // Description :
    1877   // Parameters :
    1878   // Return Values :
    1879   //   1 on success.
    1880   //   0 on failure.
    1881   // --------------------------------------------------------------------------------
    1882   public function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options = false) {
    1883     $v_result = 1;
    1884 
    1885     // ----- For each file in the list check the attributes
    1886     foreach ($p_file_list as $v_key => $v_value) {
    1887 
    1888       // ----- Check if the option is supported
    1889       if (!isset($v_requested_options[$v_key])) {
    1890         // ----- Error log
    1891         PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '" . $v_key . "' for this file");
    1892 
    1893         // ----- Return
    1894         return PclZip::errorCode();
    1895       }
    1896 
    1897       // ----- Look for attribute
    1898       switch ($v_key) {
    1899         case PCLZIP_ATT_FILE_NAME :
    1900           if (!is_string($v_value)) {
    1901             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
    1902                 "Invalid type " . gettype($v_value) . ". String expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
    1903 
    1904             return PclZip::errorCode();
    1905           }
    1906 
    1907           $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
    1908 
    1909           if ($p_filedescr['filename'] == '') {
    1910             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
    1911                 "Invalid empty filename for attribute '" . PclZipUtilOptionText($v_key) . "'");
    1912 
    1913             return PclZip::errorCode();
    1914           }
    1915 
    1916           break;
    1917 
    1918         case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
    1919           if (!is_string($v_value)) {
    1920             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
    1921                 "Invalid type " . gettype($v_value) . ". String expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
    1922 
    1923             return PclZip::errorCode();
    1924           }
    1925 
    1926           $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
    1927 
    1928           if ($p_filedescr['new_short_name'] == '') {
    1929             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
    1930                 "Invalid empty short filename for attribute '" . PclZipUtilOptionText($v_key) . "'");
    1931 
    1932             return PclZip::errorCode();
    1933           }
    1934           break;
    1935 
    1936         case PCLZIP_ATT_FILE_NEW_FULL_NAME :
    1937           if (!is_string($v_value)) {
    1938             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
    1939                 "Invalid type " . gettype($v_value) . ". String expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
    1940 
    1941             return PclZip::errorCode();
    1942           }
    1943 
    1944           $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
    1945 
    1946           if ($p_filedescr['new_full_name'] == '') {
    1947             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
    1948                 "Invalid empty full filename for attribute '" . PclZipUtilOptionText($v_key) . "'");
    1949 
    1950             return PclZip::errorCode();
    1951           }
    1952           break;
    1953 
    1954         // ----- Look for options that takes a string
    1955         case PCLZIP_ATT_FILE_COMMENT :
    1956           if (!is_string($v_value)) {
    1957             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
    1958                 "Invalid type " . gettype($v_value) . ". String expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
    1959 
    1960             return PclZip::errorCode();
    1961           }
    1962 
    1963           $p_filedescr['comment'] = $v_value;
    1964           break;
    1965 
    1966         case PCLZIP_ATT_FILE_MTIME :
    1967           if (!is_integer($v_value)) {
    1968             PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
    1969                 "Invalid type " . gettype($v_value) . ". Integer expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
    1970 
    1971             return PclZip::errorCode();
    1972           }
    1973 
    1974           $p_filedescr['mtime'] = $v_value;
    1975           break;
    1976 
    1977         case PCLZIP_ATT_FILE_CONTENT :
    1978           $p_filedescr['content'] = $v_value;
    1979           break;
    1980 
    1981         default :
    1982           // ----- Error log
    1983           PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1984               "Unknown parameter '" . $v_key . "'");
    1985 
    1986           // ----- Return
    1987           return PclZip::errorCode();
    1988       }
    1989 
    1990       // ----- Look for mandatory options
    1991       if ($v_requested_options !== false) {
    1992         for ($key = reset($v_requested_options); $key = key($v_requested_options); $key = next($v_requested_options)) {
    1993           // ----- Look for mandatory option
    1994           if ($v_requested_options[$key] == 'mandatory') {
    1995             // ----- Look if present
    1996             if (!isset($p_file_list[$key])) {
    1997               PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
    1998                   "Missing mandatory parameter " . PclZipUtilOptionText($key) . "(" . $key . ")");
    1999 
    2000               return PclZip::errorCode();
    2001             }
    2002           }
    2003         }
    2004       }
    2005 
    2006       // end foreach
    2007     }
    2008 
    2009     // ----- Return
    2010     return $v_result;
    2011   }
    2012   // --------------------------------------------------------------------------------
    2013 
    2014   // --------------------------------------------------------------------------------
    2015   // Function : privFileDescrExpand()
    2016   // Description :
    2017   //   This method look for each item of the list to see if its a file, a folder
    2018   //   or a string to be added as file. For any other type of files (link, other)
    2019   //   just ignore the item.
    2020   //   Then prepare the information that will be stored for that file.
    2021   //   When its a folder, expand the folder with all the files that are in that
    2022   //   folder (recursively).
    2023   // Parameters :
    2024   // Return Values :
    2025   //   1 on success.
    2026   //   0 on failure.
    2027   // --------------------------------------------------------------------------------
    2028   public function privFileDescrExpand(&$p_filedescr_list, &$p_options) {
    2029     $v_result = 1;
    2030 
    2031     // ----- Create a result list
    2032     $v_result_list = array();
    2033 
    2034     // ----- Look each entry
    2035     for ($i = 0; $i < sizeof($p_filedescr_list); $i++) {
    2036 
    2037       // ----- Get filedescr
    2038       $v_descr = $p_filedescr_list[$i];
    2039 
    2040       // ----- Reduce the filename
    2041       $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
    2042       $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
    2043 
    2044       // ----- Look for real file or folder
    2045       if (file_exists($v_descr['filename'])) {
    2046         if (@is_file($v_descr['filename'])) {
    2047           $v_descr['type'] = 'file';
    2048         } else {
    2049           if (@is_dir($v_descr['filename'])) {
    2050             $v_descr['type'] = 'folder';
    2051           } else {
    2052             if (@is_link($v_descr['filename'])) {
    2053               // skip
    2054               continue;
    2055             } else {
    2056               // skip
    2057               continue;
    2058             }
    2059           }
    2060         }
    2061       } // ----- Look for string added as file
    2062       else {
    2063         if (isset($v_descr['content'])) {
    2064           $v_descr['type'] = 'virtual_file';
    2065         } // ----- Missing file
    2066         else {
    2067           // ----- Error log
    2068           PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '" . $v_descr['filename'] . "' does not exist");
    2069 
    2070           // ----- Return
    2071           return PclZip::errorCode();
    2072         }
    2073       }
    2074 
    2075       // ----- Calculate the stored filename
    2076       $this->privCalculateStoredFilename($v_descr, $p_options);
    2077 
    2078       // ----- Add the descriptor in result list
    2079       $v_result_list[sizeof($v_result_list)] = $v_descr;
    2080 
    2081       // ----- Look for folder
    2082       if ($v_descr['type'] == 'folder') {
    2083         // ----- List of items in folder
    2084         $v_dirlist_descr = array();
    2085         $v_dirlist_nb = 0;
    2086         if ($v_folder_handler = opendir($v_descr['filename'])) {
    2087           while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
    2088 
    2089             // ----- Skip '.' and '..'
    2090             if (($v_item_handler == '.') || ($v_item_handler == '..')) {
    2091               continue;
    2092             }
    2093 
    2094             // ----- Compose the full filename
    2095             $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'] . '/' . $v_item_handler;
    2096 
    2097             // ----- Look for different stored filename
    2098             // Because the name of the folder was changed, the name of the
    2099             // files/sub-folders also change
    2100             if (($v_descr['stored_filename'] != $v_descr['filename'])
    2101                 && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
    2102             ) {
    2103               if ($v_descr['stored_filename'] != '') {
    2104                 $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'] . '/' . $v_item_handler;
    2105               } else {
    2106                 $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
    2107               }
    2108             }
    2109 
    2110             $v_dirlist_nb++;
    2111           }
    2112 
    2113           @closedir($v_folder_handler);
    2114         } else {
    2115           // TBC : unable to open folder in read mode
    2116         }
    2117 
    2118         // ----- Expand each element of the list
    2119         if ($v_dirlist_nb != 0) {
    2120           // ----- Expand
    2121           if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
    2122             return $v_result;
    2123           }
    2124 
    2125           // ----- Concat the resulting list
    2126           $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
    2127         } else {
    2128         }
    2129 
    2130         // ----- Free local array
    2131         unset($v_dirlist_descr);
    2132       }
    2133     }
    2134 
    2135     // ----- Get the result list
    2136     $p_filedescr_list = $v_result_list;
    2137 
    2138     // ----- Return
    2139     return $v_result;
    2140   }
    2141   // --------------------------------------------------------------------------------
    2142 
    2143   // --------------------------------------------------------------------------------
    2144   // Function : privCreate()
    2145   // Description :
    2146   // Parameters :
    2147   // Return Values :
    2148   // --------------------------------------------------------------------------------
    2149   public function privCreate($p_filedescr_list, &$p_result_list, &$p_options) {
    2150     $v_result = 1;
    2151     $v_list_detail = array();
    2152 
    2153     // ----- Magic quotes trick
    2154     $this->privDisableMagicQuotes();
    2155 
    2156     // ----- Open the file in write mode
    2157     if (($v_result = $this->privOpenFd('wb')) != 1) {
    2158       // ----- Return
    2159       return $v_result;
    2160     }
    2161 
    2162     // ----- Add the list of files
    2163     $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
    2164 
    2165     // ----- Close
    2166     $this->privCloseFd();
    2167 
    2168     // ----- Magic quotes trick
    2169     $this->privSwapBackMagicQuotes();
    2170 
    2171     // ----- Return
    2172     return $v_result;
    2173   }
    2174   // --------------------------------------------------------------------------------
    2175 
    2176   // --------------------------------------------------------------------------------
    2177   // Function : privAdd()
    2178   // Description :
    2179   // Parameters :
    2180   // Return Values :
    2181   // --------------------------------------------------------------------------------
    2182   public function privAdd($p_filedescr_list, &$p_result_list, &$p_options) {
    2183     $v_result = 1;
    2184     $v_list_detail = array();
    2185 
    2186     // ----- Look if the archive exists or is empty
    2187     if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) {
    2188 
    2189       // ----- Do a create
    2190       $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
    2191 
    2192       // ----- Return
    2193       return $v_result;
    2194     }
    2195     // ----- Magic quotes trick
    2196     $this->privDisableMagicQuotes();
    2197 
    2198     // ----- Open the zip file
    2199     if (($v_result = $this->privOpenFd('rb')) != 1) {
    2200       // ----- Magic quotes trick
    2201       $this->privSwapBackMagicQuotes();
    2202 
    2203       // ----- Return
    2204       return $v_result;
    2205     }
    2206 
    2207     // ----- Read the central directory informations
    2208     $v_central_dir = array();
    2209     if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
    2210       $this->privCloseFd();
    2211       $this->privSwapBackMagicQuotes();
    2212 
    2213       return $v_result;
    2214     }
    2215 
    2216     // ----- Go to beginning of File
    2217     @rewind($this->zip_fd);
    2218 
    2219     // ----- Creates a temporay file
    2220     $v_zip_temp_name = PCLZIP_TEMPORARY_DIR . uniqid('pclzip-') . '.tmp';
    2221 
    2222     // ----- Open the temporary file in write mode
    2223     if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) {
    2224       $this->privCloseFd();
    2225       $this->privSwapBackMagicQuotes();
    2226 
    2227       PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL,
    2228           'Unable to open temporary file \'' . $v_zip_temp_name . '\' in binary write mode');
    2229 
    2230       // ----- Return
    2231       return PclZip::errorCode();
    2232     }
    2233 
    2234     // ----- Copy the files from the archive to the temporary file
    2235     // TBC : Here I should better append the file and go back to erase the central dir
    2236     $v_size = $v_central_dir['offset'];
    2237     while ($v_size != 0) {
    2238       $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
    2239       $v_buffer = fread($this->zip_fd, $v_read_size);
    2240       @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
    2241       $v_size -= $v_read_size;
    2242     }
    2243 
    2244     // ----- Swap the file descriptor
    2245     // Here is a trick : I swap the temporary fd with the zip fd, in order to use
    2246     // the following methods on the temporary fil and not the real archive
    2247     $v_swap = $this->zip_fd;
    2248     $this->zip_fd = $v_zip_temp_fd;
    2249     $v_zip_temp_fd = $v_swap;
    2250 
    2251     // ----- Add the files
    2252     $v_header_list = array();
    2253     if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) {
    2254       fclose($v_zip_temp_fd);
    2255       $this->privCloseFd();
    2256       @unlink($v_zip_temp_name);
    2257       $this->privSwapBackMagicQuotes();
    2258 
    2259       // ----- Return
    2260       return $v_result;
    2261     }
    2262 
    2263     // ----- Store the offset of the central dir
    2264     $v_offset = @ftell($this->zip_fd);
    2265 
    2266     // ----- Copy the block of file headers from the old archive
    2267     $v_size = $v_central_dir['size'];
    2268     while ($v_size != 0) {
    2269       $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
    2270       $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
    2271       @fwrite($this->zip_fd, $v_buffer, $v_read_size);
    2272       $v_size -= $v_read_size;
    2273     }
    2274 
    2275     // ----- Create the Central Dir files header
    2276     for ($i = 0, $v_count = 0; $i < sizeof($v_header_list); $i++) {
    2277       // ----- Create the file header
    2278       if ($v_header_list[$i]['status'] == 'ok') {
    2279         if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
    2280           fclose($v_zip_temp_fd);
    2281           $this->privCloseFd();
    2282           @unlink($v_zip_temp_name);
    2283           $this->privSwapBackMagicQuotes();
    2284 
    2285           // ----- Return
    2286           return $v_result;
    2287         }
    2288         $v_count++;
    2289       }
    2290 
    2291       // ----- Transform the header to a 'usable' info
    2292       $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
    2293     }
    2294 
    2295     // ----- Zip file comment
    2296     $v_comment = $v_central_dir['comment'];
    2297     if (isset($p_options[PCLZIP_OPT_COMMENT])) {
    2298       $v_comment = $p_options[PCLZIP_OPT_COMMENT];
    2299     }
    2300     if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
    2301       $v_comment = $v_comment . $p_options[PCLZIP_OPT_ADD_COMMENT];
    2302     }
    2303     if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
    2304       $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT] . $v_comment;
    2305     }
    2306 
    2307     // ----- Calculate the size of the central header
    2308     $v_size = @ftell($this->zip_fd) - $v_offset;
    2309 
    2310     // ----- Create the central dir footer
    2311     if (($v_result = $this->privWriteCentralHeader($v_count + $v_central_dir['entries'], $v_size, $v_offset,
    2312             $v_comment)) != 1
    2313     ) {
    2314       // ----- Reset the file list
    2315       unset($v_header_list);
    2316       $this->privSwapBackMagicQuotes();
    2317 
    2318       // ----- Return
    2319       return $v_result;
    2320     }
    2321 
    2322     // ----- Swap back the file descriptor
    2323     $v_swap = $this->zip_fd;
    2324     $this->zip_fd = $v_zip_temp_fd;
    2325     $v_zip_temp_fd = $v_swap;
    2326 
    2327     // ----- Close
    2328     $this->privCloseFd();
    2329 
    2330     // ----- Close the temporary file
    2331     @fclose($v_zip_temp_fd);
    2332 
    2333     // ----- Magic quotes trick
    2334     $this->privSwapBackMagicQuotes();
    2335 
    2336     // ----- Delete the zip file
    2337     // TBC : I should test the result ...
    2338     @unlink($this->zipname);
    2339 
    2340     // ----- Rename the temporary file
    2341     // TBC : I should test the result ...
    2342     //@rename($v_zip_temp_name, $this->zipname);
    2343     PclZipUtilRename($v_zip_temp_name, $this->zipname);
    2344 
    2345     // ----- Return
    2346     return $v_result;
    2347   }
    2348   // --------------------------------------------------------------------------------
    2349 
    2350   // --------------------------------------------------------------------------------
    2351   // Function : privOpenFd()
    2352   // Description :
    2353   // Parameters :
    2354   // --------------------------------------------------------------------------------
    2355   public function privOpenFd($p_mode) {
    2356     $v_result = 1;
    2357 
    2358     // ----- Look if already open
    2359     if ($this->zip_fd != 0) {
    2360       // ----- Error log
    2361       PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \'' . $this->zipname . '\' already open');
    2362 
    2363       // ----- Return
    2364       return PclZip::errorCode();
    2365     }
    2366 
    2367     // ----- Open the zip file
    2368     if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) {
    2369       // ----- Error log
    2370       PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL,
    2371           'Unable to open archive \'' . $this->zipname . '\' in ' . $p_mode . ' mode');
    2372 
    2373       // ----- Return
    2374       return PclZip::errorCode();
    2375     }
    2376 
    2377     // ----- Return
    2378     return $v_result;
    2379   }
    2380   // --------------------------------------------------------------------------------
    2381 
    2382   // --------------------------------------------------------------------------------
    2383   // Function : privCloseFd()
    2384   // Description :
    2385   // Parameters :
    2386   // --------------------------------------------------------------------------------
    2387   public function privCloseFd() {
    2388     $v_result = 1;
    2389 
    2390     if ($this->zip_fd != 0) {
    2391       @fclose($this->zip_fd);
    2392     }
    2393     $this->zip_fd = 0;
    2394 
    2395     // ----- Return
    2396     return $v_result;
    2397   }
    2398   // --------------------------------------------------------------------------------
    2399 
    2400   // --------------------------------------------------------------------------------
    2401   // Function : privAddList()
    2402   // Description :
    2403   //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
    2404   //   different from the real path of the file. This is usefull if you want to have PclTar
    2405   //   running in any directory, and memorize relative path from an other directory.
    2406   // Parameters :
    2407   //   $p_list : An array containing the file or directory names to add in the tar
    2408   //   $p_result_list : list of added files with their properties (specially the status field)
    2409   //   $p_add_dir : Path to add in the filename path archived
    2410   //   $p_remove_dir : Path to remove in the filename path archived
    2411   // Return Values :
    2412   // --------------------------------------------------------------------------------
     1343        // --------------------------------------------------------------------------------
     1344        // Function : privCheckFormat()
     1345        // Description :
     1346        //   This method check that the archive exists and is a valid zip archive.
     1347        //   Several level of check exists. (futur)
     1348        // Parameters :
     1349        //   $p_level : Level of check. Default 0.
     1350        //              0 : Check the first bytes (magic codes) (default value))
     1351        //              1 : 0 + Check the central directory (futur)
     1352        //              2 : 1 + Check each file header (futur)
     1353        // Return Values :
     1354        //   true on success,
     1355        //   false on error, the error code is set.
     1356        // --------------------------------------------------------------------------------
     1357        public function privCheckFormat($p_level = 0) {
     1358                $v_result = true;
     1359
     1360                // ----- Reset the file system cache
     1361                clearstatcache();
     1362
     1363                // ----- Reset the error handler
     1364                $this->privErrorReset();
     1365
     1366                // ----- Look if the file exits
     1367                if (!is_file($this->zipname)) {
     1368                        // ----- Error log
     1369                        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '" . $this->zipname . "'");
     1370
     1371                        return (false);
     1372                }
     1373
     1374                // ----- Check that the file is readeable
     1375                if (!is_readable($this->zipname)) {
     1376                        // ----- Error log
     1377                        PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '" . $this->zipname . "'");
     1378
     1379                        return (false);
     1380                }
     1381
     1382                // ----- Check the magic code
     1383                // TBC
     1384
     1385                // ----- Check the central header
     1386                // TBC
     1387
     1388                // ----- Check each file header
     1389                // TBC
     1390
     1391                // ----- Return
     1392                return $v_result;
     1393        }
     1394        // --------------------------------------------------------------------------------
     1395
     1396        // --------------------------------------------------------------------------------
     1397        // Function : privParseOptions()
     1398        // Description :
     1399        //   This internal methods reads the variable list of arguments ($p_options_list,
     1400        //   $p_size) and generate an array with the options and values ($v_result_list).
     1401        //   $v_requested_options contains the options that can be present and those that
     1402        //   must be present.
     1403        //   $v_requested_options is an array, with the option value as key, and 'optional',
     1404        //   or 'mandatory' as value.
     1405        // Parameters :
     1406        //   See above.
     1407        // Return Values :
     1408        //   1 on success.
     1409        //   0 on failure.
     1410        // --------------------------------------------------------------------------------
     1411        public function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options = false) {
     1412                $v_result = 1;
     1413
     1414                // ----- Read the options
     1415                $i = 0;
     1416                while ($i < $p_size) {
     1417
     1418                        // ----- Check if the option is supported
     1419                        if (!isset($v_requested_options[$p_options_list[$i]])) {
     1420                                // ----- Error log
     1421                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1422                                        "Invalid optional parameter '" . $p_options_list[$i] . "' for this method");
     1423
     1424                                // ----- Return
     1425                                return PclZip::errorCode();
     1426                        }
     1427
     1428                        // ----- Look for next option
     1429                        switch ($p_options_list[$i]) {
     1430                                // ----- Look for options that request a path value
     1431                                case PCLZIP_OPT_PATH :
     1432                                case PCLZIP_OPT_REMOVE_PATH :
     1433                                case PCLZIP_OPT_ADD_PATH :
     1434                                        // ----- Check the number of parameters
     1435                                        if (($i + 1) >= $p_size) {
     1436                                                // ----- Error log
     1437                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1438                                                        "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1439
     1440                                                // ----- Return
     1441                                                return PclZip::errorCode();
     1442                                        }
     1443
     1444                                        // ----- Get the value
     1445                                        $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i + 1], false);
     1446                                        $i++;
     1447                                        break;
     1448
     1449                                case PCLZIP_OPT_TEMP_FILE_THRESHOLD :
     1450                                        // ----- Check the number of parameters
     1451                                        if (($i + 1) >= $p_size) {
     1452                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1453                                                        "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1454
     1455                                                return PclZip::errorCode();
     1456                                        }
     1457
     1458                                        // ----- Check for incompatible options
     1459                                        if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
     1460                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1461                                                        "Option '" . PclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
     1462
     1463                                                return PclZip::errorCode();
     1464                                        }
     1465
     1466                                        // ----- Check the value
     1467                                        $v_value = $p_options_list[$i + 1];
     1468                                        if ((!is_integer($v_value)) || ($v_value < 0)) {
     1469                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
     1470                                                        "Integer expected for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1471
     1472                                                return PclZip::errorCode();
     1473                                        }
     1474
     1475                                        // ----- Get the value (and convert it in bytes)
     1476                                        $v_result_list[$p_options_list[$i]] = $v_value * 1048576;
     1477                                        $i++;
     1478                                        break;
     1479
     1480                                case PCLZIP_OPT_TEMP_FILE_ON :
     1481                                        // ----- Check for incompatible options
     1482                                        if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
     1483                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1484                                                        "Option '" . PclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
     1485
     1486                                                return PclZip::errorCode();
     1487                                        }
     1488
     1489                                        $v_result_list[$p_options_list[$i]] = true;
     1490                                        break;
     1491
     1492                                case PCLZIP_OPT_TEMP_FILE_OFF :
     1493                                        // ----- Check for incompatible options
     1494                                        if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
     1495                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1496                                                        "Option '" . PclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
     1497
     1498                                                return PclZip::errorCode();
     1499                                        }
     1500                                        // ----- Check for incompatible options
     1501                                        if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
     1502                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1503                                                        "Option '" . PclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
     1504
     1505                                                return PclZip::errorCode();
     1506                                        }
     1507
     1508                                        $v_result_list[$p_options_list[$i]] = true;
     1509                                        break;
     1510
     1511                                case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
     1512                                        // ----- Check the number of parameters
     1513                                        if (($i + 1) >= $p_size) {
     1514                                                // ----- Error log
     1515                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1516                                                        "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1517
     1518                                                // ----- Return
     1519                                                return PclZip::errorCode();
     1520                                        }
     1521
     1522                                        // ----- Get the value
     1523                                        if (is_string($p_options_list[$i + 1])
     1524                                                && ($p_options_list[$i + 1] != '')
     1525                                        ) {
     1526                                                $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i + 1], false);
     1527                                                $i++;
     1528                                        } else {
     1529                                        }
     1530                                        break;
     1531
     1532                                // ----- Look for options that request an array of string for value
     1533                                case PCLZIP_OPT_BY_NAME :
     1534                                        // ----- Check the number of parameters
     1535                                        if (($i + 1) >= $p_size) {
     1536                                                // ----- Error log
     1537                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1538                                                        "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                                        } else {
     1548                                                if (is_array($p_options_list[$i + 1])) {
     1549                                                        $v_result_list[$p_options_list[$i]] = $p_options_list[$i + 1];
     1550                                                } else {
     1551                                                        // ----- Error log
     1552                                                        PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
     1553                                                                "Wrong parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1554
     1555                                                        // ----- Return
     1556                                                        return PclZip::errorCode();
     1557                                                }
     1558                                        }
     1559                                        $i++;
     1560                                        break;
     1561
     1562                                // ----- Look for options that request an EREG or PREG expression
     1563                                case PCLZIP_OPT_BY_EREG :
     1564                                        // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
     1565                                        // to PCLZIP_OPT_BY_PREG
     1566                                        $p_options_list[$i] = PCLZIP_OPT_BY_PREG;
     1567                                case PCLZIP_OPT_BY_PREG :
     1568                                        //case PCLZIP_OPT_CRYPT :
     1569                                        // ----- Check the number of parameters
     1570                                        if (($i + 1) >= $p_size) {
     1571                                                // ----- Error log
     1572                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1573                                                        "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1574
     1575                                                // ----- Return
     1576                                                return PclZip::errorCode();
     1577                                        }
     1578
     1579                                        // ----- Get the value
     1580                                        if (is_string($p_options_list[$i + 1])) {
     1581                                                $v_result_list[$p_options_list[$i]] = $p_options_list[$i + 1];
     1582                                        } else {
     1583                                                // ----- Error log
     1584                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
     1585                                                        "Wrong parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1586
     1587                                                // ----- Return
     1588                                                return PclZip::errorCode();
     1589                                        }
     1590                                        $i++;
     1591                                        break;
     1592
     1593                                // ----- Look for options that takes a string
     1594                                case PCLZIP_OPT_COMMENT :
     1595                                case PCLZIP_OPT_ADD_COMMENT :
     1596                                case PCLZIP_OPT_PREPEND_COMMENT :
     1597                                        // ----- Check the number of parameters
     1598                                        if (($i + 1) >= $p_size) {
     1599                                                // ----- Error log
     1600                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1601                                                        "Missing parameter value for option '"
     1602                                                        . PclZipUtilOptionText($p_options_list[$i])
     1603                                                        . "'");
     1604
     1605                                                // ----- Return
     1606                                                return PclZip::errorCode();
     1607                                        }
     1608
     1609                                        // ----- Get the value
     1610                                        if (is_string($p_options_list[$i + 1])) {
     1611                                                $v_result_list[$p_options_list[$i]] = $p_options_list[$i + 1];
     1612                                        } else {
     1613                                                // ----- Error log
     1614                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
     1615                                                        "Wrong parameter value for option '"
     1616                                                        . PclZipUtilOptionText($p_options_list[$i])
     1617                                                        . "'");
     1618
     1619                                                // ----- Return
     1620                                                return PclZip::errorCode();
     1621                                        }
     1622                                        $i++;
     1623                                        break;
     1624
     1625                                // ----- Look for options that request an array of index
     1626                                case PCLZIP_OPT_BY_INDEX :
     1627                                        // ----- Check the number of parameters
     1628                                        if (($i + 1) >= $p_size) {
     1629                                                // ----- Error log
     1630                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1631                                                        "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1632
     1633                                                // ----- Return
     1634                                                return PclZip::errorCode();
     1635                                        }
     1636
     1637                                        // ----- Get the value
     1638                                        $v_work_list = array();
     1639                                        if (is_string($p_options_list[$i + 1])) {
     1640
     1641                                                // ----- Remove spaces
     1642                                                $p_options_list[$i + 1] = strtr($p_options_list[$i + 1], ' ', '');
     1643
     1644                                                // ----- Parse items
     1645                                                $v_work_list = explode(",", $p_options_list[$i + 1]);
     1646                                        } else {
     1647                                                if (is_integer($p_options_list[$i + 1])) {
     1648                                                        $v_work_list[0] = $p_options_list[$i + 1] . '-' . $p_options_list[$i + 1];
     1649                                                } else {
     1650                                                        if (is_array($p_options_list[$i + 1])) {
     1651                                                                $v_work_list = $p_options_list[$i + 1];
     1652                                                        } else {
     1653                                                                // ----- Error log
     1654                                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
     1655                                                                        "Value must be integer, string or array for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1656
     1657                                                                // ----- Return
     1658                                                                return PclZip::errorCode();
     1659                                                        }
     1660                                                }
     1661                                        }
     1662
     1663                                        // ----- Reduce the index list
     1664                                        // each index item in the list must be a couple with a start and
     1665                                        // an end value : [0,3], [5-5], [8-10], ...
     1666                                        // ----- Check the format of each item
     1667                                        $v_sort_flag = false;
     1668                                        $v_sort_value = 0;
     1669                                        for ($j = 0; $j < sizeof($v_work_list); $j++) {
     1670                                                // ----- Explode the item
     1671                                                $v_item_list = explode("-", $v_work_list[$j]);
     1672                                                $v_size_item_list = sizeof($v_item_list);
     1673
     1674                                                // ----- TBC : Here we might check that each item is a
     1675                                                // real integer ...
     1676
     1677                                                // ----- Look for single value
     1678                                                if ($v_size_item_list == 1) {
     1679                                                        // ----- Set the option value
     1680                                                        $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
     1681                                                        $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
     1682                                                } elseif ($v_size_item_list == 2) {
     1683                                                        // ----- Set the option value
     1684                                                        $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
     1685                                                        $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
     1686                                                } else {
     1687                                                        // ----- Error log
     1688                                                        PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
     1689                                                                "Too many values in index range for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1690
     1691                                                        // ----- Return
     1692                                                        return PclZip::errorCode();
     1693                                                }
     1694
     1695
     1696                                                // ----- Look for list sort
     1697                                                if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
     1698                                                        $v_sort_flag = true;
     1699
     1700                                                        // ----- TBC : An automatic sort should be writen ...
     1701                                                        // ----- Error log
     1702                                                        PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
     1703                                                                "Invalid order of index range for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1704
     1705                                                        // ----- Return
     1706                                                        return PclZip::errorCode();
     1707                                                }
     1708                                                $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
     1709                                        }
     1710
     1711                                        // ----- Sort the items
     1712                                        if ($v_sort_flag) {
     1713                                                // TBC : To Be Completed
     1714                                        }
     1715
     1716                                        // ----- Next option
     1717                                        $i++;
     1718                                        break;
     1719
     1720                                // ----- Look for options that request no value
     1721                                case PCLZIP_OPT_REMOVE_ALL_PATH :
     1722                                case PCLZIP_OPT_EXTRACT_AS_STRING :
     1723                                case PCLZIP_OPT_NO_COMPRESSION :
     1724                                case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
     1725                                case PCLZIP_OPT_REPLACE_NEWER :
     1726                                case PCLZIP_OPT_STOP_ON_ERROR :
     1727                                        $v_result_list[$p_options_list[$i]] = true;
     1728                                        break;
     1729
     1730                                // ----- Look for options that request an octal value
     1731                                case PCLZIP_OPT_SET_CHMOD :
     1732                                        // ----- Check the number of parameters
     1733                                        if (($i + 1) >= $p_size) {
     1734                                                // ----- Error log
     1735                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1736                                                        "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1737
     1738                                                // ----- Return
     1739                                                return PclZip::errorCode();
     1740                                        }
     1741
     1742                                        // ----- Get the value
     1743                                        $v_result_list[$p_options_list[$i]] = $p_options_list[$i + 1];
     1744                                        $i++;
     1745                                        break;
     1746
     1747                                // ----- Look for options that request a call-back
     1748                                case PCLZIP_CB_PRE_EXTRACT :
     1749                                case PCLZIP_CB_POST_EXTRACT :
     1750                                case PCLZIP_CB_PRE_ADD :
     1751                                case PCLZIP_CB_POST_ADD :
     1752                                        /* for futur use
     1753                                        case PCLZIP_CB_PRE_DELETE :
     1754                                        case PCLZIP_CB_POST_DELETE :
     1755                                        case PCLZIP_CB_PRE_LIST :
     1756                                        case PCLZIP_CB_POST_LIST :
     1757                                        */
     1758                                        // ----- Check the number of parameters
     1759                                        if (($i + 1) >= $p_size) {
     1760                                                // ----- Error log
     1761                                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
     1762                                                        "Missing parameter value for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1763
     1764                                                // ----- Return
     1765                                                return PclZip::errorCode();
     1766                                        }
     1767
     1768                                        // ----- Get the value
     1769                                        $v_function_name = $p_options_list[$i + 1];
     1770
     1771                                        // ----- Check that the value is a valid existing function
     1772                                        if (!function_exists($v_function_name)) {
     1773                                                // ----- Error log
     1774                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
     1775                                                        "Function '" . $v_function_name . "()' is not an existing function for option '" . PclZipUtilOptionText($p_options_list[$i]) . "'");
     1776
     1777                                                // ----- Return
     1778                                                return PclZip::errorCode();
     1779                                        }
     1780
     1781                                        // ----- Set the attribute
     1782                                        $v_result_list[$p_options_list[$i]] = $v_function_name;
     1783                                        $i++;
     1784                                        break;
     1785
     1786                                default :
     1787                                        // ----- Error log
     1788                                        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1789                                                "Unknown parameter '"
     1790                                                . $p_options_list[$i] . "'");
     1791
     1792                                        // ----- Return
     1793                                        return PclZip::errorCode();
     1794                        }
     1795
     1796                        // ----- Next options
     1797                        $i++;
     1798                }
     1799
     1800                // ----- Look for mandatory options
     1801                if ($v_requested_options !== false) {
     1802                        for ($key = reset($v_requested_options); $key = key($v_requested_options); $key = next($v_requested_options)) {
     1803                                // ----- Look for mandatory option
     1804                                if ($v_requested_options[$key] == 'mandatory') {
     1805                                        // ----- Look if present
     1806                                        if (!isset($v_result_list[$key])) {
     1807                                                // ----- Error log
     1808                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1809                                                        "Missing mandatory parameter " . PclZipUtilOptionText($key) . "(" . $key . ")");
     1810
     1811                                                // ----- Return
     1812                                                return PclZip::errorCode();
     1813                                        }
     1814                                }
     1815                        }
     1816                }
     1817
     1818                // ----- Look for default values
     1819                if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
     1820
     1821                }
     1822
     1823                // ----- Return
     1824                return $v_result;
     1825        }
     1826        // --------------------------------------------------------------------------------
     1827
     1828        // --------------------------------------------------------------------------------
     1829        // Function : privOptionDefaultThreshold()
     1830        // Description :
     1831        // Parameters :
     1832        // Return Values :
     1833        // --------------------------------------------------------------------------------
     1834        public function privOptionDefaultThreshold(&$p_options) {
     1835                $v_result = 1;
     1836
     1837                if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
     1838                        || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])
     1839                ) {
     1840                        return $v_result;
     1841                }
     1842
     1843                // ----- Get 'memory_limit' configuration value
     1844                $v_memory_limit = ini_get('memory_limit');
     1845                $v_memory_limit = trim($v_memory_limit);
     1846                $last = strtolower(substr($v_memory_limit, -1));
     1847                $v_memory_limit = strtolower(substr($v_memory_limit, 0, -1));
     1848
     1849                if ($last == 'g') //$v_memory_limit = $v_memory_limit*1024*1024*1024;
     1850                {
     1851                        $v_memory_limit = $v_memory_limit * 1073741824;
     1852                }
     1853                if ($last == 'm') //$v_memory_limit = $v_memory_limit*1024*1024;
     1854                {
     1855                        $v_memory_limit = $v_memory_limit * 1048576;
     1856                }
     1857                if ($last == 'k') {
     1858                        $v_memory_limit = $v_memory_limit * 1024;
     1859                }
     1860
     1861                $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit * PCLZIP_TEMPORARY_FILE_RATIO);
     1862
     1863
     1864                // ----- Sanity check : No threshold if value lower than 1M
     1865                if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
     1866                        unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
     1867                }
     1868
     1869                // ----- Return
     1870                return $v_result;
     1871        }
     1872        // --------------------------------------------------------------------------------
     1873
     1874        // --------------------------------------------------------------------------------
     1875        // Function : privFileDescrParseAtt()
     1876        // Description :
     1877        // Parameters :
     1878        // Return Values :
     1879        //   1 on success.
     1880        //   0 on failure.
     1881        // --------------------------------------------------------------------------------
     1882        public function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options = false) {
     1883                $v_result = 1;
     1884
     1885                // ----- For each file in the list check the attributes
     1886                foreach ($p_file_list as $v_key => $v_value) {
     1887
     1888                        // ----- Check if the option is supported
     1889                        if (!isset($v_requested_options[$v_key])) {
     1890                                // ----- Error log
     1891                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '" . $v_key . "' for this file");
     1892
     1893                                // ----- Return
     1894                                return PclZip::errorCode();
     1895                        }
     1896
     1897                        // ----- Look for attribute
     1898                        switch ($v_key) {
     1899                                case PCLZIP_ATT_FILE_NAME :
     1900                                        if (!is_string($v_value)) {
     1901                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
     1902                                                        "Invalid type " . gettype($v_value) . ". String expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
     1903
     1904                                                return PclZip::errorCode();
     1905                                        }
     1906
     1907                                        $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
     1908
     1909                                        if ($p_filedescr['filename'] == '') {
     1910                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
     1911                                                        "Invalid empty filename for attribute '" . PclZipUtilOptionText($v_key) . "'");
     1912
     1913                                                return PclZip::errorCode();
     1914                                        }
     1915
     1916                                        break;
     1917
     1918                                case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
     1919                                        if (!is_string($v_value)) {
     1920                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
     1921                                                        "Invalid type " . gettype($v_value) . ". String expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
     1922
     1923                                                return PclZip::errorCode();
     1924                                        }
     1925
     1926                                        $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
     1927
     1928                                        if ($p_filedescr['new_short_name'] == '') {
     1929                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
     1930                                                        "Invalid empty short filename for attribute '" . PclZipUtilOptionText($v_key) . "'");
     1931
     1932                                                return PclZip::errorCode();
     1933                                        }
     1934                                        break;
     1935
     1936                                case PCLZIP_ATT_FILE_NEW_FULL_NAME :
     1937                                        if (!is_string($v_value)) {
     1938                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
     1939                                                        "Invalid type " . gettype($v_value) . ". String expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
     1940
     1941                                                return PclZip::errorCode();
     1942                                        }
     1943
     1944                                        $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
     1945
     1946                                        if ($p_filedescr['new_full_name'] == '') {
     1947                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
     1948                                                        "Invalid empty full filename for attribute '" . PclZipUtilOptionText($v_key) . "'");
     1949
     1950                                                return PclZip::errorCode();
     1951                                        }
     1952                                        break;
     1953
     1954                                // ----- Look for options that takes a string
     1955                                case PCLZIP_ATT_FILE_COMMENT :
     1956                                        if (!is_string($v_value)) {
     1957                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
     1958                                                        "Invalid type " . gettype($v_value) . ". String expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
     1959
     1960                                                return PclZip::errorCode();
     1961                                        }
     1962
     1963                                        $p_filedescr['comment'] = $v_value;
     1964                                        break;
     1965
     1966                                case PCLZIP_ATT_FILE_MTIME :
     1967                                        if (!is_integer($v_value)) {
     1968                                                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE,
     1969                                                        "Invalid type " . gettype($v_value) . ". Integer expected for attribute '" . PclZipUtilOptionText($v_key) . "'");
     1970
     1971                                                return PclZip::errorCode();
     1972                                        }
     1973
     1974                                        $p_filedescr['mtime'] = $v_value;
     1975                                        break;
     1976
     1977                                case PCLZIP_ATT_FILE_CONTENT :
     1978                                        $p_filedescr['content'] = $v_value;
     1979                                        break;
     1980
     1981                                default :
     1982                                        // ----- Error log
     1983                                        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1984                                                "Unknown parameter '" . $v_key . "'");
     1985
     1986                                        // ----- Return
     1987                                        return PclZip::errorCode();
     1988                        }
     1989
     1990                        // ----- Look for mandatory options
     1991                        if ($v_requested_options !== false) {
     1992                                for ($key = reset($v_requested_options); $key = key($v_requested_options); $key = next($v_requested_options)) {
     1993                                        // ----- Look for mandatory option
     1994                                        if ($v_requested_options[$key] == 'mandatory') {
     1995                                                // ----- Look if present
     1996                                                if (!isset($p_file_list[$key])) {
     1997                                                        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
     1998                                                                "Missing mandatory parameter " . PclZipUtilOptionText($key) . "(" . $key . ")");
     1999
     2000                                                        return PclZip::errorCode();
     2001                                                }
     2002                                        }
     2003                                }
     2004                        }
     2005
     2006                        // end foreach
     2007                }
     2008
     2009                // ----- Return
     2010                return $v_result;
     2011        }
     2012        // --------------------------------------------------------------------------------
     2013
     2014        // --------------------------------------------------------------------------------
     2015        // Function : privFileDescrExpand()
     2016        // Description :
     2017        //   This method look for each item of the list to see if its a file, a folder
     2018        //   or a string to be added as file. For any other type of files (link, other)
     2019        //   just ignore the item.
     2020        //   Then prepare the information that will be stored for that file.
     2021        //   When its a folder, expand the folder with all the files that are in that
     2022        //   folder (recursively).
     2023        // Parameters :
     2024        // Return Values :
     2025        //   1 on success.
     2026        //   0 on failure.
     2027        // --------------------------------------------------------------------------------
     2028        public function privFileDescrExpand(&$p_filedescr_list, &$p_options) {
     2029                $v_result = 1;
     2030
     2031                // ----- Create a result list
     2032                $v_result_list = array();
     2033
     2034                // ----- Look each entry
     2035                for ($i = 0; $i < sizeof($p_filedescr_list); $i++) {
     2036
     2037                        // ----- Get filedescr
     2038                        $v_descr = $p_filedescr_list[$i];
     2039
     2040                        // ----- Reduce the filename
     2041                        $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
     2042                        $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
     2043
     2044                        // ----- Look for real file or folder
     2045                        if (file_exists($v_descr['filename'])) {
     2046                                if (@is_file($v_descr['filename'])) {
     2047                                        $v_descr['type'] = 'file';
     2048                                } else {
     2049                                        if (@is_dir($v_descr['filename'])) {
     2050                                                $v_descr['type'] = 'folder';
     2051                                        } else {
     2052                                                if (@is_link($v_descr['filename'])) {
     2053                                                        // skip
     2054                                                        continue;
     2055                                                } else {
     2056                                                        // skip
     2057                                                        continue;
     2058                                                }
     2059                                        }
     2060                                }
     2061                        } // ----- Look for string added as file
     2062                        else {
     2063                                if (isset($v_descr['content'])) {
     2064                                        $v_descr['type'] = 'virtual_file';
     2065                                } // ----- Missing file
     2066                                else {
     2067                                        // ----- Error log
     2068                                        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '" . $v_descr['filename'] . "' does not exist");
     2069
     2070                                        // ----- Return
     2071                                        return PclZip::errorCode();
     2072                                }
     2073                        }
     2074
     2075                        // ----- Calculate the stored filename
     2076                        $this->privCalculateStoredFilename($v_descr, $p_options);
     2077
     2078                        // ----- Add the descriptor in result list
     2079                        $v_result_list[sizeof($v_result_list)] = $v_descr;
     2080
     2081                        // ----- Look for folder
     2082                        if ($v_descr['type'] == 'folder') {
     2083                                // ----- List of items in folder
     2084                                $v_dirlist_descr = array();
     2085                                $v_dirlist_nb = 0;
     2086                                if ($v_folder_handler = opendir($v_descr['filename'])) {
     2087                                        while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
     2088
     2089                                                // ----- Skip '.' and '..'
     2090                                                if (($v_item_handler == '.') || ($v_item_handler == '..')) {
     2091                                                        continue;
     2092                                                }
     2093
     2094                                                // ----- Compose the full filename
     2095                                                $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'] . '/' . $v_item_handler;
     2096
     2097                                                // ----- Look for different stored filename
     2098                                                // Because the name of the folder was changed, the name of the
     2099                                                // files/sub-folders also change
     2100                                                if (($v_descr['stored_filename'] != $v_descr['filename'])
     2101                                                        && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
     2102                                                ) {
     2103                                                        if ($v_descr['stored_filename'] != '') {
     2104                                                                $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'] . '/' . $v_item_handler;
     2105                                                        } else {
     2106                                                                $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
     2107                                                        }
     2108                                                }
     2109
     2110                                                $v_dirlist_nb++;
     2111                                        }
     2112
     2113                                        @closedir($v_folder_handler);
     2114                                } else {
     2115                                        // TBC : unable to open folder in read mode
     2116                                }
     2117
     2118                                // ----- Expand each element of the list
     2119                                if ($v_dirlist_nb != 0) {
     2120                                        // ----- Expand
     2121                                        if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
     2122                                                return $v_result;
     2123                                        }
     2124
     2125                                        // ----- Concat the resulting list
     2126                                        $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
     2127                                } else {
     2128                                }
     2129
     2130                                // ----- Free local array
     2131                                unset($v_dirlist_descr);
     2132                        }
     2133                }
     2134
     2135                // ----- Get the result list
     2136                $p_filedescr_list = $v_result_list;
     2137
     2138                // ----- Return
     2139                return $v_result;
     2140        }
     2141        // --------------------------------------------------------------------------------
     2142
     2143        // --------------------------------------------------------------------------------
     2144        // Function : privCreate()
     2145        // Description :
     2146        // Parameters :
     2147        // Return Values :
     2148        // --------------------------------------------------------------------------------
     2149        public function privCreate($p_filedescr_list, &$p_result_list, &$p_options) {
     2150                $v_result = 1;
     2151                $v_list_detail = array();
     2152
     2153                // ----- Magic quotes trick
     2154                $this->privDisableMagicQuotes();
     2155
     2156                // ----- Open the file in write mode
     2157                if (($v_result = $this->privOpenFd('wb')) != 1) {
     2158                        // ----- Return
     2159                        return $v_result;
     2160                }
     2161
     2162                // ----- Add the list of files
     2163                $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
     2164
     2165                // ----- Close
     2166                $this->privCloseFd();
     2167
     2168                // ----- Magic quotes trick
     2169                $this->privSwapBackMagicQuotes();
     2170
     2171                // ----- Return
     2172                return $v_result;
     2173        }
     2174        // --------------------------------------------------------------------------------
     2175
     2176        // --------------------------------------------------------------------------------
     2177        // Function : privAdd()
     2178        // Description :
     2179        // Parameters :
     2180        // Return Values :
     2181        // --------------------------------------------------------------------------------
     2182        public function privAdd($p_filedescr_list, &$p_result_list, &$p_options) {
     2183                $v_result = 1;
     2184                $v_list_detail = array();
     2185
     2186                // ----- Look if the archive exists or is empty
     2187                if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) {
     2188
     2189                        // ----- Do a create
     2190                        $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
     2191
     2192                        // ----- Return
     2193                        return $v_result;
     2194                }
     2195                // ----- Magic quotes trick
     2196                $this->privDisableMagicQuotes();
     2197
     2198                // ----- Open the zip file
     2199                if (($v_result = $this->privOpenFd('rb')) != 1) {
     2200                        // ----- Magic quotes trick
     2201                        $this->privSwapBackMagicQuotes();
     2202
     2203                        // ----- Return
     2204                        return $v_result;
     2205                }
     2206
     2207                // ----- Read the central directory informations
     2208                $v_central_dir = array();
     2209                if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
     2210                        $this->privCloseFd();
     2211                        $this->privSwapBackMagicQuotes();
     2212
     2213                        return $v_result;
     2214                }
     2215
     2216                // ----- Go to beginning of File
     2217                @rewind($this->zip_fd);
     2218
     2219                // ----- Creates a temporay file
     2220                $v_zip_temp_name = PCLZIP_TEMPORARY_DIR . uniqid('pclzip-') . '.tmp';
     2221
     2222                // ----- Open the temporary file in write mode
     2223                if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) {
     2224                        $this->privCloseFd();
     2225                        $this->privSwapBackMagicQuotes();
     2226
     2227                        PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL,
     2228                                'Unable to open temporary file \'' . $v_zip_temp_name . '\' in binary write mode');
     2229
     2230                        // ----- Return
     2231                        return PclZip::errorCode();
     2232                }
     2233
     2234                // ----- Copy the files from the archive to the temporary file
     2235                // TBC : Here I should better append the file and go back to erase the central dir
     2236                $v_size = $v_central_dir['offset'];
     2237                while ($v_size != 0) {
     2238                        $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
     2239                        $v_buffer = fread($this->zip_fd, $v_read_size);
     2240                        @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
     2241                        $v_size -= $v_read_size;
     2242                }
     2243
     2244                // ----- Swap the file descriptor
     2245                // Here is a trick : I swap the temporary fd with the zip fd, in order to use
     2246                // the following methods on the temporary fil and not the real archive
     2247                $v_swap = $this->zip_fd;
     2248                $this->zip_fd = $v_zip_temp_fd;
     2249                $v_zip_temp_fd = $v_swap;
     2250
     2251                // ----- Add the files
     2252                $v_header_list = array();
     2253                if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) {
     2254                        fclose($v_zip_temp_fd);
     2255                        $this->privCloseFd();
     2256                        @unlink($v_zip_temp_name);
     2257                        $this->privSwapBackMagicQuotes();
     2258
     2259                        // ----- Return
     2260                        return $v_result;
     2261                }
     2262
     2263                // ----- Store the offset of the central dir
     2264                $v_offset = @ftell($this->zip_fd);
     2265
     2266                // ----- Copy the block of file headers from the old archive
     2267                $v_size = $v_central_dir['size'];
     2268                while ($v_size != 0) {
     2269                        $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
     2270                        $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
     2271                        @fwrite($this->zip_fd, $v_buffer, $v_read_size);
     2272                        $v_size -= $v_read_size;
     2273                }
     2274
     2275                // ----- Create the Central Dir files header
     2276                for ($i = 0, $v_count = 0; $i < sizeof($v_header_list); $i++) {
     2277                        // ----- Create the file header
     2278                        if ($v_header_list[$i]['status'] == 'ok') {
     2279                                if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
     2280                                        fclose($v_zip_temp_fd);
     2281                                        $this->privCloseFd();
     2282                                        @unlink($v_zip_temp_name);
     2283                                        $this->privSwapBackMagicQuotes();
     2284
     2285                                        // ----- Return
     2286                                        return $v_result;
     2287                                }
     2288                                $v_count++;
     2289                        }
     2290
     2291                        // ----- Transform the header to a 'usable' info
     2292                        $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
     2293                }
     2294
     2295                // ----- Zip file comment
     2296                $v_comment = $v_central_dir['comment'];
     2297                if (isset($p_options[PCLZIP_OPT_COMMENT])) {
     2298                        $v_comment = $p_options[PCLZIP_OPT_COMMENT];
     2299                }
     2300                if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
     2301                        $v_comment = $v_comment . $p_options[PCLZIP_OPT_ADD_COMMENT];
     2302                }
     2303                if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
     2304                        $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT] . $v_comment;
     2305                }
     2306
     2307                // ----- Calculate the size of the central header
     2308                $v_size = @ftell($this->zip_fd) - $v_offset;
     2309
     2310                // ----- Create the central dir footer
     2311                if (($v_result = $this->privWriteCentralHeader($v_count + $v_central_dir['entries'], $v_size, $v_offset,
     2312                                $v_comment)) != 1
     2313                ) {
     2314                        // ----- Reset the file list
     2315                        unset($v_header_list);
     2316                        $this->privSwapBackMagicQuotes();
     2317
     2318                        // ----- Return
     2319                        return $v_result;
     2320                }
     2321
     2322                // ----- Swap back the file descriptor
     2323                $v_swap = $this->zip_fd;
     2324                $this->zip_fd = $v_zip_temp_fd;
     2325                $v_zip_temp_fd = $v_swap;
     2326
     2327                // ----- Close
     2328                $this->privCloseFd();
     2329
     2330                // ----- Close the temporary file
     2331                @fclose($v_zip_temp_fd);
     2332
     2333                // ----- Magic quotes trick
     2334                $this->privSwapBackMagicQuotes();
     2335
     2336                // ----- Delete the zip file
     2337                // TBC : I should test the result ...
     2338                @unlink($this->zipname);
     2339
     2340                // ----- Rename the temporary file
     2341                // TBC : I should test the result ...
     2342                //@rename($v_zip_temp_name, $this->zipname);
     2343                PclZipUtilRename($v_zip_temp_name, $this->zipname);
     2344
     2345                // ----- Return
     2346                return $v_result;
     2347        }
     2348        // --------------------------------------------------------------------------------
     2349
     2350        // --------------------------------------------------------------------------------
     2351        // Function : privOpenFd()
     2352        // Description :
     2353        // Parameters :
     2354        // --------------------------------------------------------------------------------
     2355        public function privOpenFd($p_mode) {
     2356                $v_result = 1;
     2357
     2358                // ----- Look if already open
     2359                if ($this->zip_fd != 0) {
     2360                        // ----- Error log
     2361                        PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \'' . $this->zipname . '\' already open');
     2362
     2363                        // ----- Return
     2364                        return PclZip::errorCode();
     2365                }
     2366
     2367                // ----- Open the zip file
     2368                if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) {
     2369                        // ----- Error log
     2370                        PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL,
     2371                                'Unable to open archive \'' . $this->zipname . '\' in ' . $p_mode . ' mode');
     2372
     2373                        // ----- Return
     2374                        return PclZip::errorCode();
     2375                }
     2376
     2377                // ----- Return
     2378                return $v_result;
     2379        }
     2380        // --------------------------------------------------------------------------------
     2381
     2382        // --------------------------------------------------------------------------------
     2383        // Function : privCloseFd()
     2384        // Description :
     2385        // Parameters :
     2386        // --------------------------------------------------------------------------------
     2387        public function privCloseFd() {
     2388                $v_result = 1;
     2389
     2390                if ($this->zip_fd != 0) {
     2391                        @fclose($this->zip_fd);
     2392                }
     2393                $this->zip_fd = 0;
     2394
     2395                // ----- Return
     2396                return $v_result;
     2397        }
     2398        // --------------------------------------------------------------------------------
     2399
     2400        // --------------------------------------------------------------------------------
     2401        // Function : privAddList()
     2402        // Description :
     2403        //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
     2404        //   different from the real path of the file. This is usefull if you want to have PclTar
     2405        //   running in any directory, and memorize relative path from an other directory.
     2406        // Parameters :
     2407        //   $p_list : An array containing the file or directory names to add in the tar
     2408        //   $p_result_list : list of added files with their properties (specially the status field)
     2409        //   $p_add_dir : Path to add in the filename path archived
     2410        //   $p_remove_dir : Path to remove in the filename path archived
     2411        // Return Values :
     2412        // --------------------------------------------------------------------------------
    24132413//  function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
    2414   public function privAddList($p_filedescr_list, &$p_result_list, &$p_options) {
    2415     $v_result = 1;
    2416 
    2417     // ----- Add the files
    2418     $v_header_list = array();
    2419     if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) {
    2420       // ----- Return
    2421       return $v_result;
    2422     }
    2423 
    2424     // ----- Store the offset of the central dir
    2425     $v_offset = @ftell($this->zip_fd);
    2426 
    2427     // ----- Create the Central Dir files header
    2428     for ($i = 0, $v_count = 0; $i < sizeof($v_header_list); $i++) {
    2429       // ----- Create the file header
    2430       if ($v_header_list[$i]['status'] == 'ok') {
    2431         if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
    2432           // ----- Return
    2433           return $v_result;
    2434         }
    2435         $v_count++;
    2436       }
    2437 
    2438       // ----- Transform the header to a 'usable' info
    2439       $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
    2440     }
    2441 
    2442     // ----- Zip file comment
    2443     $v_comment = '';
    2444     if (isset($p_options[PCLZIP_OPT_COMMENT])) {
    2445       $v_comment = $p_options[PCLZIP_OPT_COMMENT];
    2446     }
    2447 
    2448     // ----- Calculate the size of the central header
    2449     $v_size = @ftell($this->zip_fd) - $v_offset;
    2450 
    2451     // ----- Create the central dir footer
    2452     if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) {
    2453       // ----- Reset the file list
    2454       unset($v_header_list);
    2455 
    2456       // ----- Return
    2457       return $v_result;
    2458     }
    2459 
    2460     // ----- Return
    2461     return $v_result;
    2462   }
    2463   // --------------------------------------------------------------------------------
    2464 
    2465   // --------------------------------------------------------------------------------
    2466   // Function : privAddFileList()
    2467   // Description :
    2468   // Parameters :
    2469   //   $p_filedescr_list : An array containing the file description
    2470   //                      or directory names to add in the zip
    2471   //   $p_result_list : list of added files with their properties (specially the status field)
    2472   // Return Values :
    2473   // --------------------------------------------------------------------------------
    2474   public function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) {
    2475     $v_result = 1;
    2476     $v_header = array();
    2477 
    2478     // ----- Recuperate the current number of elt in list
    2479     $v_nb = sizeof($p_result_list);
    2480 
    2481     // ----- Loop on the files
    2482     for ($j = 0; ($j < sizeof($p_filedescr_list)) && ($v_result == 1); $j++) {
    2483       // ----- Format the filename
    2484       $p_filedescr_list[$j]['filename']
    2485           = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
    2486 
    2487 
    2488       // ----- Skip empty file names
    2489       // TBC : Can this be possible ? not checked in DescrParseAtt ?
    2490       if ($p_filedescr_list[$j]['filename'] == "") {
    2491         continue;
    2492       }
    2493 
    2494       // ----- Check the filename
    2495       if (($p_filedescr_list[$j]['type'] != 'virtual_file')
    2496           && (!file_exists($p_filedescr_list[$j]['filename']))
    2497       ) {
    2498         PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE,
    2499             "File '" . $p_filedescr_list[$j]['filename'] . "' does not exist");
    2500 
    2501         return PclZip::errorCode();
    2502       }
    2503 
    2504       // ----- Look if it is a file or a dir with no all path remove option
    2505       // or a dir with all its path removed
     2414        public function privAddList($p_filedescr_list, &$p_result_list, &$p_options) {
     2415                $v_result = 1;
     2416
     2417                // ----- Add the files
     2418                $v_header_list = array();
     2419                if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) {
     2420                        // ----- Return
     2421                        return $v_result;
     2422                }
     2423
     2424                // ----- Store the offset of the central dir
     2425                $v_offset = @ftell($this->zip_fd);
     2426
     2427                // ----- Create the Central Dir files header
     2428                for ($i = 0, $v_count = 0; $i < sizeof($v_header_list); $i++) {
     2429                        // ----- Create the file header
     2430                        if ($v_header_list[$i]['status'] == 'ok') {
     2431                                if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
     2432                                        // ----- Return
     2433                                        return $v_result;
     2434                                }
     2435                                $v_count++;
     2436                        }
     2437
     2438                        // ----- Transform the header to a 'usable' info
     2439                        $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
     2440                }
     2441
     2442                // ----- Zip file comment
     2443                $v_comment = '';
     2444                if (isset($p_options[PCLZIP_OPT_COMMENT])) {
     2445                        $v_comment = $p_options[PCLZIP_OPT_COMMENT];
     2446                }
     2447
     2448                // ----- Calculate the size of the central header
     2449                $v_size = @ftell($this->zip_fd) - $v_offset;
     2450
     2451                // ----- Create the central dir footer
     2452                if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) {
     2453                        // ----- Reset the file list
     2454                        unset($v_header_list);
     2455
     2456                        // ----- Return
     2457                        return $v_result;
     2458                }
     2459
     2460                // ----- Return
     2461                return $v_result;
     2462        }
     2463        // --------------------------------------------------------------------------------
     2464
     2465        // --------------------------------------------------------------------------------
     2466        // Function : privAddFileList()
     2467        // Description :
     2468        // Parameters :
     2469        //   $p_filedescr_list : An array containing the file description
     2470        //                      or directory names to add in the zip
     2471        //   $p_result_list : list of added files with their properties (specially the status field)
     2472        // Return Values :
     2473        // --------------------------------------------------------------------------------
     2474        public function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) {
     2475                $v_result = 1;
     2476                $v_header = array();
     2477
     2478                // ----- Recuperate the current number of elt in list
     2479                $v_nb = sizeof($p_result_list);
     2480
     2481                // ----- Loop on the files
     2482                for ($j = 0; ($j < sizeof($p_filedescr_list)) && ($v_result == 1); $j++) {
     2483                        // ----- Format the filename
     2484                        $p_filedescr_list[$j]['filename']
     2485                                = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
     2486
     2487
     2488                        // ----- Skip empty file names
     2489                        // TBC : Can this be possible ? not checked in DescrParseAtt ?
     2490                        if ($p_filedescr_list[$j]['filename'] == "") {
     2491                                continue;
     2492                        }
     2493
     2494                        // ----- Check the filename
     2495                        if (($p_filedescr_list[$j]['type'] != 'virtual_file')
     2496                                && (!file_exists($p_filedescr_list[$j]['filename']))
     2497                        ) {
     2498                                PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE,
     2499                                        "File '" . $p_filedescr_list[$j]['filename'] . "' does not exist");
     2500
     2501                                return PclZip::errorCode();
     2502                        }
     2503
     2504                        // ----- Look if it is a file or a dir with no all path remove option
     2505                        // or a dir with all its path removed
    25062506//      if (   (is_file($p_filedescr_list[$j]['filename']))
    25072507//          || (   is_dir($p_filedescr_list[$j]['filename'])
    2508       if (($p_filedescr_list[$j]['type'] == 'file')
    2509           || ($p_filedescr_list[$j]['type'] == 'virtual_file')
    2510           || (($p_filedescr_list[$j]['type'] == 'folder')
    2511               && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
    2512                   || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
    2513       ) {
    2514 
    2515         // ----- Add the file
    2516         $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
    2517             $p_options);
    2518         if ($v_result != 1) {
    2519           return $v_result;
    2520         }
    2521 
    2522         // ----- Store the file infos
    2523         $p_result_list[$v_nb++] = $v_header;
    2524       }
    2525     }
    2526 
    2527     // ----- Return
    2528     return $v_result;
    2529   }
    2530   // --------------------------------------------------------------------------------
    2531 
    2532   // --------------------------------------------------------------------------------
    2533   // Function : privAddFile()
    2534   // Description :
    2535   // Parameters :
    2536   // Return Values :
    2537   // --------------------------------------------------------------------------------
    2538   public function privAddFile($p_filedescr, &$p_header, &$p_options) {
    2539     $v_result = 1;
    2540 
    2541     // ----- Working variable
    2542     $p_filename = $p_filedescr['filename'];
    2543 
    2544     // TBC : Already done in the fileAtt check ... ?
    2545     if ($p_filename == "") {
    2546       // ----- Error log
    2547       PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
    2548 
    2549       // ----- Return
    2550       return PclZip::errorCode();
    2551     }
    2552 
    2553     // ----- Look for a stored different filename
    2554     /* TBC : Removed
     2508                        if (($p_filedescr_list[$j]['type'] == 'file')
     2509                                || ($p_filedescr_list[$j]['type'] == 'virtual_file')
     2510                                || (($p_filedescr_list[$j]['type'] == 'folder')
     2511                                        && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
     2512                                                || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
     2513                        ) {
     2514
     2515                                // ----- Add the file
     2516                                $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
     2517                                        $p_options);
     2518                                if ($v_result != 1) {
     2519                                        return $v_result;
     2520                                }
     2521
     2522                                // ----- Store the file infos
     2523                                $p_result_list[$v_nb++] = $v_header;
     2524                        }
     2525                }
     2526
     2527                // ----- Return
     2528                return $v_result;
     2529        }
     2530        // --------------------------------------------------------------------------------
     2531
     2532        // --------------------------------------------------------------------------------
     2533        // Function : privAddFile()
     2534        // Description :
     2535        // Parameters :
     2536        // Return Values :
     2537        // --------------------------------------------------------------------------------
     2538        public function privAddFile($p_filedescr, &$p_header, &$p_options) {
     2539                $v_result = 1;
     2540
     2541                // ----- Working variable
     2542                $p_filename = $p_filedescr['filename'];
     2543
     2544                // TBC : Already done in the fileAtt check ... ?
     2545                if ($p_filename == "") {
     2546                        // ----- Error log
     2547                        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
     2548
     2549                        // ----- Return
     2550                        return PclZip::errorCode();
     2551                }
     2552
     2553                // ----- Look for a stored different filename
     2554                /* TBC : Removed
    25552555    if (isset($p_filedescr['stored_filename'])) {
    25562556      $v_stored_filename = $p_filedescr['stored_filename'];
     
    25612561    */
    25622562
    2563     // ----- Set the file properties
    2564     clearstatcache();
    2565     $p_header['version'] = 20;
    2566     $p_header['version_extracted'] = 10;
    2567     $p_header['flag'] = 0;
    2568     $p_header['compression'] = 0;
    2569     $p_header['crc'] = 0;
    2570     $p_header['compressed_size'] = 0;
    2571     $p_header['filename_len'] = strlen($p_filename);
    2572     $p_header['extra_len'] = 0;
    2573     $p_header['disk'] = 0;
    2574     $p_header['internal'] = 0;
    2575     $p_header['offset'] = 0;
    2576     $p_header['filename'] = $p_filename;
     2563                // ----- Set the file properties
     2564                clearstatcache();
     2565                $p_header['version'] = 20;
     2566                $p_header['version_extracted'] = 10;
     2567                $p_header['flag'] = 0;
     2568                $p_header['compression'] = 0;
     2569                $p_header['crc'] = 0;
     2570                $p_header['compressed_size'] = 0;
     2571                $p_header['filename_len'] = strlen($p_filename);
     2572                $p_header['extra_len'] = 0;
     2573                $p_header['disk'] = 0;
     2574                $p_header['internal'] = 0;
     2575                $p_header['offset'] = 0;
     2576                $p_header['filename'] = $p_filename;
    25772577// TBC : Removed    $p_header['stored_filename'] = $v_stored_filename;
    2578     $p_header['stored_filename'] = $p_filedescr['stored_filename'];
    2579     $p_header['extra'] = '';
    2580     $p_header['status'] = 'ok';
    2581     $p_header['index'] = -1;
    2582 
    2583     // ----- Look for regular file
    2584     if ($p_filedescr['type'] == 'file') {
    2585       $p_header['external'] = 0x00000000;
    2586       $p_header['size'] = filesize($p_filename);
    2587     } // ----- Look for regular folder
    2588     else {
    2589       if ($p_filedescr['type'] == 'folder') {
    2590         $p_header['external'] = 0x00000010;
    2591         $p_header['mtime'] = filemtime($p_filename);
    2592         $p_header['size'] = filesize($p_filename);
    2593       } // ----- Look for virtual file
    2594       else {
    2595         if ($p_filedescr['type'] == 'virtual_file') {
    2596           $p_header['external'] = 0x00000000;
    2597           $p_header['size'] = strlen($p_filedescr['content']);
    2598         }
    2599       }
    2600     }
    2601 
    2602 
    2603     // ----- Look for filetime
    2604     if (isset($p_filedescr['mtime'])) {
    2605       $p_header['mtime'] = $p_filedescr['mtime'];
    2606     } else {
    2607       if ($p_filedescr['type'] == 'virtual_file') {
    2608         $p_header['mtime'] = time();
    2609       } else {
    2610         $p_header['mtime'] = filemtime($p_filename);
    2611       }
    2612     }
    2613 
    2614     // ------ Look for file comment
    2615     if (isset($p_filedescr['comment'])) {
    2616       $p_header['comment_len'] = strlen($p_filedescr['comment']);
    2617       $p_header['comment'] = $p_filedescr['comment'];
    2618     } else {
    2619       $p_header['comment_len'] = 0;
    2620       $p_header['comment'] = '';
    2621     }
    2622 
    2623     // ----- Look for pre-add callback
    2624     if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
    2625 
    2626       // ----- Generate a local information
    2627       $v_local_header = array();
    2628       $this->privConvertHeader2FileInfo($p_header, $v_local_header);
    2629 
    2630       // ----- Call the callback
    2631       // Here I do not use call_user_func() because I need to send a reference to the
    2632       // header.
     2578                $p_header['stored_filename'] = $p_filedescr['stored_filename'];
     2579                $p_header['extra'] = '';
     2580                $p_header['status'] = 'ok';
     2581                $p_header['index'] = -1;
     2582
     2583                // ----- Look for regular file
     2584                if ($p_filedescr['type'] == 'file') {
     2585                        $p_header['external'] = 0x00000000;
     2586                        $p_header['size'] = filesize($p_filename);
     2587                } // ----- Look for regular folder
     2588                else {
     2589                        if ($p_filedescr['type'] == 'folder') {
     2590                                $p_header['external'] = 0x00000010;
     2591                                $p_header['mtime'] = filemtime($p_filename);
     2592                                $p_header['size'] = filesize($p_filename);
     2593                        } // ----- Look for virtual file
     2594                        else {
     2595                                if ($p_filedescr['type'] == 'virtual_file') {
     2596                                        $p_header['external'] = 0x00000000;
     2597                                        $p_header['size'] = strlen($p_filedescr['content']);
     2598                                }
     2599                        }
     2600                }
     2601
     2602
     2603                // ----- Look for filetime
     2604                if (isset($p_filedescr['mtime'])) {
     2605                        $p_header['mtime'] = $p_filedescr['mtime'];
     2606                } else {
     2607                        if ($p_filedescr['type'] == 'virtual_file') {
     2608                                $p_header['mtime'] = time();
     2609                        } else {
     2610                                $p_header['mtime'] = filemtime($p_filename);
     2611                        }
     2612                }
     2613
     2614                // ------ Look for file comment
     2615                if (isset($p_filedescr['comment'])) {
     2616                        $p_header['comment_len'] = strlen($p_filedescr['comment']);
     2617                        $p_header['comment'] = $p_filedescr['comment'];
     2618                } else {
     2619                        $p_header['comment_len'] = 0;
     2620                        $p_header['comment'] = '';
     2621                }
     2622
     2623                // ----- Look for pre-add callback
     2624                if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
     2625
     2626                        // ----- Generate a local information
     2627                        $v_local_header = array();
     2628                        $this->privConvertHeader2FileInfo($p_header, $v_local_header);
     2629
     2630                        // ----- Call the callback
     2631                        // Here I do not use call_user_func() because I need to send a reference to the
     2632                        // header.
    26332633//      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
    2634       $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
    2635       if ($v_result == 0) {
    2636         // ----- Change the file status
    2637         $p_header['status'] = "skipped";
    2638         $v_result = 1;
    2639       }
    2640 
    2641       // ----- Update the informations
    2642       // Only some fields can be modified
    2643       if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
    2644         $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
    2645       }
    2646     }
    2647 
    2648     // ----- Look for empty stored filename
    2649     if ($p_header['stored_filename'] == "") {
    2650       $p_header['status'] = "filtered";
    2651     }
    2652 
    2653     // ----- Check the path length
    2654     if (strlen($p_header['stored_filename']) > 0xFF) {
    2655       $p_header['status'] = 'filename_too_long';
    2656     }
    2657 
    2658     // ----- Look if no error, or file not skipped
    2659     if ($p_header['status'] == 'ok') {
    2660 
    2661       // ----- Look for a file
    2662       if ($p_filedescr['type'] == 'file') {
    2663         // ----- Look for using temporary file to zip
    2664         if ((!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
    2665             && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
    2666                 || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
    2667                     && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])))
    2668         ) {
    2669           $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
    2670           if ($v_result < PCLZIP_ERR_NO_ERROR) {
    2671             return $v_result;
    2672           }
    2673         } // ----- Use "in memory" zip algo
    2674         else {
    2675 
    2676           // ----- Open the source file
    2677           if (($v_file = @fopen($p_filename, "rb")) == 0) {
    2678             PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
    2679 
    2680             return PclZip::errorCode();
    2681           }
    2682 
    2683           // ----- Read the file content
    2684           $v_content = @fread($v_file, $p_header['size']);
    2685 
    2686           // ----- Close the file
    2687           @fclose($v_file);
    2688 
    2689           // ----- Calculate the CRC
    2690           $p_header['crc'] = @crc32($v_content);
    2691 
    2692           // ----- Look for no compression
    2693           if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
    2694             // ----- Set header parameters
    2695             $p_header['compressed_size'] = $p_header['size'];
    2696             $p_header['compression'] = 0;
    2697           } // ----- Look for normal compression
    2698           else {
    2699             // ----- Compress the content
    2700             $v_content = @gzdeflate($v_content);
    2701 
    2702             // ----- Set header parameters
    2703             $p_header['compressed_size'] = strlen($v_content);
    2704             $p_header['compression'] = 8;
    2705           }
    2706 
    2707           // ----- Call the header generation
    2708           if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
    2709             @fclose($v_file);
    2710 
    2711             return $v_result;
    2712           }
    2713 
    2714           // ----- Write the compressed (or not) content
    2715           @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
    2716 
    2717         }
    2718 
    2719       } // ----- Look for a virtual file (a file from string)
    2720       else {
    2721         if ($p_filedescr['type'] == 'virtual_file') {
    2722 
    2723           $v_content = $p_filedescr['content'];
    2724 
    2725           // ----- Calculate the CRC
    2726           $p_header['crc'] = @crc32($v_content);
    2727 
    2728           // ----- Look for no compression
    2729           if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
    2730             // ----- Set header parameters
    2731             $p_header['compressed_size'] = $p_header['size'];
    2732             $p_header['compression'] = 0;
    2733           } // ----- Look for normal compression
    2734           else {
    2735             // ----- Compress the content
    2736             $v_content = @gzdeflate($v_content);
    2737 
    2738             // ----- Set header parameters
    2739             $p_header['compressed_size'] = strlen($v_content);
    2740             $p_header['compression'] = 8;
    2741           }
    2742 
    2743           // ----- Call the header generation
    2744           if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
    2745             @fclose($v_file);
    2746 
    2747             return $v_result;
    2748           }
    2749 
    2750           // ----- Write the compressed (or not) content
    2751           @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
    2752         } // ----- Look for a directory
    2753         else {
    2754           if ($p_filedescr['type'] == 'folder') {
    2755             // ----- Look for directory last '/'
    2756             if (@substr($p_header['stored_filename'], -1) != '/') {
    2757               $p_header['stored_filename'] .= '/';
    2758             }
    2759 
    2760             // ----- Set the file properties
    2761             $p_header['size'] = 0;
    2762             //$p_header['external'] = 0x41FF0010;   // Value for a folder : to be checked
    2763             $p_header['external'] = 0x00000010;   // Value for a folder : to be checked
    2764 
    2765             // ----- Call the header generation
    2766             if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
    2767               return $v_result;
    2768             }
    2769           }
    2770         }
    2771       }
    2772     }
    2773 
    2774     // ----- Look for post-add callback
    2775     if (isset($p_options[PCLZIP_CB_POST_ADD])) {
    2776 
    2777       // ----- Generate a local information
    2778       $v_local_header = array();
    2779       $this->privConvertHeader2FileInfo($p_header, $v_local_header);
    2780 
    2781       // ----- Call the callback
    2782       // Here I do not use call_user_func() because I need to send a reference to the
    2783       // header.
     2634                        $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
     2635                        if ($v_result == 0) {
     2636                                // ----- Change the file status
     2637                                $p_header['status'] = "skipped";
     2638                                $v_result = 1;
     2639                        }
     2640
     2641                        // ----- Update the informations
     2642                        // Only some fields can be modified
     2643                        if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
     2644                                $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
     2645                        }
     2646                }
     2647
     2648                // ----- Look for empty stored filename
     2649                if ($p_header['stored_filename'] == "") {
     2650                        $p_header['status'] = "filtered";
     2651                }
     2652
     2653                // ----- Check the path length
     2654                if (strlen($p_header['stored_filename']) > 0xFF) {
     2655                        $p_header['status'] = 'filename_too_long';
     2656                }
     2657
     2658                // ----- Look if no error, or file not skipped
     2659                if ($p_header['status'] == 'ok') {
     2660
     2661                        // ----- Look for a file
     2662                        if ($p_filedescr['type'] == 'file') {
     2663                                // ----- Look for using temporary file to zip
     2664                                if ((!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
     2665                                        && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
     2666                                                || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
     2667                                                        && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])))
     2668                                ) {
     2669                                        $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
     2670                                        if ($v_result < PCLZIP_ERR_NO_ERROR) {
     2671                                                return $v_result;
     2672                                        }
     2673                                } // ----- Use "in memory" zip algo
     2674                                else {
     2675
     2676                                        // ----- Open the source file
     2677                                        if (($v_file = @fopen($p_filename, "rb")) == 0) {
     2678                                                PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
     2679
     2680                                                return PclZip::errorCode();
     2681                                        }
     2682
     2683                                        // ----- Read the file content
     2684                                        $v_content = @fread($v_file, $p_header['size']);
     2685
     2686                                        // ----- Close the file
     2687                                        @fclose($v_file);
     2688
     2689                                        // ----- Calculate the CRC
     2690                                        $p_header['crc'] = @crc32($v_content);
     2691
     2692                                        // ----- Look for no compression
     2693                                        if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
     2694                                                // ----- Set header parameters
     2695                                                $p_header['compressed_size'] = $p_header['size'];
     2696                                                $p_header['compression'] = 0;
     2697                                        } // ----- Look for normal compression
     2698                                        else {
     2699                                                // ----- Compress the content
     2700                                                $v_content = @gzdeflate($v_content);
     2701
     2702                                                // ----- Set header parameters
     2703                                                $p_header['compressed_size'] = strlen($v_content);
     2704                                                $p_header['compression'] = 8;
     2705                                        }
     2706
     2707                                        // ----- Call the header generation
     2708                                        if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
     2709                                                @fclose($v_file);
     2710
     2711                                                return $v_result;
     2712                                        }
     2713
     2714                                        // ----- Write the compressed (or not) content
     2715                                        @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
     2716
     2717                                }
     2718
     2719                        } // ----- Look for a virtual file (a file from string)
     2720                        else {
     2721                                if ($p_filedescr['type'] == 'virtual_file') {
     2722
     2723                                        $v_content = $p_filedescr['content'];
     2724
     2725                                        // ----- Calculate the CRC
     2726                                        $p_header['crc'] = @crc32($v_content);
     2727
     2728                                        // ----- Look for no compression
     2729                                        if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
     2730                                                // ----- Set header parameters
     2731                                                $p_header['compressed_size'] = $p_header['size'];
     2732                                                $p_header['compression'] = 0;
     2733                                        } // ----- Look for normal compression
     2734                                        else {
     2735                                                // ----- Compress the content
     2736                                                $v_content = @gzdeflate($v_content);
     2737
     2738                                                // ----- Set header parameters
     2739                                                $p_header['compressed_size'] = strlen($v_content);
     2740                                                $p_header['compression'] = 8;
     2741                                        }
     2742
     2743                                        // ----- Call the header generation
     2744                                        if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
     2745                                                @fclose($v_file);
     2746
     2747                                                return $v_result;
     2748                                        }
     2749
     2750                                        // ----- Write the compressed (or not) content
     2751                                        @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
     2752                                } // ----- Look for a directory
     2753                                else {
     2754                                        if ($p_filedescr['type'] == 'folder') {
     2755                                                // ----- Look for directory last '/'
     2756                                                if (@substr($p_header['stored_filename'], -1) != '/') {
     2757                                                        $p_header['stored_filename'] .= '/';
     2758                                                }
     2759
     2760                                                // ----- Set the file properties
     2761                                                $p_header['size'] = 0;
     2762                                                //$p_header['external'] = 0x41FF0010;   // Value