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