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