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