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