(file) Return to Zip.php CVS log (file) (dir) Up to [RizwankCVS] / geekymedia_web / photo / sspadmin / inc

   1 rizwank 1.1 <?php
   2             /* vim: set ts=4 sw=4: */
   3             // +----------------------------------------------------------------------+
   4             // | PHP Version 4                                                        |
   5             // +----------------------------------------------------------------------+
   6             // | Copyright (c) 1997-2003 The PHP Group                                |
   7             // +----------------------------------------------------------------------+
   8             // | This source file is subject to version 3.0 of the PHP license,       |
   9             // | that is bundled with this package in the file LICENSE, and is        |
  10             // | available through the world-wide-web at the following url:           |
  11             // | http://www.php.net/license/3_0.txt.                                  |
  12             // | If you did not receive a copy of the PHP license and are unable to   |
  13             // | obtain it through the world-wide-web, please send a note to          |
  14             // | license@php.net so we can mail you a copy immediately.               |
  15             // +----------------------------------------------------------------------+
  16             // | Author: Vincent Blavet <vincent@blavet.net>                          |
  17             // +----------------------------------------------------------------------+
  18             //
  19             // $Id: Zip.php,v 1.6 2004/02/26 15:33:36 vblavet Exp $
  20             
  21               require_once 'PEAR.php';
  22 rizwank 1.1 
  23               // ----- Constants
  24               define( 'ARCHIVE_ZIP_READ_BLOCK_SIZE', 2048 );
  25             
  26               // ----- File list separator
  27               define( 'ARCHIVE_ZIP_SEPARATOR', ',' );
  28             
  29               // ----- Optional static temporary directory
  30               //       By default temporary files are generated in the script current
  31               //       path.
  32               //       If defined :
  33               //       - MUST BE terminated by a '/'.
  34               //       - MUST be a valid, already created directory
  35               //       Samples :
  36               // define( 'ARCHIVE_ZIP_TEMPORARY_DIR', '/temp/' );
  37               // define( 'ARCHIVE_ZIP_TEMPORARY_DIR', 'C:/Temp/' );
  38               define( 'ARCHIVE_ZIP_TEMPORARY_DIR', '' );
  39             
  40               // ----- Error codes
  41               define( 'ARCHIVE_ZIP_ERR_NO_ERROR', 0 );
  42               define( 'ARCHIVE_ZIP_ERR_WRITE_OPEN_FAIL', -1 );
  43 rizwank 1.1   define( 'ARCHIVE_ZIP_ERR_READ_OPEN_FAIL', -2 );
  44               define( 'ARCHIVE_ZIP_ERR_INVALID_PARAMETER', -3 );
  45               define( 'ARCHIVE_ZIP_ERR_MISSING_FILE', -4 );
  46               define( 'ARCHIVE_ZIP_ERR_FILENAME_TOO_LONG', -5 );
  47               define( 'ARCHIVE_ZIP_ERR_INVALID_ZIP', -6 );
  48               define( 'ARCHIVE_ZIP_ERR_BAD_EXTRACTED_FILE', -7 );
  49               define( 'ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL', -8 );
  50               define( 'ARCHIVE_ZIP_ERR_BAD_EXTENSION', -9 );
  51               define( 'ARCHIVE_ZIP_ERR_BAD_FORMAT', -10 );
  52               define( 'ARCHIVE_ZIP_ERR_DELETE_FILE_FAIL', -11 );
  53               define( 'ARCHIVE_ZIP_ERR_RENAME_FILE_FAIL', -12 );
  54               define( 'ARCHIVE_ZIP_ERR_BAD_CHECKSUM', -13 );
  55               define( 'ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
  56               define( 'ARCHIVE_ZIP_ERR_MISSING_OPTION_VALUE', -15 );
  57               define( 'ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE', -16 );
  58             
  59               // ----- Warning codes
  60               define( 'ARCHIVE_ZIP_WARN_NO_WARNING', 0 );
  61               define( 'ARCHIVE_ZIP_WARN_FILE_EXIST', 1 );
  62             
  63               // ----- Methods parameters
  64 rizwank 1.1   define( 'ARCHIVE_ZIP_PARAM_PATH', 'path' );
  65               define( 'ARCHIVE_ZIP_PARAM_ADD_PATH', 'add_path' );
  66               define( 'ARCHIVE_ZIP_PARAM_REMOVE_PATH', 'remove_path' );
  67               define( 'ARCHIVE_ZIP_PARAM_REMOVE_ALL_PATH', 'remove_all_path' );
  68               define( 'ARCHIVE_ZIP_PARAM_SET_CHMOD', 'set_chmod' );
  69               define( 'ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING', 'extract_as_string' );
  70               define( 'ARCHIVE_ZIP_PARAM_NO_COMPRESSION', 'no_compression' );
  71               define( 'ARCHIVE_ZIP_PARAM_BY_NAME', 'by_name' );
  72               define( 'ARCHIVE_ZIP_PARAM_BY_INDEX', 'by_index' );
  73               define( 'ARCHIVE_ZIP_PARAM_BY_EREG', 'by_ereg' );
  74               define( 'ARCHIVE_ZIP_PARAM_BY_PREG', 'by_preg' );
  75             
  76               define( 'ARCHIVE_ZIP_PARAM_PRE_EXTRACT', 'callback_pre_extract' );
  77               define( 'ARCHIVE_ZIP_PARAM_POST_EXTRACT', 'callback_post_extract' );
  78               define( 'ARCHIVE_ZIP_PARAM_PRE_ADD', 'callback_pre_add' );
  79               define( 'ARCHIVE_ZIP_PARAM_POST_ADD', 'callback_post_add' );
  80             
  81             
  82             
  83             /**
  84             * Class for manipulating zip archive files
  85 rizwank 1.1 *
  86             * A class which provided common methods to manipulate ZIP formatted
  87             * archive files.
  88             * It provides creation, extraction, deletion and add features.
  89             *
  90             * @author   Vincent Blavet <vincent@blavet.net>
  91             * @version  $Revision: 1.6 $
  92             * @package  Archive_Zip
  93             * @category Archive
  94             */
  95             class Archive_Zip
  96             {
  97                 /**
  98                 * The filename of the zip archive.
  99                 *
 100                 * @var string Name of the Zip file
 101                 */
 102                 var $_zipname='';
 103             
 104                 /**
 105                 * File descriptor of the opened Zip file.
 106 rizwank 1.1     *
 107                 * @var int Internal zip file descriptor
 108                 */
 109                 var $_zip_fd=0;
 110             
 111                 /**
 112                 * @var int last error code
 113                 */
 114                 var $_error_code=1;
 115             
 116                 /**
 117                 * @var string Last error description
 118                 */
 119                 var $_error_string='';
 120             
 121                 // {{{ constructor
 122                 /**
 123                 * Archive_Zip Class constructor. This flavour of the constructor only
 124                 * declare a new Archive_Zip object, identifying it by the name of the
 125                 * zip file.
 126                 *
 127 rizwank 1.1     * @param    string  $p_zipname  The name of the zip archive to create
 128                 * @access public
 129                 */
 130                 function Archive_Zip($p_zipname)
 131                 {
 132             
 133                   // ----- Check the zlib
 134                   if (!extension_loaded('zlib')) {
 135                       PEAR::loadExtension('zlib');
 136                   }
 137                   if (!extension_loaded('zlib')) {
 138                       die("The extension 'zlib' couldn't be found.\n".
 139                           "Please make sure your version of PHP was built ".
 140                           "with 'zlib' support.\n");
 141                       return false;
 142                   }
 143             
 144                   // ----- Set the attributes
 145                   $this->_zipname = $p_zipname;
 146                   $this->_zip_fd = 0;
 147             
 148 rizwank 1.1       return;
 149                 }
 150                 // }}}
 151             
 152                 // {{{ create()
 153                 /**
 154                 * This method creates a Zip Archive with the filename set with
 155             	* the constructor.
 156             	* The files and directories indicated in $p_filelist
 157                 * are added in the archive.
 158             	* When a directory is in the list, the directory and its content is added
 159                 * in the archive.
 160                 * The methods takes a variable list of parameters in $p_params.
 161                 * The supported parameters for this method are :
 162                 *   'add_path' : Add a path to the archived files.
 163                 *   'remove_path' : Remove the specified 'root' path of the archived files.
 164                 *   'remove_all_path' : Remove all the path of the archived files.
 165                 *   'no_compression' : The archived files will not be compressed.
 166                 *
 167                 * @access public
 168                 * @param  mixed  $p_filelist  The list of the files or folders to add.
 169 rizwank 1.1     *                             It can be a string with filenames separated
 170                 *                             by a comma, or an array of filenames.
 171                 * @param  mixed  $p_params  An array of variable parameters and values.
 172                 * @return mixed An array of file description on success,
 173             	*               an error code on error
 174                 */
 175                 function create($p_filelist, $p_params=0)
 176                 {
 177                     $this->_errorReset();
 178             
 179                     // ----- Set default values
 180                     if ($p_params === 0) {
 181                 	    $p_params = array();
 182                     }
 183                     if ($this->_check_parameters($p_params,
 184             	                                 array('no_compression' => false,
 185             	                                       'add_path' => "",
 186             	                                       'remove_path' => "",
 187             	                                       'remove_all_path' => false)) != 1) {
 188             		    return 0;
 189             	    }
 190 rizwank 1.1 
 191                     // ----- Look if the $p_filelist is really an array
 192                     $p_result_list = array();
 193                     if (is_array($p_filelist)) {
 194                         $v_result = $this->_create($p_filelist, $p_result_list, $p_params);
 195                     }
 196             
 197                     // ----- Look if the $p_filelist is a string
 198                     else if (is_string($p_filelist)) {
 199                         // ----- Create a list with the elements from the string
 200                         $v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist);
 201             
 202                         $v_result = $this->_create($v_list, $p_result_list, $p_params);
 203                     }
 204             
 205                     // ----- Invalid variable
 206                     else {
 207                         $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
 208             	                         'Invalid variable type p_filelist');
 209                         $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER;
 210                     }
 211 rizwank 1.1 
 212                     if ($v_result != 1) {
 213                         return 0;
 214                     }
 215             
 216                     return $p_result_list;
 217                 }
 218                 // }}}
 219             
 220                 // {{{ add()
 221                 /**
 222                 * This method add files or directory in an existing Zip Archive.
 223                 * If the Zip Archive does not exist it is created.
 224             	* The files and directories to add are indicated in $p_filelist.
 225             	* When a directory is in the list, the directory and its content is added
 226                 * in the archive.
 227                 * The methods takes a variable list of parameters in $p_params.
 228                 * The supported parameters for this method are :
 229                 *   'add_path' : Add a path to the archived files.
 230                 *   'remove_path' : Remove the specified 'root' path of the archived files.
 231                 *   'remove_all_path' : Remove all the path of the archived files.
 232 rizwank 1.1     *   'no_compression' : The archived files will not be compressed.
 233                 *   'callback_pre_add' : A callback function that will be called before
 234                 *                        each entry archiving.
 235                 *   'callback_post_add' : A callback function that will be called after
 236                 *                         each entry archiving.
 237                 *
 238                 * @access public
 239                 * @param    mixed  $p_filelist  The list of the files or folders to add.
 240                 *                               It can be a string with filenames separated
 241                 *                               by a comma, or an array of filenames.
 242                 * @param    mixed  $p_params  An array of variable parameters and values.
 243                 * @return mixed An array of file description on success,
 244             	*               0 on an unrecoverable failure, an error code is logged.
 245                 */
 246                 function add($p_filelist, $p_params=0)
 247                 {
 248                     $this->_errorReset();
 249             
 250                     // ----- Set default values
 251                     if ($p_params === 0) {
 252                     	$p_params = array();
 253 rizwank 1.1         }
 254                     if ($this->_check_parameters($p_params,
 255             	                                 array ('no_compression' => false,
 256             	                                        'add_path' => '',
 257             	                                        'remove_path' => '',
 258             	                                        'remove_all_path' => false,
 259             						    	     		'callback_pre_add' => '',
 260             							    		    'callback_post_add' => '')) != 1) {
 261             		    return 0;
 262             	    }
 263             
 264                     // ----- Look if the $p_filelist is really an array
 265                     $p_result_list = array();
 266                     if (is_array($p_filelist)) {
 267                         // ----- Call the create fct
 268                         $v_result = $this->_add($p_filelist, $p_result_list, $p_params);
 269                     }
 270             
 271                     // ----- Look if the $p_filelist is a string
 272                     else if (is_string($p_filelist)) {
 273                         // ----- Create a list with the elements from the string
 274 rizwank 1.1             $v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist);
 275             
 276                         // ----- Call the create fct
 277                         $v_result = $this->_add($v_list, $p_result_list, $p_params);
 278                     }
 279             
 280                     // ----- Invalid variable
 281                     else {
 282                         $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
 283             	                         "add() : Invalid variable type p_filelist");
 284                         $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER;
 285                     }
 286             
 287                     if ($v_result != 1) {
 288                         return 0;
 289                     }
 290             
 291                     // ----- Return the result list
 292                     return $p_result_list;
 293                 }
 294                 // }}}
 295 rizwank 1.1 
 296                 // {{{ listContent()
 297                 /**
 298                 * This method gives the names and properties of the files and directories
 299             	* which are present in the zip archive.
 300                 * The properties of each entries in the list are :
 301                 *   filename : Name of the file.
 302             	*              For create() or add() it's the filename given by the user.
 303             	*              For an extract() it's the filename of the extracted file.
 304                 *   stored_filename : Name of the file / directory stored in the archive.
 305                 *   size : Size of the stored file.
 306                 *   compressed_size : Size of the file's data compressed in the archive
 307                 *                     (without the zip headers overhead)
 308                 *   mtime : Last known modification date of the file (UNIX timestamp)
 309                 *   comment : Comment associated with the file
 310                 *   folder : true | false (indicates if the entry is a folder)
 311                 *   index : index of the file in the archive (-1 when not available)
 312                 *   status : status of the action on the entry (depending of the action) :
 313                 *            Values are :
 314                 *              ok : OK !
 315                 *              filtered : the file/dir was not extracted (filtered by user)
 316 rizwank 1.1     *              already_a_directory : the file can't be extracted because a
 317                 *                                    directory with the same name already
 318             	*                                    exists
 319                 *              write_protected : the file can't be extracted because a file
 320                 *                                with the same name already exists and is
 321                 *                                write protected
 322                 *              newer_exist : the file was not extracted because a newer
 323             	*                            file already exists
 324                 *              path_creation_fail : the file is not extracted because the
 325             	*                                   folder does not exists and can't be
 326             	*                                   created
 327                 *              write_error : the file was not extracted because there was a
 328                 *                            error while writing the file
 329                 *              read_error : the file was not extracted because there was a
 330             	*                           error while reading the file
 331                 *              invalid_header : the file was not extracted because of an
 332             	*                               archive format error (bad file header)
 333                 * Note that each time a method can continue operating when there
 334                 * is an error on a single file, the error is only logged in the file status.
 335                 *
 336                 * @access public
 337 rizwank 1.1     * @return mixed An array of file description on success,
 338             	*               0 on an unrecoverable failure, an error code is logged.
 339                 */
 340                 function listContent()
 341                 {
 342                     $this->_errorReset();
 343             
 344                     // ----- Check archive
 345                     if (!$this->_checkFormat()) {
 346                         return(0);
 347                     }
 348             
 349                     $v_list = array();
 350                     if ($this->_list($v_list) != 1) {
 351                         unset($v_list);
 352                         return(0);
 353                     }
 354             
 355                     return $v_list;
 356                 }
 357                 // }}}
 358 rizwank 1.1 
 359                 // {{{ extract()
 360                 /**
 361                 * This method extract the files and folders which are in the zip archive.
 362                 * It can extract all the archive or a part of the archive by using filter
 363                 * feature (extract by name, by index, by ereg, by preg). The extraction
 364                 * can occur in the current path or an other path.
 365                 * All the advanced features are activated by the use of variable
 366             	* parameters.
 367             	* The return value is an array of entry descriptions which gives
 368             	* information on extracted files (See listContent()).
 369             	* The method may return a success value (an array) even if some files
 370             	* are not correctly extracted (see the file status in listContent()).
 371                 * The supported variable parameters for this method are :
 372                 *   'add_path' : Path where the files and directories are to be extracted
 373                 *   'remove_path' : First part ('root' part) of the memorized path
 374                 *                   (if similar) to remove while extracting.
 375                 *   'remove_all_path' : Remove all the memorized path while extracting.
 376                 *   'extract_as_string' :
 377                 *   'set_chmod' : After the extraction of the file the indicated mode
 378                 *                 will be set.
 379 rizwank 1.1     *   'by_name' : It can be a string with file/dir names separated by ',',
 380                 *               or an array of file/dir names to extract from the archive.
 381                 *   'by_index' : A string with range of indexes separated by ',',
 382                 *                (sample "1,3-5,12").
 383                 *   'by_ereg' : A regular expression (ereg) that must match the extracted
 384                 *               filename.
 385                 *   'by_preg' : A regular expression (preg) that must match the extracted
 386                 *               filename.
 387                 *   'callback_pre_extract' : A callback function that will be called before
 388                 *                            each entry extraction.
 389                 *   'callback_post_extract' : A callback function that will be called after
 390                 *                            each entry extraction.
 391                 *
 392                 * @access public
 393                 * @param    mixed  $p_params  An array of variable parameters and values.
 394                 * @return mixed An array of file description on success,
 395             	*               0 on an unrecoverable failure, an error code is logged.
 396                 */
 397                 function extract($p_params=0)
 398                 {
 399             
 400 rizwank 1.1         $this->_errorReset();
 401             
 402                     // ----- Check archive
 403                     if (!$this->_checkFormat()) {
 404                         return(0);
 405                     }
 406             
 407                     // ----- Set default values
 408                     if ($p_params === 0) {
 409                     	$p_params = array();
 410                     }
 411                     if ($this->_check_parameters($p_params,
 412             	                                 array ('extract_as_string' => false,
 413             	                                        'add_path' => '',
 414             	                                        'remove_path' => '',
 415             	                                        'remove_all_path' => false,
 416             					    		     		'callback_pre_extract' => '',
 417             						    			    'callback_post_extract' => '',
 418             							    		    'set_chmod' => 0,
 419             								    	    'by_name' => '',
 420             									        'by_index' => '',
 421 rizwank 1.1 									        'by_ereg' => '',
 422             									        'by_preg' => '') ) != 1) {
 423             	    	return 0;
 424             	    }
 425             
 426                     // ----- Call the extracting fct
 427                     $v_list = array();
 428                     if ($this->_extractByRule($v_list, $p_params) != 1) {
 429                         unset($v_list);
 430                         return(0);
 431                     }
 432             
 433                     return $v_list;
 434                 }
 435                 // }}}
 436             
 437             
 438                 // {{{ delete()
 439                 /**
 440                 * This methods delete archive entries in the zip archive.
 441                 * Notice that at least one filtering rule (set by the variable parameter
 442 rizwank 1.1     * list) must be set.
 443                 * Also notice that if you delete a folder entry, only the folder entry
 444                 * is deleted, not all the files bellonging to this folder.
 445                 * The supported variable parameters for this method are :
 446                 *   'by_name' : It can be a string with file/dir names separated by ',',
 447                 *               or an array of file/dir names to delete from the archive.
 448                 *   'by_index' : A string with range of indexes separated by ',',
 449                 *                (sample "1,3-5,12").
 450                 *   'by_ereg' : A regular expression (ereg) that must match the extracted
 451                 *               filename.
 452                 *   'by_preg' : A regular expression (preg) that must match the extracted
 453                 *               filename.
 454                 *
 455                 * @access public
 456                 * @param    mixed  $p_params  An array of variable parameters and values.
 457                 * @return mixed An array of file description on success,
 458             	*               0 on an unrecoverable failure, an error code is logged.
 459                 */
 460                 function delete($p_params)
 461                 {
 462                     $this->_errorReset();
 463 rizwank 1.1 
 464                     // ----- Check archive
 465                     if (!$this->_checkFormat()) {
 466                         return(0);
 467                     }
 468             
 469                     // ----- Set default values
 470                     if ($this->_check_parameters($p_params,
 471             	                                 array ('by_name' => '',
 472             									        'by_index' => '',
 473             									        'by_ereg' => '',
 474             									        'by_preg' => '') ) != 1) {
 475             	    	return 0;
 476                 	}
 477             
 478                     // ----- Check that at least one rule is set
 479                     if (   ($p_params['by_name'] == '')
 480                         && ($p_params['by_index'] == '')
 481                         && ($p_params['by_ereg'] == '')
 482                         && ($p_params['by_preg'] == '')) {
 483                         $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
 484 rizwank 1.1 			                 'At least one filtering rule must'
 485             							 .' be set as parameter');
 486                         return 0;
 487                     }
 488             
 489                     // ----- Call the delete fct
 490                     $v_list = array();
 491                     if ($this->_deleteByRule($v_list, $p_params) != 1) {
 492                         unset($v_list);
 493                         return(0);
 494                     }
 495             
 496                     return $v_list;
 497                 }
 498                 // }}}
 499             
 500                 // {{{ properties()
 501                 /**
 502                 * This method gives the global properties of the archive.
 503                 *  The properties are :
 504                 *    nb : Number of files in the archive
 505 rizwank 1.1     *    comment : Comment associated with the archive file
 506                 *    status : not_exist, ok
 507                 *
 508                 * @access public
 509                 * @param    mixed  $p_params  {Description}
 510                 * @return mixed An array with the global properties or 0 on error.
 511                 */
 512                 function properties()
 513                 {
 514                     $this->_errorReset();
 515             
 516                     // ----- Check archive
 517                     if (!$this->_checkFormat()) {
 518                         return(0);
 519                     }
 520             
 521                     // ----- Default properties
 522                     $v_prop = array();
 523                     $v_prop['comment'] = '';
 524                     $v_prop['nb'] = 0;
 525                     $v_prop['status'] = 'not_exist';
 526 rizwank 1.1 
 527                     // ----- Look if file exists
 528                     if (@is_file($this->_zipname)) {
 529                         // ----- Open the zip file
 530                         if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0) {
 531                             $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
 532             				                 'Unable to open archive \''.$this->_zipname
 533             								 .'\' in binary read mode');
 534                             return 0;
 535                         }
 536             
 537                         // ----- Read the central directory informations
 538                         $v_central_dir = array();
 539                         if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) {
 540                             return 0;
 541                         }
 542             
 543                         $this->_closeFd();
 544             
 545                         // ----- Set the user attributes
 546                         $v_prop['comment'] = $v_central_dir['comment'];
 547 rizwank 1.1             $v_prop['nb'] = $v_central_dir['entries'];
 548                         $v_prop['status'] = 'ok';
 549                     }
 550             
 551                     return $v_prop;
 552                 }
 553                 // }}}
 554             
 555             
 556                 // {{{ duplicate()
 557                 /**
 558                 * This method creates an archive by copying the content of an other one.
 559             	* If the archive already exist, it is replaced by the new one without
 560             	* any warning.
 561                 *
 562                 * @access public
 563                 * @param  mixed  $p_archive  It can be a valid Archive_Zip object or
 564             	*                            the filename of a valid zip archive.
 565                 * @return integer 1 on success, 0 on failure.
 566                 */
 567                 function duplicate($p_archive)
 568 rizwank 1.1     {
 569                     $this->_errorReset();
 570             
 571                     // ----- Look if the $p_archive is a Archive_Zip object
 572                     if (   (is_object($p_archive))
 573             		    && (strtolower(get_class($p_archive)) == 'archive_zip')) {
 574                         $v_result = $this->_duplicate($p_archive->_zipname);
 575                     }
 576             
 577                     // ----- Look if the $p_archive is a string (so a filename)
 578                     else if (is_string($p_archive)) {
 579                         // ----- Check that $p_archive is a valid zip file
 580                         // TBC : Should also check the archive format
 581                         if (!is_file($p_archive)) {
 582                             $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE,
 583             				                 "No file with filename '".$p_archive."'");
 584                             $v_result = ARCHIVE_ZIP_ERR_MISSING_FILE;
 585                         }
 586                         else {
 587                             $v_result = $this->_duplicate($p_archive);
 588                         }
 589 rizwank 1.1         }
 590             
 591                     // ----- Invalid variable
 592                     else {
 593                         $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
 594             			                 "Invalid variable type p_archive_to_add");
 595                         $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER;
 596                     }
 597             
 598                     return $v_result;
 599                 }
 600                 // }}}
 601             
 602                 // {{{ merge()
 603                 /**
 604                 *  This method merge a valid zip archive at the end of the
 605             	*  archive identified by the Archive_Zip object.
 606                 *  If the archive ($this) does not exist, the merge becomes a duplicate.
 607                 *  If the archive to add does not exist, the merge is a success.
 608                 *
 609                 * @access public
 610 rizwank 1.1     * @param mixed $p_archive_to_add  It can be a valid Archive_Zip object or
 611             	*                                 the filename of a valid zip archive.
 612                 * @return integer 1 on success, 0 on failure.
 613                 */
 614                 function merge($p_archive_to_add)
 615                 {
 616                     $v_result = 1;
 617                     $this->_errorReset();
 618             
 619                     // ----- Check archive
 620                     if (!$this->_checkFormat()) {
 621                         return(0);
 622                     }
 623             
 624                     // ----- Look if the $p_archive_to_add is a Archive_Zip object
 625                     if (   (is_object($p_archive_to_add))
 626             		    && (strtolower(get_class($p_archive_to_add)) == 'archive_zip')) {
 627                         $v_result = $this->_merge($p_archive_to_add);
 628                     }
 629             
 630                     // ----- Look if the $p_archive_to_add is a string (so a filename)
 631 rizwank 1.1         else if (is_string($p_archive_to_add)) {
 632                         // ----- Create a temporary archive
 633                         $v_object_archive = new Archive_Zip($p_archive_to_add);
 634             
 635                         // ----- Merge the archive
 636                         $v_result = $this->_merge($v_object_archive);
 637                     }
 638             
 639                     // ----- Invalid variable
 640                     else {
 641                         $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
 642             			                 "Invalid variable type p_archive_to_add");
 643                         $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER;
 644                     }
 645             
 646                     return $v_result;
 647                 }
 648                 // }}}
 649             
 650                 // {{{ errorCode()
 651                 /**
 652 rizwank 1.1     * Method that gives the lastest error code.
 653                 *
 654                 * @access public
 655                 * @return integer The error code value.
 656                 */
 657                 function errorCode()
 658                 {
 659                     return($this->_error_code);
 660                 }
 661                 // }}}
 662             
 663                 // {{{ errorName()
 664                 /**
 665                 * This method gives the latest error code name.
 666                 *
 667                 * @access public
 668                 * @param  boolean $p_with_code  If true, gives the name and the int value.
 669                 * @return string The error name.
 670                 */
 671                 function errorName($p_with_code=false)
 672                 {
 673 rizwank 1.1         $v_const_list = get_defined_constants();
 674               	
 675                   	// ----- Extract error constants from all const.
 676                     for (reset($v_const_list);
 677             		     list($v_key, $v_value) = each($v_const_list);) {
 678                  	    if (substr($v_key, 0, strlen('ARCHIVE_ZIP_ERR_'))
 679             			    =='ARCHIVE_ZIP_ERR_') {
 680                 		    $v_error_list[$v_key] = $v_value;
 681                 	    }
 682                     }
 683                 
 684                     // ----- Search the name form the code value
 685                     $v_key=array_search($this->_error_code, $v_error_list, true);
 686               	    if ($v_key!=false) {
 687                         $v_value = $v_key;
 688               	    }
 689               	    else {
 690                         $v_value = 'NoName';
 691               	    }
 692               	
 693                     if ($p_with_code) {
 694 rizwank 1.1             return($v_value.' ('.$this->_error_code.')');
 695                     }
 696                     else {
 697                       return($v_value);
 698                     }
 699                 }
 700                 // }}}
 701             
 702                 // {{{ errorInfo()
 703                 /**
 704                 * This method returns the description associated with the latest error.
 705                 *
 706                 * @access public
 707                 * @param  boolean $p_full If set to true gives the description with the
 708                 *                         error code, the name and the description.
 709                 *                         If set to false gives only the description
 710                 *                         and the error code.
 711                 * @return string The error description.
 712                 */
 713                 function errorInfo($p_full=false)
 714                 {
 715 rizwank 1.1         if ($p_full) {
 716                         return($this->errorName(true)." : ".$this->_error_string);
 717                     }
 718                     else {
 719                         return($this->_error_string." [code ".$this->_error_code."]");
 720                     }
 721                 }
 722                 // }}}
 723             
 724             
 725             // -----------------------------------------------------------------------------
 726             // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
 727             // *****                                                        *****
 728             // *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       *****
 729             // -----------------------------------------------------------------------------
 730             
 731               // ---------------------------------------------------------------------------
 732               // Function : _checkFormat()
 733               // Description :
 734               //   This method check that the archive exists and is a valid zip archive.
 735               //   Several level of check exists. (futur)
 736 rizwank 1.1   // Parameters :
 737               //   $p_level : Level of check. Default 0.
 738               //              0 : Check the first bytes (magic codes) (default value))
 739               //              1 : 0 + Check the central directory (futur)
 740               //              2 : 1 + Check each file header (futur)
 741               // Return Values :
 742               //   true on success,
 743               //   false on error, the error code is set.
 744               // ---------------------------------------------------------------------------
 745               /**
 746               * Archive_Zip::_checkFormat()
 747               *
 748               * { Description }
 749               *
 750               * @param integer $p_level
 751               */
 752               function _checkFormat($p_level=0)
 753               {
 754                 $v_result = true;
 755             
 756                 // ----- Reset the error handler
 757 rizwank 1.1     $this->_errorReset();
 758             
 759                 // ----- Look if the file exits
 760                 if (!is_file($this->_zipname)) {
 761                   // ----- Error log
 762                   $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE,
 763             	                   "Missing archive file '".$this->_zipname."'");
 764                   return(false);
 765                 }
 766             
 767                 // ----- Check that the file is readeable
 768                 if (!is_readable($this->_zipname)) {
 769                   // ----- Error log
 770                   $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
 771             	                   "Unable to read archive '".$this->_zipname."'");
 772                   return(false);
 773                 }
 774             
 775                 // ----- Check the magic code
 776                 // TBC
 777             
 778 rizwank 1.1     // ----- Check the central header
 779                 // TBC
 780             
 781                 // ----- Check each file header
 782                 // TBC
 783             
 784                 // ----- Return
 785                 return $v_result;
 786               }
 787               // ---------------------------------------------------------------------------
 788             
 789               // ---------------------------------------------------------------------------
 790               // Function : _create()
 791               // Description :
 792               // Parameters :
 793               // Return Values :
 794               // ---------------------------------------------------------------------------
 795               /**
 796               * Archive_Zip::_create()
 797               *
 798               * { Description }
 799 rizwank 1.1   *
 800               */
 801               function _create($p_list, &$p_result_list, &$p_params)
 802               {
 803                 $v_result=1;
 804                 $v_list_detail = array();
 805             
 806             	$p_add_dir = $p_params['add_path'];
 807             	$p_remove_dir = $p_params['remove_path'];
 808             	$p_remove_all_dir = $p_params['remove_all_path'];
 809             
 810                 // ----- Open the file in write mode
 811                 if (($v_result = $this->_openFd('wb')) != 1)
 812                 {
 813                   // ----- Return
 814                   return $v_result;
 815                 }
 816             
 817                 // ----- Add the list of files
 818                 $v_result = $this->_addList($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params);
 819             
 820 rizwank 1.1     // ----- Close
 821                 $this->_closeFd();
 822             
 823                 // ----- Return
 824                 return $v_result;
 825               }
 826               // ---------------------------------------------------------------------------
 827             
 828               // ---------------------------------------------------------------------------
 829               // Function : _add()
 830               // Description :
 831               // Parameters :
 832               // Return Values :
 833               // ---------------------------------------------------------------------------
 834               /**
 835               * Archive_Zip::_add()
 836               *
 837               * { Description }
 838               *
 839               */
 840               function _add($p_list, &$p_result_list, &$p_params)
 841 rizwank 1.1   {
 842                 $v_result=1;
 843                 $v_list_detail = array();
 844             
 845             	$p_add_dir = $p_params['add_path'];
 846             	$p_remove_dir = $p_params['remove_path'];
 847             	$p_remove_all_dir = $p_params['remove_all_path'];
 848             
 849                 // ----- Look if the archive exists or is empty and need to be created
 850                 if ((!is_file($this->_zipname)) || (filesize($this->_zipname) == 0)) {
 851                   $v_result = $this->_create($p_list, $p_result_list, $p_params);
 852                   return $v_result;
 853                 }
 854             
 855                 // ----- Open the zip file
 856                 if (($v_result=$this->_openFd('rb')) != 1) {
 857                   return $v_result;
 858                 }
 859             
 860                 // ----- Read the central directory informations
 861                 $v_central_dir = array();
 862 rizwank 1.1     if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
 863                 {
 864                   $this->_closeFd();
 865                   return $v_result;
 866                 }
 867             
 868                 // ----- Go to beginning of File
 869                 @rewind($this->_zip_fd);
 870             
 871                 // ----- Creates a temporay file
 872                 $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-').'.tmp';
 873             
 874                 // ----- Open the temporary file in write mode
 875                 if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
 876                 {
 877                   $this->_closeFd();
 878             
 879                   $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
 880             	                   'Unable to open temporary file \''
 881             					   .$v_zip_temp_name.'\' in binary write mode');
 882                   return Archive_Zip::errorCode();
 883 rizwank 1.1     }
 884             
 885                 // ----- Copy the files from the archive to the temporary file
 886                 // TBC : Here I should better append the file and go back to erase the
 887             	// central dir
 888                 $v_size = $v_central_dir['offset'];
 889                 while ($v_size != 0)
 890                 {
 891                   $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
 892             	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
 893                   $v_buffer = fread($this->_zip_fd, $v_read_size);
 894                   @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
 895                   $v_size -= $v_read_size;
 896                 }
 897             
 898                 // ----- Swap the file descriptor
 899                 // Here is a trick : I swap the temporary fd with the zip fd, in order to 
 900                 // use the following methods on the temporary fil and not the real archive
 901                 $v_swap = $this->_zip_fd;
 902                 $this->_zip_fd = $v_zip_temp_fd;
 903                 $v_zip_temp_fd = $v_swap;
 904 rizwank 1.1 
 905                 // ----- Add the files
 906                 $v_header_list = array();
 907                 if (($v_result = $this->_addFileList($p_list, $v_header_list,
 908             	                                     $p_add_dir, $p_remove_dir,
 909             										 $p_remove_all_dir, $p_params)) != 1)
 910                 {
 911                   fclose($v_zip_temp_fd);
 912                   $this->_closeFd();
 913                   @unlink($v_zip_temp_name);
 914             
 915                   // ----- Return
 916                   return $v_result;
 917                 }
 918             
 919                 // ----- Store the offset of the central dir
 920                 $v_offset = @ftell($this->_zip_fd);
 921             
 922                 // ----- Copy the block of file headers from the old archive
 923                 $v_size = $v_central_dir['size'];
 924                 while ($v_size != 0)
 925 rizwank 1.1     {
 926                   $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
 927             	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
 928                   $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
 929                   @fwrite($this->_zip_fd, $v_buffer, $v_read_size);
 930                   $v_size -= $v_read_size;
 931                 }
 932             
 933                 // ----- Create the Central Dir files header
 934                 for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
 935                 {
 936                   // ----- Create the file header
 937                   if ($v_header_list[$i]['status'] == 'ok') {
 938                     if (($v_result=$this->_writeCentralFileHeader($v_header_list[$i]))!=1) {
 939                       fclose($v_zip_temp_fd);
 940                       $this->_closeFd();
 941                       @unlink($v_zip_temp_name);
 942             
 943                       // ----- Return
 944                       return $v_result;
 945                     }
 946 rizwank 1.1         $v_count++;
 947                   }
 948             
 949                   // ----- Transform the header to a 'usable' info
 950                   $this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
 951                 }
 952             
 953                 // ----- Zip file comment
 954                 $v_comment = '';
 955             
 956                 // ----- Calculate the size of the central header
 957                 $v_size = @ftell($this->_zip_fd)-$v_offset;
 958             
 959                 // ----- Create the central dir footer
 960                 if (($v_result = $this->_writeCentralHeader($v_count
 961             	                                              +$v_central_dir['entries'],
 962             	                                            $v_size, $v_offset,
 963             												$v_comment)) != 1) {
 964                   // ----- Reset the file list
 965                   unset($v_header_list);
 966             
 967 rizwank 1.1       // ----- Return
 968                   return $v_result;
 969                 }
 970             
 971                 // ----- Swap back the file descriptor
 972                 $v_swap = $this->_zip_fd;
 973                 $this->_zip_fd = $v_zip_temp_fd;
 974                 $v_zip_temp_fd = $v_swap;
 975             
 976                 // ----- Close
 977                 $this->_closeFd();
 978             
 979                 // ----- Close the temporary file
 980                 @fclose($v_zip_temp_fd);
 981             
 982                 // ----- Delete the zip file
 983                 // TBC : I should test the result ...
 984                 @unlink($this->_zipname);
 985             
 986                 // ----- Rename the temporary file
 987                 // TBC : I should test the result ...
 988 rizwank 1.1     //@rename($v_zip_temp_name, $this->_zipname);
 989                 $this->_tool_Rename($v_zip_temp_name, $this->_zipname);
 990             
 991                 // ----- Return
 992                 return $v_result;
 993               }
 994               // ---------------------------------------------------------------------------
 995             
 996               // ---------------------------------------------------------------------------
 997               // Function : _openFd()
 998               // Description :
 999               // Parameters :
1000               // ---------------------------------------------------------------------------
1001               /**
1002               * Archive_Zip::_openFd()
1003               *
1004               * { Description }
1005               *
1006               */
1007               function _openFd($p_mode)
1008               {
1009 rizwank 1.1     $v_result=1;
1010             
1011                 // ----- Look if already open
1012                 if ($this->_zip_fd != 0)
1013                 {
1014                   $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
1015             	                   'Zip file \''.$this->_zipname.'\' already open');
1016                   return Archive_Zip::errorCode();
1017                 }
1018             
1019                 // ----- Open the zip file
1020                 if (($this->_zip_fd = @fopen($this->_zipname, $p_mode)) == 0)
1021                 {
1022                   $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
1023             	                   'Unable to open archive \''.$this->_zipname
1024             					   .'\' in '.$p_mode.' mode');
1025                   return Archive_Zip::errorCode();
1026                 }
1027             
1028                 // ----- Return
1029                 return $v_result;
1030 rizwank 1.1   }
1031               // ---------------------------------------------------------------------------
1032             
1033               // ---------------------------------------------------------------------------
1034               // Function : _closeFd()
1035               // Description :
1036               // Parameters :
1037               // ---------------------------------------------------------------------------
1038               /**
1039               * Archive_Zip::_closeFd()
1040               *
1041               * { Description }
1042               *
1043               */
1044               function _closeFd()
1045               {
1046                 $v_result=1;
1047             
1048                 if ($this->_zip_fd != 0)
1049                   @fclose($this->_zip_fd);
1050                 $this->_zip_fd = 0;
1051 rizwank 1.1 
1052                 // ----- Return
1053                 return $v_result;
1054               }
1055               // ---------------------------------------------------------------------------
1056             
1057               // ---------------------------------------------------------------------------
1058               // Function : _addList()
1059               // Description :
1060               //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
1061               //   different from the real path of the file. This is usefull if you want to have PclTar
1062               //   running in any directory, and memorize relative path from an other directory.
1063               // Parameters :
1064               //   $p_list : An array containing the file or directory names to add in the tar
1065               //   $p_result_list : list of added files with their properties (specially the status field)
1066               //   $p_add_dir : Path to add in the filename path archived
1067               //   $p_remove_dir : Path to remove in the filename path archived
1068               // Return Values :
1069               // ---------------------------------------------------------------------------
1070               /**
1071               * Archive_Zip::_addList()
1072 rizwank 1.1   *
1073               * { Description }
1074               *
1075               */
1076               function _addList($p_list, &$p_result_list,
1077                                 $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params)
1078               {
1079                 $v_result=1;
1080             
1081                 // ----- Add the files
1082                 $v_header_list = array();
1083                 if (($v_result = $this->_addFileList($p_list, $v_header_list,
1084             	                                     $p_add_dir, $p_remove_dir,
1085             										 $p_remove_all_dir, $p_params)) != 1) {
1086                   return $v_result;
1087                 }
1088             
1089                 // ----- Store the offset of the central dir
1090                 $v_offset = @ftell($this->_zip_fd);
1091             
1092                 // ----- Create the Central Dir files header
1093 rizwank 1.1     for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
1094                 {
1095                   // ----- Create the file header
1096                   if ($v_header_list[$i]['status'] == 'ok') {
1097                     if (($v_result = $this->_writeCentralFileHeader($v_header_list[$i])) != 1) {
1098                       return $v_result;
1099                     }
1100                     $v_count++;
1101                   }
1102             
1103                   // ----- Transform the header to a 'usable' info
1104                   $this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
1105                 }
1106             
1107                 // ----- Zip file comment
1108                 $v_comment = '';
1109             
1110                 // ----- Calculate the size of the central header
1111                 $v_size = @ftell($this->_zip_fd)-$v_offset;
1112             
1113                 // ----- Create the central dir footer
1114 rizwank 1.1     if (($v_result = $this->_writeCentralHeader($v_count, $v_size, $v_offset,
1115             	                                            $v_comment)) != 1)
1116                 {
1117                   // ----- Reset the file list
1118                   unset($v_header_list);
1119             
1120                   // ----- Return
1121                   return $v_result;
1122                 }
1123             
1124                 // ----- Return
1125                 return $v_result;
1126               }
1127               // ---------------------------------------------------------------------------
1128             
1129               // ---------------------------------------------------------------------------
1130               // Function : _addFileList()
1131               // Description :
1132               //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
1133               //   different from the real path of the file. This is usefull if you want to
1134               //   run the lib in any directory, and memorize relative path from an other directory.
1135 rizwank 1.1   // Parameters :
1136               //   $p_list : An array containing the file or directory names to add in the tar
1137               //   $p_result_list : list of added files with their properties (specially the status field)
1138               //   $p_add_dir : Path to add in the filename path archived
1139               //   $p_remove_dir : Path to remove in the filename path archived
1140               // Return Values :
1141               // ---------------------------------------------------------------------------
1142               /**
1143               * Archive_Zip::_addFileList()
1144               *
1145               * { Description }
1146               *
1147               */
1148               function _addFileList($p_list, &$p_result_list,
1149                                     $p_add_dir, $p_remove_dir, $p_remove_all_dir,
1150             						&$p_params)
1151               {
1152                 $v_result=1;
1153                 $v_header = array();
1154             
1155                 // ----- Recuperate the current number of elt in list
1156 rizwank 1.1     $v_nb = sizeof($p_result_list);
1157             
1158                 // ----- Loop on the files
1159                 for ($j=0; ($j<count($p_list)) && ($v_result==1); $j++)
1160                 {
1161                   // ----- Recuperate the filename
1162                   $p_filename = $this->_tool_TranslateWinPath($p_list[$j], false);
1163             
1164                   // ----- Skip empty file names
1165                   if ($p_filename == "")
1166                   {
1167                     continue;
1168                   }
1169             
1170                   // ----- Check the filename
1171                   if (!file_exists($p_filename))
1172                   {
1173                     $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE,
1174             		                 "File '$p_filename' does not exists");
1175                     return Archive_Zip::errorCode();
1176                   }
1177 rizwank 1.1 
1178                   // ----- Look if it is a file or a dir with no all pathnre move
1179                   if ((is_file($p_filename)) || ((is_dir($p_filename)) && !$p_remove_all_dir)) {
1180                     // ----- Add the file
1181                     if (($v_result = $this->_addFile($p_filename, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1)
1182                     {
1183                       // ----- Return status
1184                       return $v_result;
1185                     }
1186             
1187                     // ----- Store the file infos
1188                     $p_result_list[$v_nb++] = $v_header;
1189                   }
1190             
1191                   // ----- Look for directory
1192                   if (is_dir($p_filename))
1193                   {
1194             
1195                     // ----- Look for path
1196                     if ($p_filename != ".")
1197                       $v_path = $p_filename."/";
1198 rizwank 1.1         else
1199                       $v_path = "";
1200             
1201                     // ----- Read the directory for files and sub-directories
1202                     $p_hdir = opendir($p_filename);
1203                     $p_hitem = readdir($p_hdir); // '.' directory
1204                     $p_hitem = readdir($p_hdir); // '..' directory
1205                     while ($p_hitem = readdir($p_hdir))
1206                     {
1207             
1208                       // ----- Look for a file
1209                       if (is_file($v_path.$p_hitem))
1210                       {
1211             
1212                         // ----- Add the file
1213                         if (($v_result = $this->_addFile($v_path.$p_hitem, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1)
1214                         {
1215                           // ----- Return status
1216                           return $v_result;
1217                         }
1218             
1219 rizwank 1.1             // ----- Store the file infos
1220                         $p_result_list[$v_nb++] = $v_header;
1221                       }
1222             
1223                       // ----- Recursive call to _addFileList()
1224                       else
1225                       {
1226             
1227                         // ----- Need an array as parameter
1228                         $p_temp_list[0] = $v_path.$p_hitem;
1229                         $v_result = $this->_addFileList($p_temp_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params);
1230             
1231                         // ----- Update the number of elements of the list
1232                         $v_nb = sizeof($p_result_list);
1233                       }
1234                     }
1235             
1236                     // ----- Free memory for the recursive loop
1237                     unset($p_temp_list);
1238                     unset($p_hdir);
1239                     unset($p_hitem);
1240 rizwank 1.1       }
1241                 }
1242             
1243                 return $v_result;
1244               }
1245               // ---------------------------------------------------------------------------
1246             
1247               // ---------------------------------------------------------------------------
1248               // Function : _addFile()
1249               // Description :
1250               // Parameters :
1251               // Return Values :
1252               // ---------------------------------------------------------------------------
1253               /**
1254               * Archive_Zip::_addFile()
1255               *
1256               * { Description }
1257               *
1258               */
1259               function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params)
1260               {
1261 rizwank 1.1     $v_result=1;
1262             
1263                 if ($p_filename == "")
1264                 {
1265                   // ----- Error log
1266                   $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
1267             
1268                   // ----- Return
1269                   return Archive_Zip::errorCode();
1270                 }
1271             
1272                 // ----- Calculate the stored filename
1273                 $v_stored_filename = $p_filename;
1274             
1275                 // ----- Look for all path to remove
1276                 if ($p_remove_all_dir) {
1277                   $v_stored_filename = basename($p_filename);
1278                 }
1279                 // ----- Look for partial path remove
1280                 else if ($p_remove_dir != "")
1281                 {
1282 rizwank 1.1       if (substr($p_remove_dir, -1) != '/')
1283                     $p_remove_dir .= "/";
1284             
1285                   if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./"))
1286                   {
1287                     if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./"))
1288                       $p_remove_dir = "./".$p_remove_dir;
1289                     if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./"))
1290                       $p_remove_dir = substr($p_remove_dir, 2);
1291                   }
1292             
1293                   $v_compare = $this->_tool_PathInclusion($p_remove_dir, $p_filename);
1294                   if ($v_compare > 0)
1295             //      if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
1296                   {
1297             
1298                     if ($v_compare == 2) {
1299                       $v_stored_filename = "";
1300                     }
1301                     else {
1302                       $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
1303 rizwank 1.1         }
1304                   }
1305                 }
1306                 // ----- Look for path to add
1307                 if ($p_add_dir != "")
1308                 {
1309                   if (substr($p_add_dir, -1) == "/")
1310                     $v_stored_filename = $p_add_dir.$v_stored_filename;
1311                   else
1312                     $v_stored_filename = $p_add_dir."/".$v_stored_filename;
1313                 }
1314             
1315                 // ----- Filename (reduce the path of stored name)
1316                 $v_stored_filename = $this->_tool_PathReduction($v_stored_filename);
1317             
1318             
1319                 /* filename length moved after call-back in release 1.3
1320                 // ----- Check the path length
1321                 if (strlen($v_stored_filename) > 0xFF)
1322                 {
1323                   // ----- Error log
1324 rizwank 1.1       $this->_errorLog(-5, "Stored file name is too long (max. 255) : '$v_stored_filename'");
1325             
1326                   // ----- Return
1327                   return Archive_Zip::errorCode();
1328                 }
1329                 */
1330             
1331                 // ----- Set the file properties
1332                 clearstatcache();
1333                 $p_header['version'] = 20;
1334                 $p_header['version_extracted'] = 10;
1335                 $p_header['flag'] = 0;
1336                 $p_header['compression'] = 0;
1337                 $p_header['mtime'] = filemtime($p_filename);
1338                 $p_header['crc'] = 0;
1339                 $p_header['compressed_size'] = 0;
1340                 $p_header['size'] = filesize($p_filename);
1341                 $p_header['filename_len'] = strlen($p_filename);
1342                 $p_header['extra_len'] = 0;
1343                 $p_header['comment_len'] = 0;
1344                 $p_header['disk'] = 0;
1345 rizwank 1.1     $p_header['internal'] = 0;
1346                 $p_header['external'] = (is_file($p_filename)?0xFE49FFE0:0x41FF0010);
1347                 $p_header['offset'] = 0;
1348                 $p_header['filename'] = $p_filename;
1349                 $p_header['stored_filename'] = $v_stored_filename;
1350                 $p_header['extra'] = '';
1351                 $p_header['comment'] = '';
1352                 $p_header['status'] = 'ok';
1353                 $p_header['index'] = -1;
1354             
1355                 // ----- Look for pre-add callback
1356                 if (   (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD]))
1357             	    && ($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD] != '')) {
1358             
1359                   // ----- Generate a local information
1360                   $v_local_header = array();
1361                   $this->_convertHeader2FileInfo($p_header, $v_local_header);
1362             
1363                   // ----- Call the callback
1364                   // Here I do not use call_user_func() because I need to send a reference to the
1365                   // header.
1366 rizwank 1.1       eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_ADD].'(ARCHIVE_ZIP_PARAM_PRE_ADD, $v_local_header);');
1367                   if ($v_result == 0) {
1368                     // ----- Change the file status
1369                     $p_header['status'] = "skipped";
1370                     $v_result = 1;
1371                   }
1372             
1373                   // ----- Update the informations
1374                   // Only some fields can be modified
1375                   if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
1376                     $p_header['stored_filename'] = $this->_tool_PathReduction($v_local_header['stored_filename']);
1377                   }
1378                 }
1379             
1380                 // ----- Look for empty stored filename
1381                 if ($p_header['stored_filename'] == "") {
1382                   $p_header['status'] = "filtered";
1383                 }
1384             
1385                 // ----- Check the path length
1386                 if (strlen($p_header['stored_filename']) > 0xFF) {
1387 rizwank 1.1       $p_header['status'] = 'filename_too_long';
1388                 }
1389             
1390                 // ----- Look if no error, or file not skipped
1391                 if ($p_header['status'] == 'ok') {
1392             
1393                   // ----- Look for a file
1394                   if (is_file($p_filename))
1395                   {
1396                     // ----- Open the source file
1397                     if (($v_file = @fopen($p_filename, "rb")) == 0) {
1398                       $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
1399                       return Archive_Zip::errorCode();
1400                     }
1401                     
1402                     if ($p_params['no_compression']) {
1403                       // ----- Read the file content
1404                       $v_content_compressed = @fread($v_file, $p_header['size']);
1405             
1406                       // ----- Calculate the CRC
1407                       $p_header['crc'] = crc32($v_content_compressed);
1408 rizwank 1.1         }
1409                     else {
1410                       // ----- Read the file content
1411                       $v_content = @fread($v_file, $p_header['size']);
1412             
1413                       // ----- Calculate the CRC
1414                       $p_header['crc'] = crc32($v_content);
1415             
1416                       // ----- Compress the file
1417                       $v_content_compressed = gzdeflate($v_content);
1418                     }
1419             
1420                     // ----- Set header parameters
1421                     $p_header['compressed_size'] = strlen($v_content_compressed);
1422                     $p_header['compression'] = 8;
1423             
1424                     // ----- Call the header generation
1425                     if (($v_result = $this->_writeFileHeader($p_header)) != 1) {
1426                       @fclose($v_file);
1427                       return $v_result;
1428                     }
1429 rizwank 1.1 
1430                     // ----- Write the compressed content
1431                     $v_binary_data = pack('a'.$p_header['compressed_size'], $v_content_compressed);
1432                     @fwrite($this->_zip_fd, $v_binary_data, $p_header['compressed_size']);
1433             
1434                     // ----- Close the file
1435                     @fclose($v_file);
1436                   }
1437             
1438                   // ----- Look for a directory
1439                   else
1440                   {
1441                     // ----- Set the file properties
1442                     $p_header['filename'] .= '/';
1443                     $p_header['filename_len']++;
1444                     $p_header['size'] = 0;
1445                     $p_header['external'] = 0x41FF0010;   // Value for a folder : to be checked
1446             
1447                     // ----- Call the header generation
1448                     if (($v_result = $this->_writeFileHeader($p_header)) != 1)
1449                     {
1450 rizwank 1.1           return $v_result;
1451                     }
1452                   }
1453                 }
1454             
1455                 // ----- Look for pre-add callback
1456                 if (   (isset($p_params[ARCHIVE_ZIP_PARAM_POST_ADD]))
1457             	    && ($p_params[ARCHIVE_ZIP_PARAM_POST_ADD] != '')) {
1458             
1459                   // ----- Generate a local information
1460                   $v_local_header = array();
1461                   $this->_convertHeader2FileInfo($p_header, $v_local_header);
1462             
1463                   // ----- Call the callback
1464                   // Here I do not use call_user_func() because I need to send a reference to the
1465                   // header.
1466                   eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_ADD].'(ARCHIVE_ZIP_PARAM_POST_ADD, $v_local_header);');
1467                   if ($v_result == 0) {
1468                     // ----- Ignored
1469                     $v_result = 1;
1470                   }
1471 rizwank 1.1 
1472                   // ----- Update the informations
1473                   // Nothing can be modified
1474                 }
1475             
1476                 // ----- Return
1477                 return $v_result;
1478               }
1479               // ---------------------------------------------------------------------------
1480             
1481               // ---------------------------------------------------------------------------
1482               // Function : _writeFileHeader()
1483               // Description :
1484               // Parameters :
1485               // Return Values :
1486               // ---------------------------------------------------------------------------
1487               /**
1488               * Archive_Zip::_writeFileHeader()
1489               *
1490               * { Description }
1491               *
1492 rizwank 1.1   */
1493               function _writeFileHeader(&$p_header)
1494               {
1495                 $v_result=1;
1496             
1497                 // TBC
1498                 //for(reset($p_header); $key = key($p_header); next($p_header)) {
1499                 //}
1500             
1501                 // ----- Store the offset position of the file
1502                 $p_header['offset'] = ftell($this->_zip_fd);
1503             
1504                 // ----- Transform UNIX mtime to DOS format mdate/mtime
1505                 $v_date = getdate($p_header['mtime']);
1506                 $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
1507                 $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
1508             
1509                 // ----- Packed data
1510                 $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, $p_header['version'], $p_header['flag'],
1511                                       $p_header['compression'], $v_mtime, $v_mdate,
1512                                       $p_header['crc'], $p_header['compressed_size'], $p_header['size'],
1513 rizwank 1.1                           strlen($p_header['stored_filename']), $p_header['extra_len']);
1514             
1515                 // ----- Write the first 148 bytes of the header in the archive
1516                 fputs($this->_zip_fd, $v_binary_data, 30);
1517             
1518                 // ----- Write the variable fields
1519                 if (strlen($p_header['stored_filename']) != 0)
1520                 {
1521                   fputs($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
1522                 }
1523                 if ($p_header['extra_len'] != 0)
1524                 {
1525                   fputs($this->_zip_fd, $p_header['extra'], $p_header['extra_len']);
1526                 }
1527             
1528                 // ----- Return
1529                 return $v_result;
1530               }
1531               // ---------------------------------------------------------------------------
1532             
1533               // ---------------------------------------------------------------------------
1534 rizwank 1.1   // Function : _writeCentralFileHeader()
1535               // Description :
1536               // Parameters :
1537               // Return Values :
1538               // ---------------------------------------------------------------------------
1539               /**
1540               * Archive_Zip::_writeCentralFileHeader()
1541               *
1542               * { Description }
1543               *
1544               */
1545               function _writeCentralFileHeader(&$p_header)
1546               {
1547                 $v_result=1;
1548             
1549                 // TBC
1550                 //for(reset($p_header); $key = key($p_header); next($p_header)) {
1551                 //}
1552             
1553                 // ----- Transform UNIX mtime to DOS format mdate/mtime
1554                 $v_date = getdate($p_header['mtime']);
1555 rizwank 1.1     $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
1556                 $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
1557             
1558                 // ----- Packed data
1559                 $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, $p_header['version'], $p_header['version_extracted'],
1560                                       $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'],
1561                                       $p_header['compressed_size'], $p_header['size'],
1562                                       strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'],
1563                                       $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']);
1564             
1565                 // ----- Write the 42 bytes of the header in the zip file
1566                 fputs($this->_zip_fd, $v_binary_data, 46);
1567             
1568                 // ----- Write the variable fields
1569                 if (strlen($p_header['stored_filename']) != 0)
1570                 {
1571                   fputs($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
1572                 }
1573                 if ($p_header['extra_len'] != 0)
1574                 {
1575                   fputs($this->_zip_fd, $p_header['extra'], $p_header['extra_len']);
1576 rizwank 1.1     }
1577                 if ($p_header['comment_len'] != 0)
1578                 {
1579                   fputs($this->_zip_fd, $p_header['comment'], $p_header['comment_len']);
1580                 }
1581             
1582                 // ----- Return
1583                 return $v_result;
1584               }
1585               // ---------------------------------------------------------------------------
1586             
1587               // ---------------------------------------------------------------------------
1588               // Function : _writeCentralHeader()
1589               // Description :
1590               // Parameters :
1591               // Return Values :
1592               // ---------------------------------------------------------------------------
1593               /**
1594               * Archive_Zip::_writeCentralHeader()
1595               *
1596               * { Description }
1597 rizwank 1.1   *
1598               */
1599               function _writeCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
1600               {
1601                 $v_result=1;
1602             
1603                 // ----- Packed data
1604                 $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment));
1605             
1606                 // ----- Write the 22 bytes of the header in the zip file
1607                 fputs($this->_zip_fd, $v_binary_data, 22);
1608             
1609                 // ----- Write the variable fields
1610                 if (strlen($p_comment) != 0)
1611                 {
1612                   fputs($this->_zip_fd, $p_comment, strlen($p_comment));
1613                 }
1614             
1615                 // ----- Return
1616                 return $v_result;
1617               }
1618 rizwank 1.1   // ---------------------------------------------------------------------------
1619             
1620               // ---------------------------------------------------------------------------
1621               // Function : _list()
1622               // Description :
1623               // Parameters :
1624               // Return Values :
1625               // ---------------------------------------------------------------------------
1626               /**
1627               * Archive_Zip::_list()
1628               *
1629               * { Description }
1630               *
1631               */
1632               function _list(&$p_list)
1633               {
1634                 $v_result=1;
1635             
1636                 // ----- Open the zip file
1637                 if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0)
1638                 {
1639 rizwank 1.1       // ----- Error log
1640                   $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->_zipname.'\' in binary read mode');
1641             
1642                   // ----- Return
1643                   return Archive_Zip::errorCode();
1644                 }
1645             
1646                 // ----- Read the central directory informations
1647                 $v_central_dir = array();
1648                 if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
1649                 {
1650                   return $v_result;
1651                 }
1652             
1653                 // ----- Go to beginning of Central Dir
1654                 @rewind($this->_zip_fd);
1655                 if (@fseek($this->_zip_fd, $v_central_dir['offset']))
1656                 {
1657                   // ----- Error log
1658                   $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
1659             
1660 rizwank 1.1       // ----- Return
1661                   return Archive_Zip::errorCode();
1662                 }
1663             
1664                 // ----- Read each entry
1665                 for ($i=0; $i<$v_central_dir['entries']; $i++)
1666                 {
1667                   // ----- Read the file header
1668                   if (($v_result = $this->_readCentralFileHeader($v_header)) != 1)
1669                   {
1670                     return $v_result;
1671                   }
1672                   $v_header['index'] = $i;
1673             
1674                   // ----- Get the only interesting attributes
1675                   $this->_convertHeader2FileInfo($v_header, $p_list[$i]);
1676                   unset($v_header);
1677                 }
1678             
1679                 // ----- Close the zip file
1680                 $this->_closeFd();
1681 rizwank 1.1 
1682                 // ----- Return
1683                 return $v_result;
1684               }
1685               // ---------------------------------------------------------------------------
1686             
1687               // ---------------------------------------------------------------------------
1688               // Function : _convertHeader2FileInfo()
1689               // Description :
1690               //   This function takes the file informations from the central directory
1691               //   entries and extract the interesting parameters that will be given back.
1692               //   The resulting file infos are set in the array $p_info
1693               //     $p_info['filename'] : Filename with full path. Given by user (add),
1694               //                           extracted in the filesystem (extract).
1695               //     $p_info['stored_filename'] : Stored filename in the archive.
1696               //     $p_info['size'] = Size of the file.
1697               //     $p_info['compressed_size'] = Compressed size of the file.
1698               //     $p_info['mtime'] = Last modification date of the file.
1699               //     $p_info['comment'] = Comment associated with the file.
1700               //     $p_info['folder'] = true/false : indicates if the entry is a folder or not.
1701               //     $p_info['status'] = status of the action on the file.
1702 rizwank 1.1   // Parameters :
1703               // Return Values :
1704               // ---------------------------------------------------------------------------
1705               /**
1706               * Archive_Zip::_convertHeader2FileInfo()
1707               *
1708               * { Description }
1709               *
1710               */
1711               function _convertHeader2FileInfo($p_header, &$p_info)
1712               {
1713                 $v_result=1;
1714             
1715                 // ----- Get the interesting attributes
1716                 $p_info['filename'] = $p_header['filename'];
1717                 $p_info['stored_filename'] = $p_header['stored_filename'];
1718                 $p_info['size'] = $p_header['size'];
1719                 $p_info['compressed_size'] = $p_header['compressed_size'];
1720                 $p_info['mtime'] = $p_header['mtime'];
1721                 $p_info['comment'] = $p_header['comment'];
1722                 $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
1723 rizwank 1.1     $p_info['index'] = $p_header['index'];
1724                 $p_info['status'] = $p_header['status'];
1725             
1726                 // ----- Return
1727                 return $v_result;
1728               }
1729               // ---------------------------------------------------------------------------
1730             
1731               // ---------------------------------------------------------------------------
1732               // Function : _extractByRule()
1733               // Description :
1734               //   Extract a file or directory depending of rules (by index, by name, ...)
1735               // Parameters :
1736               //   $p_file_list : An array where will be placed the properties of each
1737               //                  extracted file
1738               //   $p_path : Path to add while writing the extracted files
1739               //   $p_remove_path : Path to remove (from the file memorized path) while writing the
1740               //                    extracted files. If the path does not match the file path,
1741               //                    the file is extracted with its memorized path.
1742               //                    $p_remove_path does not apply to 'list' mode.
1743               //                    $p_path and $p_remove_path are commulative.
1744 rizwank 1.1   // Return Values :
1745               //   1 on success,0 or less on error (see error code list)
1746               // ---------------------------------------------------------------------------
1747               /**
1748               * Archive_Zip::_extractByRule()
1749               *
1750               * { Description }
1751               *
1752               */
1753               function _extractByRule(&$p_file_list, &$p_params)
1754               {
1755                 $v_result=1;
1756             
1757             	$p_path = $p_params['add_path'];
1758             	$p_remove_path = $p_params['remove_path'];
1759             	$p_remove_all_path = $p_params['remove_all_path'];
1760             
1761                 // ----- Check the path
1762                 if (($p_path == "")
1763             	    || ((substr($p_path, 0, 1) != "/")
1764             	    && (substr($p_path, 0, 3) != "../") && (substr($p_path,1,2)!=":/")))
1765 rizwank 1.1       $p_path = "./".$p_path;
1766             
1767                 // ----- Reduce the path last (and duplicated) '/'
1768                 if (($p_path != "./") && ($p_path != "/")) {
1769                   // ----- Look for the path end '/'
1770                   while (substr($p_path, -1) == "/") {
1771                     $p_path = substr($p_path, 0, strlen($p_path)-1);
1772                   }
1773                 }
1774             
1775                 // ----- Look for path to remove format (should end by /)
1776                 if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) {
1777                   $p_remove_path .= '/';
1778                 }
1779                 $p_remove_path_size = strlen($p_remove_path);
1780             
1781                 // ----- Open the zip file
1782                 if (($v_result = $this->_openFd('rb')) != 1)
1783                 {
1784                   return $v_result;
1785                 }
1786 rizwank 1.1 
1787                 // ----- Read the central directory informations
1788                 $v_central_dir = array();
1789                 if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
1790                 {
1791                   // ----- Close the zip file
1792                   $this->_closeFd();
1793             
1794                   return $v_result;
1795                 }
1796             
1797                 // ----- Start at beginning of Central Dir
1798                 $v_pos_entry = $v_central_dir['offset'];
1799             
1800                 // ----- Read each entry
1801                 $j_start = 0;
1802                 for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) {
1803                   // ----- Read next Central dir entry
1804                   @rewind($this->_zip_fd);
1805                   if (@fseek($this->_zip_fd, $v_pos_entry)) {
1806                     $this->_closeFd();
1807 rizwank 1.1 
1808                     $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP,
1809             		                 'Invalid archive size');
1810             
1811                     return Archive_Zip::errorCode();
1812                   }
1813             
1814                   // ----- Read the file header
1815                   $v_header = array();
1816                   if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) {
1817                     $this->_closeFd();
1818             
1819                     return $v_result;
1820                   }
1821             
1822                   // ----- Store the index
1823                   $v_header['index'] = $i;
1824             
1825                   // ----- Store the file position
1826                   $v_pos_entry = ftell($this->_zip_fd);
1827             
1828 rizwank 1.1       // ----- Look for the specific extract rules
1829                   $v_extract = false;
1830             
1831                   // ----- Look for extract by name rule
1832                   if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]))
1833                       && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) {
1834             
1835                       // ----- Look if the filename is in the list
1836                       for ($j=0;
1837             		          ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]))
1838             			   && (!$v_extract);
1839             			   $j++) {
1840             
1841                           // ----- Look for a directory
1842                           if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) == "/") {
1843             
1844                               // ----- Look if the directory is in the filename path
1845                               if (   (strlen($v_header['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]))
1846                                   && (substr($v_header['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) {
1847                                   $v_extract = true;
1848                               }
1849 rizwank 1.1               }
1850                           // ----- Look for a filename
1851                           elseif ($v_header['stored_filename'] == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) {
1852                               $v_extract = true;
1853                           }
1854                       }
1855                   }
1856             
1857                   // ----- Look for extract by ereg rule
1858                   else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG]))
1859                            && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != "")) {
1860             
1861                       if (ereg($p_params[ARCHIVE_ZIP_PARAM_BY_EREG], $v_header['stored_filename'])) {
1862                           $v_extract = true;
1863                       }
1864                   }
1865             
1866                   // ----- Look for extract by preg rule
1867                   else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG]))
1868                            && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != "")) {
1869             
1870 rizwank 1.1           if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG], $v_header['stored_filename'])) {
1871                           $v_extract = true;
1872                       }
1873                   }
1874             
1875                   // ----- Look for extract by index rule
1876                   else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]))
1877                            && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) {
1878             
1879                       // ----- Look if the index is in the list
1880                       for ($j=$j_start; ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) && (!$v_extract); $j++) {
1881             
1882                           if (($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']) && ($i<=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) {
1883                               $v_extract = true;
1884                           }
1885                           if ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) {
1886                               $j_start = $j+1;
1887                           }
1888             
1889                           if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']>$i) {
1890                               break;
1891 rizwank 1.1               }
1892                       }
1893                   }
1894             
1895                   // ----- Look for no rule, which means extract all the archive
1896                   else {
1897                       $v_extract = true;
1898                   }
1899             
1900             
1901                   // ----- Look for real extraction
1902                   if ($v_extract)
1903                   {
1904             
1905                     // ----- Go to the file position
1906                     @rewind($this->_zip_fd);
1907                     if (@fseek($this->_zip_fd, $v_header['offset']))
1908                     {
1909                       // ----- Close the zip file
1910                       $this->_closeFd();
1911             
1912 rizwank 1.1           // ----- Error log
1913                       $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
1914             
1915                       // ----- Return
1916                       return Archive_Zip::errorCode();
1917                     }
1918             
1919                     // ----- Look for extraction as string
1920                     if ($p_params[ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING]) {
1921             
1922                       // ----- Extracting the file
1923                       if (($v_result = $this->_extractFileAsString($v_header, $v_string)) != 1)
1924                       {
1925                         // ----- Close the zip file
1926                         $this->_closeFd();
1927             
1928                         return $v_result;
1929                       }
1930             
1931                       // ----- Get the only interesting attributes
1932                       if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
1933 rizwank 1.1           {
1934                         // ----- Close the zip file
1935                         $this->_closeFd();
1936             
1937                         return $v_result;
1938                       }
1939             
1940                       // ----- Set the file content
1941                       $p_file_list[$v_nb_extracted]['content'] = $v_string;
1942             
1943                       // ----- Next extracted file
1944                       $v_nb_extracted++;
1945                     }
1946                     else {
1947                       // ----- Extracting the file
1948                       if (($v_result = $this->_extractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_params)) != 1)
1949                       {
1950                         // ----- Close the zip file
1951                         $this->_closeFd();
1952             
1953                         return $v_result;
1954 rizwank 1.1           }
1955             
1956                       // ----- Get the only interesting attributes
1957                       if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
1958                       {
1959                         // ----- Close the zip file
1960                         $this->_closeFd();
1961             
1962                         return $v_result;
1963                       }
1964                     }
1965                   }
1966                 }
1967             
1968                 // ----- Close the zip file
1969                 $this->_closeFd();
1970             
1971                 // ----- Return
1972                 return $v_result;
1973               }
1974               // ---------------------------------------------------------------------------
1975 rizwank 1.1 
1976               // ---------------------------------------------------------------------------
1977               // Function : _extractFile()
1978               // Description :
1979               // Parameters :
1980               // Return Values :
1981               // ---------------------------------------------------------------------------
1982               /**
1983               * Archive_Zip::_extractFile()
1984               *
1985               * { Description }
1986               *
1987               */
1988               function _extractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_params)
1989               {
1990                 $v_result=1;
1991             
1992                 // ----- Read the file header
1993                 if (($v_result = $this->_readFileHeader($v_header)) != 1)
1994                 {
1995                   // ----- Return
1996 rizwank 1.1       return $v_result;
1997                 }
1998             
1999             
2000                 // ----- Check that the file header is coherent with $p_entry info
2001                 // TBC
2002             
2003                 // ----- Look for all path to remove
2004                 if ($p_remove_all_path == true) {
2005                     // ----- Get the basename of the path
2006                     $p_entry['filename'] = basename($p_entry['filename']);
2007                 }
2008             
2009                 // ----- Look for path to remove
2010                 else if ($p_remove_path != "")
2011                 {
2012                   //if (strcmp($p_remove_path, $p_entry['filename'])==0)
2013                   if ($this->_tool_PathInclusion($p_remove_path, $p_entry['filename']) == 2)
2014                   {
2015             
2016                     // ----- Change the file status
2017 rizwank 1.1         $p_entry['status'] = "filtered";
2018             
2019                     // ----- Return
2020                     return $v_result;
2021                   }
2022             
2023                   $p_remove_path_size = strlen($p_remove_path);
2024                   if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
2025                   {
2026             
2027                     // ----- Remove the path
2028                     $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
2029             
2030                   }
2031                 }
2032             
2033                 // ----- Add the path
2034                 if ($p_path != '')
2035                 {
2036                   $p_entry['filename'] = $p_path."/".$p_entry['filename'];
2037                 }
2038 rizwank 1.1 
2039                 // ----- Look for pre-extract callback
2040                 if (   (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT]))
2041             	    && ($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] != '')) {
2042             
2043                   // ----- Generate a local information
2044                   $v_local_header = array();
2045                   $this->_convertHeader2FileInfo($p_entry, $v_local_header);
2046             
2047                   // ----- Call the callback
2048                   // Here I do not use call_user_func() because I need to send a reference to the
2049                   // header.
2050                   eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT].'(ARCHIVE_ZIP_PARAM_PRE_EXTRACT, $v_local_header);');
2051                   if ($v_result == 0) {
2052                     // ----- Change the file status
2053                     $p_entry['status'] = "skipped";
2054                     $v_result = 1;
2055                   }
2056             
2057                   // ----- Update the informations
2058                   // Only some fields can be modified
2059 rizwank 1.1       $p_entry['filename'] = $v_local_header['filename'];
2060                 }
2061             
2062                 // ----- Trace
2063             
2064                 // ----- Look if extraction should be done
2065                 if ($p_entry['status'] == 'ok') {
2066             
2067                 // ----- Look for specific actions while the file exist
2068                 if (file_exists($p_entry['filename']))
2069                 {
2070             
2071                   // ----- Look if file is a directory
2072                   if (is_dir($p_entry['filename']))
2073                   {
2074             
2075                     // ----- Change the file status
2076                     $p_entry['status'] = "already_a_directory";
2077             
2078                     // ----- Return
2079                     //return $v_result;
2080 rizwank 1.1       }
2081                   // ----- Look if file is write protected
2082                   else if (!is_writeable($p_entry['filename']))
2083                   {
2084             
2085                     // ----- Change the file status
2086                     $p_entry['status'] = "write_protected";
2087             
2088                     // ----- Return
2089                     //return $v_result;
2090                   }
2091             
2092                   // ----- Look if the extracted file is older
2093                   else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
2094                   {
2095             
2096                     // ----- Change the file status
2097                     $p_entry['status'] = "newer_exist";
2098             
2099                     // ----- Return
2100                     //return $v_result;
2101 rizwank 1.1       }
2102                 }
2103             
2104                 // ----- Check the directory availability and create it if necessary
2105                 else {
2106                   if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
2107                     $v_dir_to_check = $p_entry['filename'];
2108                   else if (!strstr($p_entry['filename'], "/"))
2109                     $v_dir_to_check = "";
2110                   else
2111                     $v_dir_to_check = dirname($p_entry['filename']);
2112             
2113                   if (($v_result = $this->_dirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
2114             
2115                     // ----- Change the file status
2116                     $p_entry['status'] = "path_creation_fail";
2117             
2118                     // ----- Return
2119                     //return $v_result;
2120                     $v_result = 1;
2121                   }
2122 rizwank 1.1     }
2123                 }
2124             
2125                 // ----- Look if extraction should be done
2126                 if ($p_entry['status'] == 'ok') {
2127             
2128                   // ----- Do the extraction (if not a folder)
2129                   if (!(($p_entry['external']&0x00000010)==0x00000010))
2130                   {
2131             
2132                     // ----- Look for not compressed file
2133                     if ($p_entry['compressed_size'] == $p_entry['size'])
2134                     {
2135             
2136                       // ----- Opening destination file
2137                       if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
2138                       {
2139             
2140                         // ----- Change the file status
2141                         $p_entry['status'] = "write_error";
2142             
2143 rizwank 1.1             // ----- Return
2144                         return $v_result;
2145                       }
2146             
2147             
2148                       // ----- Read the file by ARCHIVE_ZIP_READ_BLOCK_SIZE octets blocks
2149                       $v_size = $p_entry['compressed_size'];
2150                       while ($v_size != 0)
2151                       {
2152                         $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
2153                         $v_buffer = fread($this->_zip_fd, $v_read_size);
2154                         $v_binary_data = pack('a'.$v_read_size, $v_buffer);
2155                         @fwrite($v_dest_file, $v_binary_data, $v_read_size);
2156                         $v_size -= $v_read_size;
2157                       }
2158             
2159                       // ----- Closing the destination file
2160                       fclose($v_dest_file);
2161             
2162                       // ----- Change the file mtime
2163                       touch($p_entry['filename'], $p_entry['mtime']);
2164 rizwank 1.1         }
2165                     else
2166                     {
2167                       // ----- Trace
2168             
2169                       // ----- Opening destination file
2170                       if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
2171             
2172                         // ----- Change the file status
2173                         $p_entry['status'] = "write_error";
2174             
2175                         return $v_result;
2176                       }
2177             
2178             
2179                       // ----- Read the compressed file in a buffer (one shot)
2180                       $v_buffer = @fread($this->_zip_fd, $p_entry['compressed_size']);
2181             
2182                       // ----- Decompress the file
2183                       $v_file_content = gzinflate($v_buffer);
2184                       unset($v_buffer);
2185 rizwank 1.1 
2186                       // ----- Write the uncompressed data
2187                       @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
2188                       unset($v_file_content);
2189             
2190                       // ----- Closing the destination file
2191                       @fclose($v_dest_file);
2192             
2193                       // ----- Change the file mtime
2194                       touch($p_entry['filename'], $p_entry['mtime']);
2195                     }
2196             
2197                     // ----- Look for chmod option
2198                     if (   (isset($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]))
2199             		    && ($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD] != 0)) {
2200             
2201                       // ----- Change the mode of the file
2202                       chmod($p_entry['filename'], $p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]);
2203                     }
2204             
2205                   }
2206 rizwank 1.1     }
2207             
2208                 // ----- Look for post-extract callback
2209                 if (   (isset($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT]))
2210             	    && ($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] != '')) {
2211             
2212                   // ----- Generate a local information
2213                   $v_local_header = array();
2214                   $this->_convertHeader2FileInfo($p_entry, $v_local_header);
2215             
2216                   // ----- Call the callback
2217                   // Here I do not use call_user_func() because I need to send a reference to the
2218                   // header.
2219                   eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT].'(ARCHIVE_ZIP_PARAM_POST_EXTRACT, $v_local_header);');
2220                 }
2221             
2222                 // ----- Return
2223                 return $v_result;
2224               }
2225               // ---------------------------------------------------------------------------
2226             
2227 rizwank 1.1   // ---------------------------------------------------------------------------
2228               // Function : _extractFileAsString()
2229               // Description :
2230               // Parameters :
2231               // Return Values :
2232               // ---------------------------------------------------------------------------
2233               /**
2234               * Archive_Zip::_extractFileAsString()
2235               *
2236               * { Description }
2237               *
2238               */
2239               function _extractFileAsString(&$p_entry, &$p_string)
2240               {
2241                 $v_result=1;
2242             
2243                 // ----- Read the file header
2244                 $v_header = array();
2245                 if (($v_result = $this->_readFileHeader($v_header)) != 1)
2246                 {
2247                   // ----- Return
2248 rizwank 1.1       return $v_result;
2249                 }
2250             
2251             
2252                 // ----- Check that the file header is coherent with $p_entry info
2253                 // TBC
2254             
2255                 // ----- Trace
2256             
2257                 // ----- Do the extraction (if not a folder)
2258                 if (!(($p_entry['external']&0x00000010)==0x00000010))
2259                 {
2260                   // ----- Look for not compressed file
2261                   if ($p_entry['compressed_size'] == $p_entry['size'])
2262                   {
2263                     // ----- Trace
2264             
2265                     // ----- Reading the file
2266                     $p_string = fread($this->_zip_fd, $p_entry['compressed_size']);
2267                   }
2268                   else
2269 rizwank 1.1       {
2270                     // ----- Trace
2271             
2272                     // ----- Reading the file
2273                     $v_data = fread($this->_zip_fd, $p_entry['compressed_size']);
2274             
2275                     // ----- Decompress the file
2276                     $p_string = gzinflate($v_data);
2277                   }
2278             
2279                   // ----- Trace
2280                 }
2281                 else {
2282                     // TBC : error : can not extract a folder in a string
2283                 }
2284             
2285                 // ----- Return
2286                 return $v_result;
2287               }
2288               // ---------------------------------------------------------------------------
2289             
2290 rizwank 1.1   // ---------------------------------------------------------------------------
2291               // Function : _readFileHeader()
2292               // Description :
2293               // Parameters :
2294               // Return Values :
2295               // ---------------------------------------------------------------------------
2296               /**
2297               * Archive_Zip::_readFileHeader()
2298               *
2299               * { Description }
2300               *
2301               */
2302               function _readFileHeader(&$p_header)
2303               {
2304                 $v_result=1;
2305             
2306                 // ----- Read the 4 bytes signature
2307                 $v_binary_data = @fread($this->_zip_fd, 4);
2308                 $v_data = unpack('Vid', $v_binary_data);
2309             
2310                 // ----- Check signature
2311 rizwank 1.1     if ($v_data['id'] != 0x04034b50)
2312                 {
2313             
2314                   // ----- Error log
2315                   $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
2316             
2317                   // ----- Return
2318                   return Archive_Zip::errorCode();
2319                 }
2320             
2321                 // ----- Read the first 42 bytes of the header
2322                 $v_binary_data = fread($this->_zip_fd, 26);
2323             
2324                 // ----- Look for invalid block size
2325                 if (strlen($v_binary_data) != 26)
2326                 {
2327                   $p_header['filename'] = "";
2328                   $p_header['status'] = "invalid_header";
2329             
2330                   // ----- Error log
2331                   $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
2332 rizwank 1.1 
2333                   // ----- Return
2334                   return Archive_Zip::errorCode();
2335                 }
2336             
2337                 // ----- Extract the values
2338                 $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
2339             
2340                 // ----- Get filename
2341                 $p_header['filename'] = fread($this->_zip_fd, $v_data['filename_len']);
2342             
2343                 // ----- Get extra_fields
2344                 if ($v_data['extra_len'] != 0) {
2345                   $p_header['extra'] = fread($this->_zip_fd, $v_data['extra_len']);
2346                 }
2347                 else {
2348                   $p_header['extra'] = '';
2349                 }
2350             
2351                 // ----- Extract properties
2352                 $p_header['compression'] = $v_data['compression'];
2353 rizwank 1.1     $p_header['size'] = $v_data['size'];
2354                 $p_header['compressed_size'] = $v_data['compressed_size'];
2355                 $p_header['crc'] = $v_data['crc'];
2356                 $p_header['flag'] = $v_data['flag'];
2357             
2358                 // ----- Recuperate date in UNIX format
2359                 $p_header['mdate'] = $v_data['mdate'];
2360                 $p_header['mtime'] = $v_data['mtime'];
2361                 if ($p_header['mdate'] && $p_header['mtime'])
2362                 {
2363                   // ----- Extract time
2364                   $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
2365                   $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
2366                   $v_seconde = ($p_header['mtime'] & 0x001F)*2;
2367             
2368                   // ----- Extract date
2369                   $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
2370                   $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
2371                   $v_day = $p_header['mdate'] & 0x001F;
2372             
2373                   // ----- Get UNIX date format
2374 rizwank 1.1       $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
2375             
2376                 }
2377                 else
2378                 {
2379                   $p_header['mtime'] = time();
2380                 }
2381             
2382                 // ----- Other informations
2383             
2384                 // TBC
2385                 //for(reset($v_data); $key = key($v_data); next($v_data)) {
2386                 //}
2387             
2388                 // ----- Set the stored filename
2389                 $p_header['stored_filename'] = $p_header['filename'];
2390             
2391                 // ----- Set the status field
2392                 $p_header['status'] = "ok";
2393             
2394                 // ----- Return
2395 rizwank 1.1     return $v_result;
2396               }
2397               // ---------------------------------------------------------------------------
2398             
2399               // ---------------------------------------------------------------------------
2400               // Function : _readCentralFileHeader()
2401               // Description :
2402               // Parameters :
2403               // Return Values :
2404               // ---------------------------------------------------------------------------
2405               /**
2406               * Archive_Zip::_readCentralFileHeader()
2407               *
2408               * { Description }
2409               *
2410               */
2411               function _readCentralFileHeader(&$p_header)
2412               {
2413                 $v_result=1;
2414             
2415                 // ----- Read the 4 bytes signature
2416 rizwank 1.1     $v_binary_data = @fread($this->_zip_fd, 4);
2417                 $v_data = unpack('Vid', $v_binary_data);
2418             
2419                 // ----- Check signature
2420                 if ($v_data['id'] != 0x02014b50)
2421                 {
2422             
2423                   // ----- Error log
2424                   $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
2425             
2426                   // ----- Return
2427                   return Archive_Zip::errorCode();
2428                 }
2429             
2430                 // ----- Read the first 42 bytes of the header
2431                 $v_binary_data = fread($this->_zip_fd, 42);
2432             
2433                 // ----- Look for invalid block size
2434                 if (strlen($v_binary_data) != 42)
2435                 {
2436                   $p_header['filename'] = "";
2437 rizwank 1.1       $p_header['status'] = "invalid_header";
2438             
2439                   // ----- Error log
2440                   $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
2441             
2442                   // ----- Return
2443                   return Archive_Zip::errorCode();
2444                 }
2445             
2446                 // ----- Extract the values
2447                 $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
2448             
2449                 // ----- Get filename
2450                 if ($p_header['filename_len'] != 0)
2451                   $p_header['filename'] = fread($this->_zip_fd, $p_header['filename_len']);
2452                 else
2453                   $p_header['filename'] = '';
2454             
2455                 // ----- Get extra
2456                 if ($p_header['extra_len'] != 0)
2457                   $p_header['extra'] = fread($this->_zip_fd, $p_header['extra_len']);
2458 rizwank 1.1     else
2459                   $p_header['extra'] = '';
2460             
2461                 // ----- Get comment
2462                 if ($p_header['comment_len'] != 0)
2463                   $p_header['comment'] = fread($this->_zip_fd, $p_header['comment_len']);
2464                 else
2465                   $p_header['comment'] = '';
2466             
2467                 // ----- Extract properties
2468             
2469                 // ----- Recuperate date in UNIX format
2470                 if ($p_header['mdate'] && $p_header['mtime'])
2471                 {
2472                   // ----- Extract time
2473                   $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
2474                   $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
2475                   $v_seconde = ($p_header['mtime'] & 0x001F)*2;
2476             
2477                   // ----- Extract date
2478                   $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
2479 rizwank 1.1       $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
2480                   $v_day = $p_header['mdate'] & 0x001F;
2481             
2482                   // ----- Get UNIX date format
2483                   $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
2484             
2485                 }
2486                 else
2487                 {
2488                   $p_header['mtime'] = time();
2489                 }
2490             
2491                 // ----- Set the stored filename
2492                 $p_header['stored_filename'] = $p_header['filename'];
2493             
2494                 // ----- Set default status to ok
2495                 $p_header['status'] = 'ok';
2496             
2497                 // ----- Look if it is a directory
2498                 if (substr($p_header['filename'], -1) == '/')
2499                 {
2500 rizwank 1.1       $p_header['external'] = 0x41FF0010;
2501                 }
2502             
2503             
2504                 // ----- Return
2505                 return $v_result;
2506               }
2507               // ---------------------------------------------------------------------------
2508             
2509               // ---------------------------------------------------------------------------
2510               // Function : _readEndCentralDir()
2511               // Description :
2512               // Parameters :
2513               // Return Values :
2514               // ---------------------------------------------------------------------------
2515               /**
2516               * Archive_Zip::_readEndCentralDir()
2517               *
2518               * { Description }
2519               *
2520               */
2521 rizwank 1.1   function _readEndCentralDir(&$p_central_dir)
2522               {
2523                 $v_result=1;
2524             
2525                 // ----- Go to the end of the zip file
2526                 $v_size = filesize($this->_zipname);
2527                 @fseek($this->_zip_fd, $v_size);
2528                 if (@ftell($this->_zip_fd) != $v_size) {
2529                   $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
2530             	                   'Unable to go to the end of the archive \''
2531             					   .$this->_zipname.'\'');
2532                   return Archive_Zip::errorCode();
2533                 }
2534             
2535                 // ----- First try : look if this is an archive with no commentaries
2536             	// (most of the time)
2537                 // in this case the end of central dir is at 22 bytes of the file end
2538                 $v_found = 0;
2539                 if ($v_size > 26) {
2540                   @fseek($this->_zip_fd, $v_size-22);
2541                   if (($v_pos = @ftell($this->_zip_fd)) != ($v_size-22)) {
2542 rizwank 1.1         $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
2543             		                 'Unable to seek back to the middle of the archive \''
2544             						 .$this->_zipname.'\'');
2545                     return Archive_Zip::errorCode();
2546                   }
2547             
2548                   // ----- Read for bytes
2549                   $v_binary_data = @fread($this->_zip_fd, 4);
2550                   $v_data = unpack('Vid', $v_binary_data);
2551             
2552                   // ----- Check signature
2553                   if ($v_data['id'] == 0x06054b50) {
2554                     $v_found = 1;
2555                   }
2556             
2557                   $v_pos = ftell($this->_zip_fd);
2558                 }
2559             
2560                 // ----- Go back to the maximum possible size of the Central Dir End Record
2561                 if (!$v_found) {
2562                   $v_maximum_size = 65557; // 0xFFFF + 22;
2563 rizwank 1.1       if ($v_maximum_size > $v_size)
2564                     $v_maximum_size = $v_size;
2565                   @fseek($this->_zip_fd, $v_size-$v_maximum_size);
2566                   if (@ftell($this->_zip_fd) != ($v_size-$v_maximum_size)) {
2567                     $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
2568             		                 'Unable to seek back to the middle of the archive \''
2569             						 .$this->_zipname.'\'');
2570                     return Archive_Zip::errorCode();
2571                   }
2572             
2573                   // ----- Read byte per byte in order to find the signature
2574                   $v_pos = ftell($this->_zip_fd);
2575                   $v_bytes = 0x00000000;
2576                   while ($v_pos < $v_size) {
2577                     // ----- Read a byte
2578                     $v_byte = @fread($this->_zip_fd, 1);
2579             
2580                     // -----  Add the byte
2581                     $v_bytes = ($v_bytes << 8) | Ord($v_byte);
2582             
2583                     // ----- Compare the bytes
2584 rizwank 1.1         if ($v_bytes == 0x504b0506) {
2585                       $v_pos++;
2586                       break;
2587                     }
2588             
2589                     $v_pos++;
2590                   }
2591             
2592                   // ----- Look if not found end of central dir
2593                   if ($v_pos == $v_size) {
2594                     $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
2595             		                 "Unable to find End of Central Dir Record signature");
2596                     return Archive_Zip::errorCode();
2597                   }
2598                 }
2599             
2600                 // ----- Read the first 18 bytes of the header
2601                 $v_binary_data = fread($this->_zip_fd, 18);
2602             
2603                 // ----- Look for invalid block size
2604                 if (strlen($v_binary_data) != 18) {
2605 rizwank 1.1       $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
2606             	                   "Invalid End of Central Dir Record size : "
2607             					   .strlen($v_binary_data));
2608                   return Archive_Zip::errorCode();
2609                 }
2610             
2611                 // ----- Extract the values
2612                 $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
2613             
2614                 // ----- Check the global size
2615                 if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
2616                   $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
2617             	                   "Fail to find the right signature");
2618                   return Archive_Zip::errorCode();
2619                 }
2620             
2621                 // ----- Get comment
2622                 if ($v_data['comment_size'] != 0)
2623                   $p_central_dir['comment'] = fread($this->_zip_fd, $v_data['comment_size']);
2624                 else
2625                   $p_central_dir['comment'] = '';
2626 rizwank 1.1 
2627                 $p_central_dir['entries'] = $v_data['entries'];
2628                 $p_central_dir['disk_entries'] = $v_data['disk_entries'];
2629                 $p_central_dir['offset'] = $v_data['offset'];
2630                 $p_central_dir['size'] = $v_data['size'];
2631                 $p_central_dir['disk'] = $v_data['disk'];
2632                 $p_central_dir['disk_start'] = $v_data['disk_start'];
2633             
2634                 // ----- Return
2635                 return $v_result;
2636               }
2637               // ---------------------------------------------------------------------------
2638             
2639               // ---------------------------------------------------------------------------
2640               // Function : _deleteByRule()
2641               // Description :
2642               // Parameters :
2643               // Return Values :
2644               // ---------------------------------------------------------------------------
2645               /**
2646               * Archive_Zip::_deleteByRule()
2647 rizwank 1.1   *
2648               * { Description }
2649               *
2650               */
2651               function _deleteByRule(&$p_result_list, &$p_params)
2652               {
2653                 $v_result=1;
2654                 $v_list_detail = array();
2655             
2656                 // ----- Open the zip file
2657                 if (($v_result=$this->_openFd('rb')) != 1)
2658                 {
2659                   // ----- Return
2660                   return $v_result;
2661                 }
2662             
2663                 // ----- Read the central directory informations
2664                 $v_central_dir = array();
2665                 if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
2666                 {
2667                   $this->_closeFd();
2668 rizwank 1.1       return $v_result;
2669                 }
2670             
2671                 // ----- Go to beginning of File
2672                 @rewind($this->_zip_fd);
2673             
2674                 // ----- Scan all the files
2675                 // ----- Start at beginning of Central Dir
2676                 $v_pos_entry = $v_central_dir['offset'];
2677                 @rewind($this->_zip_fd);
2678                 if (@fseek($this->_zip_fd, $v_pos_entry)) {
2679                   // ----- Clean
2680                   $this->_closeFd();
2681             
2682                   $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP,
2683             	                   'Invalid archive size');
2684                   return Archive_Zip::errorCode();
2685                 }
2686             
2687                 // ----- Read each entry
2688                 $v_header_list = array();
2689 rizwank 1.1     $j_start = 0;
2690                 for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) {
2691             
2692                   // ----- Read the file header
2693                   $v_header_list[$v_nb_extracted] = array();
2694                   $v_result
2695             	    = $this->_readCentralFileHeader($v_header_list[$v_nb_extracted]);
2696                   if ($v_result != 1) {
2697                     // ----- Clean
2698                     $this->_closeFd();
2699             
2700                     return $v_result;
2701                   }
2702             
2703                   // ----- Store the index
2704                   $v_header_list[$v_nb_extracted]['index'] = $i;
2705             
2706                   // ----- Look for the specific extract rules
2707                   $v_found = false;
2708             
2709                   // ----- Look for extract by name rule
2710 rizwank 1.1       if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]))
2711                       && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) {
2712             
2713                       // ----- Look if the filename is in the list
2714                       for ($j=0;
2715             		       ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]))
2716             			     && (!$v_found);
2717             			   $j++) {
2718             
2719                           // ----- Look for a directory
2720                           if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) == "/") {
2721             
2722                               // ----- Look if the directory is in the filename path
2723                               if (   (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]))
2724                                   && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) {
2725                                   $v_found = true;
2726                               }
2727                               elseif (   (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
2728                                       && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) {
2729                                   $v_found = true;
2730                               }
2731 rizwank 1.1               }
2732                           // ----- Look for a filename
2733                           elseif ($v_header_list[$v_nb_extracted]['stored_filename']
2734             			          == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) {
2735                               $v_found = true;
2736                           }
2737                       }
2738                   }
2739             
2740                   // ----- Look for extract by ereg rule
2741                   else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG]))
2742                            && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != "")) {
2743             
2744                       if (ereg($p_params[ARCHIVE_ZIP_PARAM_BY_EREG],
2745             		           $v_header_list[$v_nb_extracted]['stored_filename'])) {
2746                           $v_found = true;
2747                       }
2748                   }
2749             
2750                   // ----- Look for extract by preg rule
2751                   else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG]))
2752 rizwank 1.1                && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != "")) {
2753             
2754                       if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG],
2755             		                 $v_header_list[$v_nb_extracted]['stored_filename'])) {
2756                           $v_found = true;
2757                       }
2758                   }
2759             
2760                   // ----- Look for extract by index rule
2761                   else if (   (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]))
2762                            && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) {
2763             
2764                       // ----- Look if the index is in the list
2765                       for ($j=$j_start;
2766             		       ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]))
2767             			     && (!$v_found);
2768             			   $j++) {
2769             
2770                           if (   ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start'])
2771             			      && ($i<=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) {
2772                               $v_found = true;
2773 rizwank 1.1               }
2774                           if ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) {
2775                               $j_start = $j+1;
2776                           }
2777             
2778                           if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']>$i) {
2779                               break;
2780                           }
2781                       }
2782                   }
2783             
2784                   // ----- Look for deletion
2785                   if ($v_found) {
2786                     unset($v_header_list[$v_nb_extracted]);
2787                   }
2788                   else {
2789                     $v_nb_extracted++;
2790                   }
2791                 }
2792             
2793                 // ----- Look if something need to be deleted
2794 rizwank 1.1     if ($v_nb_extracted > 0) {
2795             
2796                     // ----- Creates a temporay file
2797                     $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-')
2798             		                   .'.tmp';
2799             
2800                     // ----- Creates a temporary zip archive
2801                     $v_temp_zip = new Archive_Zip($v_zip_temp_name);
2802             
2803                     // ----- Open the temporary zip file in write mode
2804                     if (($v_result = $v_temp_zip->_openFd('wb')) != 1) {
2805                         $this->_closeFd();
2806             
2807                         // ----- Return
2808                         return $v_result;
2809                     }
2810             
2811                     // ----- Look which file need to be kept
2812                     for ($i=0; $i<sizeof($v_header_list); $i++) {
2813             
2814                         // ----- Calculate the position of the header
2815 rizwank 1.1             @rewind($this->_zip_fd);
2816                         if (@fseek($this->_zip_fd,  $v_header_list[$i]['offset'])) {
2817                             // ----- Clean
2818                             $this->_closeFd();
2819                             $v_temp_zip->_closeFd();
2820                             @unlink($v_zip_temp_name);
2821             
2822                             $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP,
2823             				                 'Invalid archive size');
2824                             return Archive_Zip::errorCode();
2825                         }
2826             
2827                         // ----- Read the file header
2828                         if (($v_result = $this->_readFileHeader($v_header_list[$i])) != 1) {
2829                             // ----- Clean
2830                             $this->_closeFd();
2831                             $v_temp_zip->_closeFd();
2832                             @unlink($v_zip_temp_name);
2833             
2834                             return $v_result;
2835                         }
2836 rizwank 1.1 
2837                         // ----- Write the file header
2838                         $v_result = $v_temp_zip->_writeFileHeader($v_header_list[$i]);
2839                         if ($v_result != 1) {
2840                             // ----- Clean
2841                             $this->_closeFd();
2842                             $v_temp_zip->_closeFd();
2843                             @unlink($v_zip_temp_name);
2844             
2845                             return $v_result;
2846                         }
2847             
2848                         // ----- Read/write the data block
2849                         $v_result = $this->_tool_CopyBlock($this->_zip_fd,
2850             			                                   $v_temp_zip->_zip_fd,
2851             								       $v_header_list[$i]['compressed_size']);
2852                         if ($v_result != 1) {
2853                             // ----- Clean
2854                             $this->_closeFd();
2855                             $v_temp_zip->_closeFd();
2856                             @unlink($v_zip_temp_name);
2857 rizwank 1.1 
2858                             return $v_result;
2859                         }
2860                     }
2861             
2862                     // ----- Store the offset of the central dir
2863                     $v_offset = @ftell($v_temp_zip->_zip_fd);
2864             
2865                     // ----- Re-Create the Central Dir files header
2866                     for ($i=0; $i<sizeof($v_header_list); $i++) {
2867                         // ----- Create the file header
2868                         $v_result=$v_temp_zip->_writeCentralFileHeader($v_header_list[$i]);
2869                         if ($v_result != 1) {
2870                         	// ----- Clean
2871                             $v_temp_zip->_closeFd();
2872                             $this->_closeFd();
2873                             @unlink($v_zip_temp_name);
2874             
2875                             return $v_result;
2876                         }
2877             
2878 rizwank 1.1             // ----- Transform the header to a 'usable' info
2879                         $v_temp_zip->_convertHeader2FileInfo($v_header_list[$i],
2880             			                                     $p_result_list[$i]);
2881                     }
2882             
2883             
2884                     // ----- Zip file comment
2885                     $v_comment = '';
2886             
2887                     // ----- Calculate the size of the central header
2888                     $v_size = @ftell($v_temp_zip->_zip_fd)-$v_offset;
2889             
2890                     // ----- Create the central dir footer
2891                     $v_result = $v_temp_zip->_writeCentralHeader(sizeof($v_header_list),
2892             		                                             $v_size, $v_offset,
2893             													 $v_comment);
2894                     if ($v_result != 1) {
2895                         // ----- Clean
2896                         unset($v_header_list);
2897                         $v_temp_zip->_closeFd();
2898                         $this->_closeFd();
2899 rizwank 1.1             @unlink($v_zip_temp_name);
2900             
2901                         return $v_result;
2902                     }
2903             
2904                     // ----- Close
2905                     $v_temp_zip->_closeFd();
2906                     $this->_closeFd();
2907             
2908                     // ----- Delete the zip file
2909                     // TBC : I should test the result ...
2910                     @unlink($this->_zipname);
2911             
2912                     // ----- Rename the temporary file
2913                     // TBC : I should test the result ...
2914                     //@rename($v_zip_temp_name, $this->_zipname);
2915                     $this->_tool_Rename($v_zip_temp_name, $this->_zipname);
2916             
2917                     // ----- Destroy the temporary archive
2918                     unset($v_temp_zip);
2919                 }
2920 rizwank 1.1 
2921                 // ----- Return
2922                 return $v_result;
2923               }
2924               // ---------------------------------------------------------------------------
2925             
2926               // ---------------------------------------------------------------------------
2927               // Function : _dirCheck()
2928               // Description :
2929               //   Check if a directory exists, if not it creates it and all the parents directory
2930               //   which may be useful.
2931               // Parameters :
2932               //   $p_dir : Directory path to check.
2933               // Return Values :
2934               //    1 : OK
2935               //   -1 : Unable to create directory
2936               // ---------------------------------------------------------------------------
2937               /**
2938               * Archive_Zip::_dirCheck()
2939               *
2940               * { Description }
2941 rizwank 1.1   *
2942               * @param [type] $p_is_dir
2943               */
2944               function _dirCheck($p_dir, $p_is_dir=false)
2945               {
2946                 $v_result = 1;
2947             
2948                 // ----- Remove the final '/'
2949                 if (($p_is_dir) && (substr($p_dir, -1)=='/')) {
2950                   $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
2951                 }
2952             
2953                 // ----- Check the directory availability
2954                 if ((is_dir($p_dir)) || ($p_dir == "")) {
2955                   return 1;
2956                 }
2957             
2958                 // ----- Extract parent directory
2959                 $p_parent_dir = dirname($p_dir);
2960             
2961                 // ----- Just a check
2962 rizwank 1.1     if ($p_parent_dir != $p_dir) {
2963                   // ----- Look for parent directory
2964                   if ($p_parent_dir != "") {
2965                     if (($v_result = $this->_dirCheck($p_parent_dir)) != 1) {
2966                       return $v_result;
2967                     }
2968                   }
2969                 }
2970             
2971                 // ----- Create the directory
2972                 if (!@mkdir($p_dir, 0777)) {
2973                   $this->_errorLog(ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL,
2974             	                   "Unable to create directory '$p_dir'");
2975                   return Archive_Zip::errorCode();
2976                 }
2977             
2978                 // ----- Return
2979                 return $v_result;
2980               }
2981               // ---------------------------------------------------------------------------
2982             
2983 rizwank 1.1   // ---------------------------------------------------------------------------
2984               // Function : _merge()
2985               // Description :
2986               //   If $p_archive_to_add does not exist, the function exit with a success result.
2987               // Parameters :
2988               // Return Values :
2989               // ---------------------------------------------------------------------------
2990               /**
2991               * Archive_Zip::_merge()
2992               *
2993               * { Description }
2994               *
2995               */
2996               function _merge(&$p_archive_to_add)
2997               {
2998                 $v_result=1;
2999             
3000                 // ----- Look if the archive_to_add exists
3001                 if (!is_file($p_archive_to_add->_zipname)) {
3002                   // ----- Nothing to merge, so merge is a success
3003                   return 1;
3004 rizwank 1.1     }
3005             
3006                 // ----- Look if the archive exists
3007                 if (!is_file($this->_zipname)) {
3008                   // ----- Do a duplicate
3009                   $v_result = $this->_duplicate($p_archive_to_add->_zipname);
3010             
3011                   return $v_result;
3012                 }
3013             
3014                 // ----- Open the zip file
3015                 if (($v_result=$this->_openFd('rb')) != 1) {
3016                   return $v_result;
3017                 }
3018             
3019                 // ----- Read the central directory informations
3020                 $v_central_dir = array();
3021                 if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) {
3022                   $this->_closeFd();
3023                   return $v_result;
3024                 }
3025 rizwank 1.1 
3026                 // ----- Go to beginning of File
3027                 @rewind($this->_zip_fd);
3028             
3029                 // ----- Open the archive_to_add file
3030                 if (($v_result=$p_archive_to_add->_openFd('rb')) != 1) {
3031                   $this->_closeFd();
3032                   return $v_result;
3033                 }
3034             
3035                 // ----- Read the central directory informations
3036                 $v_central_dir_to_add = array();
3037                 $v_result = $p_archive_to_add->_readEndCentralDir($v_central_dir_to_add);
3038                 if ($v_result != 1) {
3039                   $this->_closeFd();
3040                   $p_archive_to_add->_closeFd();
3041                   return $v_result;
3042                 }
3043             
3044                 // ----- Go to beginning of File
3045                 @rewind($p_archive_to_add->_zip_fd);
3046 rizwank 1.1 
3047                 // ----- Creates a temporay file
3048                 $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-').'.tmp';
3049             
3050                 // ----- Open the temporary file in write mode
3051                 if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) {
3052                   $this->_closeFd();
3053                   $p_archive_to_add->_closeFd();
3054                   $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
3055             	                   'Unable to open temporary file \''
3056             					   .$v_zip_temp_name.'\' in binary write mode');
3057                   return Archive_Zip::errorCode();
3058                 }
3059             
3060                 // ----- Copy the files from the archive to the temporary file
3061                 // TBC : Here I should better append the file and go back to erase the
3062             	// central dir
3063                 $v_size = $v_central_dir['offset'];
3064                 while ($v_size != 0) {
3065                   $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3066             	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3067 rizwank 1.1       $v_buffer = fread($this->_zip_fd, $v_read_size);
3068                   @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
3069                   $v_size -= $v_read_size;
3070                 }
3071             
3072                 // ----- Copy the files from the archive_to_add into the temporary file
3073                 $v_size = $v_central_dir_to_add['offset'];
3074                 while ($v_size != 0) {
3075                   $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3076             	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3077                   $v_buffer = fread($p_archive_to_add->_zip_fd, $v_read_size);
3078                   @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
3079                   $v_size -= $v_read_size;
3080                 }
3081             
3082                 // ----- Store the offset of the central dir
3083                 $v_offset = @ftell($v_zip_temp_fd);
3084             
3085                 // ----- Copy the block of file headers from the old archive
3086                 $v_size = $v_central_dir['size'];
3087                 while ($v_size != 0) {
3088 rizwank 1.1       $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3089             	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3090                   $v_buffer = @fread($this->_zip_fd, $v_read_size);
3091                   @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
3092                   $v_size -= $v_read_size;
3093                 }
3094             
3095                 // ----- Copy the block of file headers from the archive_to_add
3096                 $v_size = $v_central_dir_to_add['size'];
3097                 while ($v_size != 0) {
3098                   $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3099             	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3100                   $v_buffer = @fread($p_archive_to_add->_zip_fd, $v_read_size);
3101                   @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
3102                   $v_size -= $v_read_size;
3103                 }
3104             
3105                 // ----- Zip file comment
3106                 // TBC : I should merge the two comments
3107                 $v_comment = '';
3108             
3109 rizwank 1.1     // ----- Calculate the size of the (new) central header
3110                 $v_size = @ftell($v_zip_temp_fd)-$v_offset;
3111             
3112                 // ----- Swap the file descriptor
3113                 // Here is a trick : I swap the temporary fd with the zip fd, in order to use
3114                 // the following methods on the temporary fil and not the real archive fd
3115                 $v_swap = $this->_zip_fd;
3116                 $this->_zip_fd = $v_zip_temp_fd;
3117                 $v_zip_temp_fd = $v_swap;
3118             
3119                 // ----- Create the central dir footer
3120                 if (($v_result = $this->_writeCentralHeader($v_central_dir['entries']
3121             	                                          +$v_central_dir_to_add['entries'],
3122             												$v_size, $v_offset,
3123             												$v_comment)) != 1) {
3124                   $this->_closeFd();
3125                   $p_archive_to_add->_closeFd();
3126                   @fclose($v_zip_temp_fd);
3127                   $this->_zip_fd = null;
3128             
3129                   // ----- Reset the file list
3130 rizwank 1.1       unset($v_header_list);
3131             
3132                   // ----- Return
3133                   return $v_result;
3134                 }
3135             
3136                 // ----- Swap back the file descriptor
3137                 $v_swap = $this->_zip_fd;
3138                 $this->_zip_fd = $v_zip_temp_fd;
3139                 $v_zip_temp_fd = $v_swap;
3140             
3141                 // ----- Close
3142                 $this->_closeFd();
3143                 $p_archive_to_add->_closeFd();
3144             
3145                 // ----- Close the temporary file
3146                 @fclose($v_zip_temp_fd);
3147             
3148                 // ----- Delete the zip file
3149                 // TBC : I should test the result ...
3150                 @unlink($this->_zipname);
3151 rizwank 1.1 
3152                 // ----- Rename the temporary file
3153                 // TBC : I should test the result ...
3154                 //@rename($v_zip_temp_name, $this->_zipname);
3155                 $this->_tool_Rename($v_zip_temp_name, $this->_zipname);
3156             
3157                 // ----- Return
3158                 return $v_result;
3159               }
3160               // ---------------------------------------------------------------------------
3161             
3162               // ---------------------------------------------------------------------------
3163               // Function : _duplicate()
3164               // Description :
3165               // Parameters :
3166               // Return Values :
3167               // ---------------------------------------------------------------------------
3168               /**
3169               * Archive_Zip::_duplicate()
3170               *
3171               * { Description }
3172 rizwank 1.1   *
3173               */
3174               function _duplicate($p_archive_filename)
3175               {
3176                 $v_result=1;
3177             
3178                 // ----- Look if the $p_archive_filename exists
3179                 if (!is_file($p_archive_filename)) {
3180             
3181                   // ----- Nothing to duplicate, so duplicate is a success.
3182                   $v_result = 1;
3183             
3184                   // ----- Return
3185                   return $v_result;
3186                 }
3187             
3188                 // ----- Open the zip file
3189                 if (($v_result=$this->_openFd('wb')) != 1) {
3190                   // ----- Return
3191                   return $v_result;
3192                 }
3193 rizwank 1.1 
3194                 // ----- Open the temporary file in write mode
3195                 if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) {
3196                   $this->_closeFd();
3197                   $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
3198             	                   'Unable to open archive file \''
3199             					   .$p_archive_filename.'\' in binary write mode');
3200                   return Archive_Zip::errorCode();
3201                 }
3202             
3203                 // ----- Copy the files from the archive to the temporary file
3204                 // TBC : Here I should better append the file and go back to erase the
3205             	// central dir
3206                 $v_size = filesize($p_archive_filename);
3207                 while ($v_size != 0) {
3208                   $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3209             	                  ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3210                   $v_buffer = fread($v_zip_temp_fd, $v_read_size);
3211                   @fwrite($this->_zip_fd, $v_buffer, $v_read_size);
3212                   $v_size -= $v_read_size;
3213                 }
3214 rizwank 1.1 
3215                 // ----- Close
3216                 $this->_closeFd();
3217             
3218                 // ----- Close the temporary file
3219                 @fclose($v_zip_temp_fd);
3220             
3221                 return $v_result;
3222               }
3223               // ---------------------------------------------------------------------------
3224             
3225               /**
3226               * Archive_Zip::_check_parameters()
3227               *
3228               * { Description }
3229               *
3230               * @param integer $p_error_code
3231               * @param string $p_error_string
3232               */
3233               function _check_parameters(&$p_params, $p_default)
3234               {
3235 rizwank 1.1     
3236                 // ----- Check that param is an array
3237                 if (!is_array($p_params)) {
3238                     $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
3239             		                 'Unsupported parameter, waiting for an array');
3240                     return Archive_Zip::errorCode();
3241                 }
3242                 
3243                 // ----- Check that all the params are valid
3244                 for (reset($p_params); list($v_key, $v_value) = each($p_params); ) {
3245                 	if (!isset($p_default[$v_key])) {
3246                         $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
3247             			                 'Unsupported parameter with key \''.$v_key.'\'');
3248             
3249                         return Archive_Zip::errorCode();
3250                 	}
3251                 }
3252             
3253             	// ----- Set the default values
3254                 for (reset($p_default); list($v_key, $v_value) = each($p_default); ) {
3255                 	if (!isset($p_params[$v_key])) {
3256 rizwank 1.1     		$p_params[$v_key] = $p_default[$v_key];
3257                 	}
3258                 }
3259                 
3260                 // ----- Check specific parameters
3261                 $v_callback_list = array ('callback_pre_add','callback_post_add',
3262             	                          'callback_pre_extract','callback_post_extract');
3263                 for ($i=0; $i<sizeof($v_callback_list); $i++) {
3264                 	$v_key=$v_callback_list[$i];
3265                     if (   (isset($p_params[$v_key])) && ($p_params[$v_key] != '')) {
3266                         if (!function_exists($p_params[$v_key])) {
3267                             $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE,
3268             				                 "Callback '".$p_params[$v_key]
3269             								 ."()' is not an existing function for "
3270             								 ."parameter '".$v_key."'");
3271                             return Archive_Zip::errorCode();
3272                         }
3273             	    }
3274                 }
3275             
3276                 return(1);
3277 rizwank 1.1   }
3278               // ---------------------------------------------------------------------------
3279             
3280               // ---------------------------------------------------------------------------
3281               // Function : _errorLog()
3282               // Description :
3283               // Parameters :
3284               // ---------------------------------------------------------------------------
3285               /**
3286               * Archive_Zip::_errorLog()
3287               *
3288               * { Description }
3289               *
3290               * @param integer $p_error_code
3291               * @param string $p_error_string
3292               */
3293               function _errorLog($p_error_code=0, $p_error_string='')
3294               {
3295                   $this->_error_code = $p_error_code;
3296                   $this->_error_string = $p_error_string;
3297               }
3298 rizwank 1.1   // ---------------------------------------------------------------------------
3299             
3300               // ---------------------------------------------------------------------------
3301               // Function : _errorReset()
3302               // Description :
3303               // Parameters :
3304               // ---------------------------------------------------------------------------
3305               /**
3306               * Archive_Zip::_errorReset()
3307               *
3308               * { Description }
3309               *
3310               */
3311               function _errorReset()
3312               {
3313                   $this->_error_code = 1;
3314                   $this->_error_string = '';
3315               }
3316               // ---------------------------------------------------------------------------
3317             
3318               // ---------------------------------------------------------------------------
3319 rizwank 1.1   // Function : $this->_tool_PathReduction()
3320               // Description :
3321               // Parameters :
3322               // Return Values :
3323               // ---------------------------------------------------------------------------
3324               /**
3325               * _tool_PathReduction()
3326               *
3327               * { Description }
3328               *
3329               */
3330               function _tool_PathReduction($p_dir)
3331               {
3332                 $v_result = "";
3333             
3334                 // ----- Look for not empty path
3335                 if ($p_dir != "")
3336                 {
3337                   // ----- Explode path by directory names
3338                   $v_list = explode("/", $p_dir);
3339             
3340 rizwank 1.1       // ----- Study directories from last to first
3341                   for ($i=sizeof($v_list)-1; $i>=0; $i--)
3342                   {
3343                     // ----- Look for current path
3344                     if ($v_list[$i] == ".")
3345                     {
3346                       // ----- Ignore this directory
3347                       // Should be the first $i=0, but no check is done
3348                     }
3349                     else if ($v_list[$i] == "..")
3350                     {
3351                       // ----- Ignore it and ignore the $i-1
3352                       $i--;
3353                     }
3354                     else if (($v_list[$i] == "") && ($i!=(sizeof($v_list)-1)) && ($i!=0))
3355                     {
3356                       // ----- Ignore only the double '//' in path,
3357                       // but not the first and last '/'
3358                     }
3359                     else
3360                     {
3361 rizwank 1.1           $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
3362                     }
3363                   }
3364                 }
3365             
3366                 // ----- Return
3367                 return $v_result;
3368               }
3369               // ---------------------------------------------------------------------------
3370             
3371               // ---------------------------------------------------------------------------
3372               // Function : $this->_tool_PathInclusion()
3373               // Description :
3374               //   This function indicates if the path $p_path is under the $p_dir tree. Or,
3375               //   said in an other way, if the file or sub-dir $p_path is inside the dir
3376               //   $p_dir.
3377               //   The function indicates also if the path is exactly the same as the dir.
3378               //   This function supports path with duplicated '/' like '//', but does not
3379               //   support '.' or '..' statements.
3380               // Parameters :
3381               // Return Values :
3382 rizwank 1.1   //   0 if $p_path is not inside directory $p_dir
3383               //   1 if $p_path is inside directory $p_dir
3384               //   2 if $p_path is exactly the same as $p_dir
3385               // ---------------------------------------------------------------------------
3386               /**
3387               * _tool_PathInclusion()
3388               *
3389               * { Description }
3390               *
3391               */
3392               function _tool_PathInclusion($p_dir, $p_path)
3393               {
3394                 $v_result = 1;
3395             
3396                 // ----- Explode dir and path by directory separator
3397                 $v_list_dir = explode("/", $p_dir);
3398                 $v_list_dir_size = sizeof($v_list_dir);
3399                 $v_list_path = explode("/", $p_path);
3400                 $v_list_path_size = sizeof($v_list_path);
3401             
3402                 // ----- Study directories paths
3403 rizwank 1.1     $i = 0;
3404                 $j = 0;
3405                 while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
3406             
3407                   // ----- Look for empty dir (path reduction)
3408                   if ($v_list_dir[$i] == '') {
3409                     $i++;
3410                     continue;
3411                   }
3412                   if ($v_list_path[$j] == '') {
3413                     $j++;
3414                     continue;
3415                   }
3416             
3417                   // ----- Compare the items
3418                   if (   ($v_list_dir[$i] != $v_list_path[$j])
3419             	      && ($v_list_dir[$i] != '')
3420             		  && ( $v_list_path[$j] != ''))  {
3421                     $v_result = 0;
3422                   }
3423             
3424 rizwank 1.1       // ----- Next items
3425                   $i++;
3426                   $j++;
3427                 }
3428             
3429                 // ----- Look if everything seems to be the same
3430                 if ($v_result) {
3431                   // ----- Skip all the empty items
3432                   while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
3433                   while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
3434             
3435                   if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
3436                     // ----- There are exactly the same
3437                     $v_result = 2;
3438                   }
3439                   else if ($i < $v_list_dir_size) {
3440                     // ----- The path is shorter than the dir
3441                     $v_result = 0;
3442                   }
3443                 }
3444             
3445 rizwank 1.1     // ----- Return
3446                 return $v_result;
3447               }
3448               // ---------------------------------------------------------------------------
3449             
3450               // ---------------------------------------------------------------------------
3451               // Function : $this->_tool_CopyBlock()
3452               // Description :
3453               // Parameters :
3454               //   $p_mode : read/write compression mode
3455               //             0 : src & dest normal
3456               //             1 : src gzip, dest normal
3457               //             2 : src normal, dest gzip
3458               //             3 : src & dest gzip
3459               // Return Values :
3460               // ---------------------------------------------------------------------------
3461               /**
3462               * _tool_CopyBlock()
3463               *
3464               * { Description }
3465               *
3466 rizwank 1.1   * @param integer $p_mode
3467               */
3468               function _tool_CopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
3469               {
3470                 $v_result = 1;
3471             
3472                 if ($p_mode==0)
3473                 {
3474                   while ($p_size != 0)
3475                   {
3476                     $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3477             		                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3478                     $v_buffer = @fread($p_src, $v_read_size);
3479                     @fwrite($p_dest, $v_buffer, $v_read_size);
3480                     $p_size -= $v_read_size;
3481                   }
3482                 }
3483                 else if ($p_mode==1)
3484                 {
3485                   while ($p_size != 0)
3486                   {
3487 rizwank 1.1         $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3488             		                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3489                     $v_buffer = @gzread($p_src, $v_read_size);
3490                     @fwrite($p_dest, $v_buffer, $v_read_size);
3491                     $p_size -= $v_read_size;
3492                   }
3493                 }
3494                 else if ($p_mode==2)
3495                 {
3496                   while ($p_size != 0)
3497                   {
3498                     $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3499             		                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3500                     $v_buffer = @fread($p_src, $v_read_size);
3501                     @gzwrite($p_dest, $v_buffer, $v_read_size);
3502                     $p_size -= $v_read_size;
3503                   }
3504                 }
3505                 else if ($p_mode==3)
3506                 {
3507                   while ($p_size != 0)
3508 rizwank 1.1       {
3509                     $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
3510             		                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
3511                     $v_buffer = @gzread($p_src, $v_read_size);
3512                     @gzwrite($p_dest, $v_buffer, $v_read_size);
3513                     $p_size -= $v_read_size;
3514                   }
3515                 }
3516             
3517                 // ----- Return
3518                 return $v_result;
3519               }
3520               // ---------------------------------------------------------------------------
3521             
3522               // ---------------------------------------------------------------------------
3523               // Function : $this->_tool_Rename()
3524               // Description :
3525               //   This function tries to do a simple rename() function. If it fails, it
3526               //   tries to copy the $p_src file in a new $p_dest file and then unlink the
3527               //   first one.
3528               // Parameters :
3529 rizwank 1.1   //   $p_src : Old filename
3530               //   $p_dest : New filename
3531               // Return Values :
3532               //   1 on success, 0 on failure.
3533               // ---------------------------------------------------------------------------
3534               /**
3535               * _tool_Rename()
3536               *
3537               * { Description }
3538               *
3539               */
3540               function _tool_Rename($p_src, $p_dest)
3541               {
3542                 $v_result = 1;
3543             
3544                 // ----- Try to rename the files
3545                 if (!@rename($p_src, $p_dest)) {
3546             
3547                   // ----- Try to copy & unlink the src
3548                   if (!@copy($p_src, $p_dest)) {
3549                     $v_result = 0;
3550 rizwank 1.1       }
3551                   else if (!@unlink($p_src)) {
3552                     $v_result = 0;
3553                   }
3554                 }
3555             
3556                 // ----- Return
3557                 return $v_result;
3558               }
3559               // ---------------------------------------------------------------------------
3560             
3561               // ---------------------------------------------------------------------------
3562               // Function : $this->_tool_TranslateWinPath()
3563               // Description :
3564               //   Translate windows path by replacing '\' by '/' and optionally removing
3565               //   drive letter.
3566               // Parameters :
3567               //   $p_path : path to translate.
3568               //   $p_remove_disk_letter : true | false
3569               // Return Values :
3570               //   The path translated.
3571 rizwank 1.1   // ---------------------------------------------------------------------------
3572               /**
3573               * _tool_TranslateWinPath()
3574               *
3575               * { Description }
3576               *
3577               * @param [type] $p_remove_disk_letter
3578               */
3579               function _tool_TranslateWinPath($p_path, $p_remove_disk_letter=true)
3580               {
3581                 if (stristr(php_uname(), 'windows')) {
3582                   // ----- Look for potential disk letter
3583                   if (   ($p_remove_disk_letter)
3584             	      && (($v_position = strpos($p_path, ':')) != false)) {
3585                       $p_path = substr($p_path, $v_position+1);
3586                   }
3587                   // ----- Change potential windows directory separator
3588                   if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
3589                       $p_path = strtr($p_path, '\\', '/');
3590                   }
3591                 }
3592 rizwank 1.1     return $p_path;
3593               }
3594               // ---------------------------------------------------------------------------
3595             
3596               }
3597               // End of class
3598             
3599             ?>

Rizwan Kassim
Powered by
ViewCVS 0.9.2