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