00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00036
00037 define( 'ARCHIVE_ZIP_READ_BLOCK_SIZE', 2048 );
00038
00039
00040 define( 'ARCHIVE_ZIP_SEPARATOR', ',' );
00041
00042 define( 'ARCHIVE_ZIP_TEMPORARY_DIR', '' );
00043
00044
00045 define( 'ARCHIVE_ZIP_ERR_NO_ERROR', 0 );
00046 define( 'ARCHIVE_ZIP_ERR_WRITE_OPEN_FAIL', -1 );
00047 define( 'ARCHIVE_ZIP_ERR_READ_OPEN_FAIL', -2 );
00048 define( 'ARCHIVE_ZIP_ERR_INVALID_PARAMETER', -3 );
00049 define( 'ARCHIVE_ZIP_ERR_MISSING_FILE', -4 );
00050 define( 'ARCHIVE_ZIP_ERR_FILENAME_TOO_LONG', -5 );
00051 define( 'ARCHIVE_ZIP_ERR_INVALID_ZIP', -6 );
00052 define( 'ARCHIVE_ZIP_ERR_BAD_EXTRACTED_FILE', -7 );
00053 define( 'ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL', -8 );
00054 define( 'ARCHIVE_ZIP_ERR_BAD_EXTENSION', -9 );
00055 define( 'ARCHIVE_ZIP_ERR_BAD_FORMAT', -10 );
00056 define( 'ARCHIVE_ZIP_ERR_DELETE_FILE_FAIL', -11 );
00057 define( 'ARCHIVE_ZIP_ERR_RENAME_FILE_FAIL', -12 );
00058 define( 'ARCHIVE_ZIP_ERR_BAD_CHECKSUM', -13 );
00059 define( 'ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
00060 define( 'ARCHIVE_ZIP_ERR_MISSING_OPTION_VALUE', -15 );
00061 define( 'ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE', -16 );
00062
00063
00064 define( 'ARCHIVE_ZIP_WARN_NO_WARNING', 0 );
00065 define( 'ARCHIVE_ZIP_WARN_FILE_EXIST', 1 );
00066
00067
00068 define( 'ARCHIVE_ZIP_PARAM_PATH', 'path' );
00069 define( 'ARCHIVE_ZIP_PARAM_ADD_PATH', 'add_path' );
00070 define( 'ARCHIVE_ZIP_PARAM_REMOVE_PATH', 'remove_path' );
00071 define( 'ARCHIVE_ZIP_PARAM_REMOVE_ALL_PATH', 'remove_all_path' );
00072 define( 'ARCHIVE_ZIP_PARAM_SET_CHMOD', 'set_chmod' );
00073 define( 'ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING', 'extract_as_string' );
00074 define( 'ARCHIVE_ZIP_PARAM_NO_COMPRESSION', 'no_compression' );
00075
00076 define( 'ARCHIVE_ZIP_PARAM_PRE_EXTRACT', 'callback_pre_extract' );
00077 define( 'ARCHIVE_ZIP_PARAM_POST_EXTRACT', 'callback_post_extract' );
00078 define( 'ARCHIVE_ZIP_PARAM_PRE_ADD', 'callback_pre_add' );
00079 define( 'ARCHIVE_ZIP_PARAM_POST_ADD', 'callback_post_add' );
00080
00081
00082
00089 class em_unzip {
00095 var $_zipname='';
00096
00102 var $_zip_fd=0;
00103
00107 var $_error_code=1;
00108
00112 var $_error_string='';
00113
00122 function em_unzip($p_zipname) {
00123
00124
00125 if (!extension_loaded('zlib')) {
00126 die("The extension 'zlib' couldn't be found.\n".
00127 "Please make sure your version of PHP was built ".
00128 "with 'zlib' support.\n");
00129 }
00130
00131
00132 $this->_zipname = $p_zipname;
00133 $this->_zip_fd = 0;
00134
00135 return;
00136 }
00137
00138
00139
00159 function extract($p_params=0) {
00160 $this->_errorReset();
00161
00162
00163 if (!$this->_checkFormat()) {
00164 return(0);
00165 }
00166
00167
00168 if ($p_params === 0) {
00169 $p_params = array();
00170 }
00171 if ($this->_check_parameters($p_params,
00172 array ('extract_as_string' => false,
00173 'add_path' => '',
00174 'remove_path' => '',
00175 'remove_all_path' => false,
00176 'callback_pre_extract' => '',
00177 'callback_post_extract' => '',
00178 'set_chmod' => 0) ) != 1) {
00179 return 0;
00180 }
00181
00182
00183 $v_list = array();
00184 if ($this->_extractByRule($v_list, $p_params) != 1) {
00185 unset($v_list);
00186 return(0);
00187 }
00188
00189 return $v_list;
00190 }
00191
00198 function errorCode() {
00199 return($this->_error_code);
00200 }
00201
00209 function errorName($p_with_code=false) {
00210 $v_const_list = get_defined_constants();
00211
00212
00213 for (reset($v_const_list);
00214 list($v_key, $v_value) = each($v_const_list);) {
00215 if (substr($v_key, 0, strlen('ARCHIVE_ZIP_ERR_')) =='ARCHIVE_ZIP_ERR_') {
00216 $v_error_list[$v_key] = $v_value;
00217 }
00218 }
00219
00220
00221 $v_key=array_search($this->_error_code, $v_error_list, true);
00222 if ($v_key!=false) {
00223 $v_value = $v_key;
00224 } else {
00225 $v_value = 'NoName';
00226 }
00227
00228 if ($p_with_code) {
00229 return($v_value.' ('.$this->_error_code.')');
00230 } else {
00231 return($v_value);
00232 }
00233 }
00234
00245 function errorInfo($p_full=false) {
00246 if ($p_full) {
00247 return($this->errorName(true)." : ".$this->_error_string);
00248 } else {
00249 return($this->_error_string." [code ".$this->_error_code."]");
00250 }
00251 }
00252
00253
00261 function _checkFormat($p_level=0) {
00262 $v_result = true;
00263
00264
00265 $this->_errorReset();
00266
00267
00268 if (!is_file($this->_zipname)) {
00269
00270 $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE,
00271 "Missing archive file '".$this->_zipname."'");
00272 return(false);
00273 }
00274
00275
00276 if (!is_readable($this->_zipname)) {
00277
00278 $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
00279 "Unable to read archive '".$this->_zipname."'");
00280 return(false);
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 return $v_result;
00294 }
00295
00296
00303 function _openFd($p_mode) {
00304 $v_result=1;
00305
00306
00307 if ($this->_zip_fd != 0) {
00308 $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
00309 'Zip file \''.$this->_zipname.'\' already open');
00310 return em_unzip::errorCode();
00311 }
00312
00313
00314 if (($this->_zip_fd = @fopen($this->_zipname, $p_mode)) == 0) {
00315 $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
00316 'Unable to open archive \''.$this->_zipname
00317 .'\' in '.$p_mode.' mode');
00318 return em_unzip::errorCode();
00319 }
00320
00321
00322 return $v_result;
00323 }
00324
00331 function _closeFd() {
00332 $v_result=1;
00333
00334 if ($this->_zip_fd != 0)
00335 @fclose($this->_zip_fd);
00336 $this->_zip_fd = 0;
00337
00338
00339 return $v_result;
00340 }
00341
00342
00343
00350 function _convertHeader2FileInfo($p_header, &$p_info) {
00351 $v_result=1;
00352
00353
00354 $p_info['filename'] = $p_header['filename'];
00355 $p_info['stored_filename'] = $p_header['stored_filename'];
00356 $p_info['size'] = $p_header['size'];
00357 $p_info['compressed_size'] = $p_header['compressed_size'];
00358 $p_info['mtime'] = $p_header['mtime'];
00359 $p_info['comment'] = $p_header['comment'];
00360 $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
00361 $p_info['index'] = $p_header['index'];
00362 $p_info['status'] = $p_header['status'];
00363
00364
00365 return $v_result;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00390 function _extractByRule(&$p_file_list, &$p_params)
00391 {
00392 $v_result=1;
00393
00394 $p_path = $p_params['add_path'];
00395 $p_remove_path = $p_params['remove_path'];
00396 $p_remove_all_path = $p_params['remove_all_path'];
00397
00398
00399 if (($p_path == "")
00400 || ((substr($p_path, 0, 1) != "/")
00401 && (substr($p_path, 0, 3) != "../") && (substr($p_path,1,2)!=":/")))
00402 $p_path = "./".$p_path;
00403
00404
00405 if (($p_path != "./") && ($p_path != "/")) {
00406
00407 while (substr($p_path, -1) == "/") {
00408 $p_path = substr($p_path, 0, strlen($p_path)-1);
00409 }
00410 }
00411
00412
00413 if (($v_result = $this->_openFd('rb')) != 1)
00414 {
00415 return $v_result;
00416 }
00417
00418
00419 $v_central_dir = array();
00420 if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
00421 {
00422
00423 $this->_closeFd();
00424
00425 return $v_result;
00426 }
00427
00428
00429 $v_pos_entry = $v_central_dir['offset'];
00430
00431
00432 $j_start = 0;
00433 for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) {
00434
00435 @rewind($this->_zip_fd);
00436 if (@fseek($this->_zip_fd, $v_pos_entry)) {
00437 $this->_closeFd();
00438
00439 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP,
00440 'Invalid archive size');
00441
00442 return em_unzip::errorCode();
00443 }
00444
00445
00446 $v_header = array();
00447 if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) {
00448 $this->_closeFd();
00449
00450 return $v_result;
00451 }
00452
00453
00454 $v_header['index'] = $i;
00455
00456
00457 $v_pos_entry = ftell($this->_zip_fd);
00458
00459
00460
00461 @rewind($this->_zip_fd);
00462 if (@fseek($this->_zip_fd, $v_header['offset']))
00463 {
00464
00465 $this->_closeFd();
00466
00467
00468 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
00469
00470
00471 return em_unzip::errorCode();
00472 }
00473
00474
00475 if (($v_result = $this->_extractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_params)) != 1)
00476 {
00477
00478 $this->_closeFd();
00479
00480 return $v_result;
00481 }
00482
00483
00484 if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
00485 {
00486
00487 $this->_closeFd();
00488
00489 return $v_result;
00490 }
00491 }
00492
00493
00494 $this->_closeFd();
00495
00496
00497 return $v_result;
00498 }
00499
00506 function _extractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_params) {
00507 $v_result=1;
00508
00509
00510 if (($v_result = $this->_readFileHeader($v_header)) != 1)
00511 {
00512
00513 return $v_result;
00514 }
00515
00516
00517
00518
00519
00520
00521 if ($p_remove_all_path == true) {
00522
00523 $p_entry['filename'] = basename($p_entry['filename']);
00524 }
00525
00526
00527 else if ($p_remove_path != "")
00528 {
00529
00530 if ($this->_tool_PathInclusion($p_remove_path, $p_entry['filename']) == 2)
00531 {
00532
00533
00534 $p_entry['status'] = "filtered";
00535
00536
00537 return $v_result;
00538 }
00539
00540 $p_remove_path_size = strlen($p_remove_path);
00541 if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
00542 {
00543
00544
00545 $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
00546
00547 }
00548 }
00549
00550
00551 if ($p_path != '')
00552 {
00553 $p_entry['filename'] = $p_path."/".$p_entry['filename'];
00554 }
00555
00556
00557 if ( (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT]))
00558 && ($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] != '')) {
00559
00560
00561 $v_local_header = array();
00562 $this->_convertHeader2FileInfo($p_entry, $v_local_header);
00563
00564
00565
00566
00567 eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT].'(ARCHIVE_ZIP_PARAM_PRE_EXTRACT, $v_local_header);');
00568 if ($v_result == 0) {
00569
00570 $p_entry['status'] = "skipped";
00571 $v_result = 1;
00572 }
00573
00574
00575
00576 $p_entry['filename'] = $v_local_header['filename'];
00577 }
00578
00579
00580
00581
00582 if ($p_entry['status'] == 'ok') {
00583
00584
00585 if (file_exists($p_entry['filename'])) {
00586
00587 if (is_dir($p_entry['filename'])) {
00588
00589 $p_entry['status'] = "already_a_directory";
00590
00591
00592
00593 }
00594
00595 else if (!is_writeable($p_entry['filename'])) {
00596
00597 $p_entry['status'] = "write_protected";
00598
00599
00600
00601 }
00602
00603
00604 else if (filemtime($p_entry['filename']) > $p_entry['mtime']) {
00605
00606 $p_entry['status'] = "newer_exist";
00607
00608
00609
00610 }
00611 }
00612
00613
00614 else {
00615 if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
00616 $v_dir_to_check = $p_entry['filename'];
00617 else if (!strstr($p_entry['filename'], "/"))
00618 $v_dir_to_check = "";
00619 else
00620 $v_dir_to_check = dirname($p_entry['filename']);
00621
00622 if (($v_result = $this->_dirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
00623
00624 $p_entry['status'] = "path_creation_fail";
00625
00626
00627
00628 $v_result = 1;
00629 }
00630 }
00631 }
00632
00633
00634 if ($p_entry['status'] == 'ok') {
00635
00636 if (!(($p_entry['external']&0x00000010)==0x00000010)) {
00637
00638 if ($p_entry['compressed_size'] == $p_entry['size']) {
00639
00640 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
00641
00642 $p_entry['status'] = "write_error";
00643
00644
00645 return $v_result;
00646 }
00647
00648
00649
00650 $v_size = $p_entry['compressed_size'];
00651 while ($v_size != 0) {
00652 $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
00653 $v_buffer = fread($this->_zip_fd, $v_read_size);
00654 $v_binary_data = pack('a'.$v_read_size, $v_buffer);
00655 @fwrite($v_dest_file, $v_binary_data, $v_read_size);
00656 $v_size -= $v_read_size;
00657 }
00658
00659
00660 fclose($v_dest_file);
00661
00662
00663 touch($p_entry['filename'], $p_entry['mtime']);
00664 } else {
00665
00666
00667
00668 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
00669
00670
00671 $p_entry['status'] = "write_error";
00672
00673 return $v_result;
00674 }
00675
00676
00677
00678 $v_buffer = @fread($this->_zip_fd, $p_entry['compressed_size']);
00679
00680
00681 $v_file_content = gzinflate($v_buffer);
00682 unset($v_buffer);
00683
00684
00685 @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
00686 unset($v_file_content);
00687
00688
00689 @fclose($v_dest_file);
00690
00691
00692 @touch($p_entry['filename'], $p_entry['mtime']);
00693 }
00694
00695
00696 if ( (isset($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]))
00697 && ($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD] != 0)) {
00698
00699
00700 chmod($p_entry['filename'], $p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]);
00701 }
00702
00703 }
00704 }
00705
00706
00707 if ( (isset($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT]))
00708 && ($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] != '')) {
00709
00710
00711 $v_local_header = array();
00712 $this->_convertHeader2FileInfo($p_entry, $v_local_header);
00713
00714
00715
00716
00717 eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT].'(ARCHIVE_ZIP_PARAM_POST_EXTRACT, $v_local_header);');
00718 }
00719
00720
00721 return $v_result;
00722 }
00723
00730 function _readFileHeader(&$p_header) {
00731 $v_result=1;
00732
00733
00734 $v_binary_data = @fread($this->_zip_fd, 4);
00735 $v_data = unpack('Vid', $v_binary_data);
00736
00737
00738 if ($v_data['id'] != 0x04034b50) {
00739
00740
00741 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
00742
00743
00744 return em_unzip::errorCode();
00745 }
00746
00747
00748 $v_binary_data = fread($this->_zip_fd, 26);
00749
00750
00751 if (strlen($v_binary_data) != 26) {
00752 $p_header['filename'] = "";
00753 $p_header['status'] = "invalid_header";
00754
00755
00756 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
00757
00758
00759 return em_unzip::errorCode();
00760 }
00761
00762
00763 $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
00764
00765
00766 $p_header['filename'] = fread($this->_zip_fd, $v_data['filename_len']);
00767
00768
00769 if ($v_data['extra_len'] != 0) {
00770 $p_header['extra'] = fread($this->_zip_fd, $v_data['extra_len']);
00771 }
00772 else {
00773 $p_header['extra'] = '';
00774 }
00775
00776
00777 $p_header['compression'] = $v_data['compression'];
00778 $p_header['size'] = $v_data['size'];
00779 $p_header['compressed_size'] = $v_data['compressed_size'];
00780 $p_header['crc'] = $v_data['crc'];
00781 $p_header['flag'] = $v_data['flag'];
00782
00783
00784 $p_header['mdate'] = $v_data['mdate'];
00785 $p_header['mtime'] = $v_data['mtime'];
00786 if ($p_header['mdate'] && $p_header['mtime']) {
00787
00788 $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
00789 $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
00790 $v_seconde = ($p_header['mtime'] & 0x001F)*2;
00791
00792
00793 $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
00794 $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
00795 $v_day = $p_header['mdate'] & 0x001F;
00796
00797
00798 $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
00799
00800 } else {
00801 $p_header['mtime'] = time();
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811 $p_header['stored_filename'] = $p_header['filename'];
00812
00813
00814 $p_header['status'] = "ok";
00815
00816
00817 return $v_result;
00818 }
00819
00826 function _readCentralFileHeader(&$p_header) {
00827 $v_result=1;
00828
00829
00830 $v_binary_data = @fread($this->_zip_fd, 4);
00831 $v_data = unpack('Vid', $v_binary_data);
00832
00833
00834 if ($v_data['id'] != 0x02014b50) {
00835
00836
00837 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
00838
00839
00840 return em_unzip::errorCode();
00841 }
00842
00843
00844 $v_binary_data = fread($this->_zip_fd, 42);
00845
00846
00847 if (strlen($v_binary_data) != 42) {
00848 $p_header['filename'] = "";
00849 $p_header['status'] = "invalid_header";
00850
00851
00852 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
00853
00854
00855 return em_unzip::errorCode();
00856 }
00857
00858
00859 $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);
00860
00861
00862 if ($p_header['filename_len'] != 0)
00863 $p_header['filename'] = fread($this->_zip_fd, $p_header['filename_len']);
00864 else
00865 $p_header['filename'] = '';
00866
00867
00868 if ($p_header['extra_len'] != 0)
00869 $p_header['extra'] = fread($this->_zip_fd, $p_header['extra_len']);
00870 else
00871 $p_header['extra'] = '';
00872
00873
00874 if ($p_header['comment_len'] != 0)
00875 $p_header['comment'] = fread($this->_zip_fd, $p_header['comment_len']);
00876 else
00877 $p_header['comment'] = '';
00878
00879
00880
00881
00882 if ($p_header['mdate'] && $p_header['mtime']) {
00883
00884 $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
00885 $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
00886 $v_seconde = ($p_header['mtime'] & 0x001F)*2;
00887
00888
00889 $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
00890 $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
00891 $v_day = $p_header['mdate'] & 0x001F;
00892
00893
00894 $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
00895
00896 } else {
00897 $p_header['mtime'] = time();
00898 }
00899
00900
00901 $p_header['stored_filename'] = $p_header['filename'];
00902
00903
00904 $p_header['status'] = 'ok';
00905
00906
00907 if (substr($p_header['filename'], -1) == '/') {
00908 $p_header['external'] = 0x41FF0010;
00909 }
00910
00911
00912
00913 return $v_result;
00914 }
00915
00922 function _readEndCentralDir(&$p_central_dir) {
00923 $v_result=1;
00924
00925
00926 $v_size = filesize($this->_zipname);
00927 @fseek($this->_zip_fd, $v_size);
00928 if (@ftell($this->_zip_fd) != $v_size) {
00929 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00930 'Unable to go to the end of the archive \''
00931 .$this->_zipname.'\'');
00932 return em_unzip::errorCode();
00933 }
00934
00935
00936
00937
00938 $v_found = 0;
00939 if ($v_size > 26) {
00940 @fseek($this->_zip_fd, $v_size-22);
00941 if (($v_pos = @ftell($this->_zip_fd)) != ($v_size-22)) {
00942 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00943 'Unable to seek back to the middle of the archive \''
00944 .$this->_zipname.'\'');
00945 return em_unzip::errorCode();
00946 }
00947
00948
00949 $v_binary_data = @fread($this->_zip_fd, 4);
00950 $v_data = unpack('Vid', $v_binary_data);
00951
00952
00953 if ($v_data['id'] == 0x06054b50) {
00954 $v_found = 1;
00955 }
00956
00957 $v_pos = ftell($this->_zip_fd);
00958 }
00959
00960
00961 if (!$v_found) {
00962 $v_maximum_size = 65557;
00963 if ($v_maximum_size > $v_size)
00964 $v_maximum_size = $v_size;
00965 @fseek($this->_zip_fd, $v_size-$v_maximum_size);
00966 if (@ftell($this->_zip_fd) != ($v_size-$v_maximum_size)) {
00967 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00968 'Unable to seek back to the middle of the archive \''
00969 .$this->_zipname.'\'');
00970 return em_unzip::errorCode();
00971 }
00972
00973
00974 $v_pos = ftell($this->_zip_fd);
00975 $v_bytes = 0x00000000;
00976 while ($v_pos < $v_size) {
00977
00978 $v_byte = @fread($this->_zip_fd, 1);
00979
00980
00981 $v_bytes = ($v_bytes << 8) | Ord($v_byte);
00982
00983
00984 if ($v_bytes == 0x504b0506) {
00985 $v_pos++;
00986 break;
00987 }
00988
00989 $v_pos++;
00990 }
00991
00992
00993 if ($v_pos == $v_size) {
00994 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00995 "Unable to find End of Central Dir Record signature");
00996 return em_unzip::errorCode();
00997 }
00998 }
00999
01000
01001 $v_binary_data = fread($this->_zip_fd, 18);
01002
01003
01004 if (strlen($v_binary_data) != 18) {
01005 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
01006 "Invalid End of Central Dir Record size : "
01007 .strlen($v_binary_data));
01008 return em_unzip::errorCode();
01009 }
01010
01011
01012 $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
01013
01014
01015 if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
01016 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
01017 "Fail to find the right signature");
01018 return em_unzip::errorCode();
01019 }
01020
01021
01022 if ($v_data['comment_size'] != 0)
01023 $p_central_dir['comment'] = fread($this->_zip_fd, $v_data['comment_size']);
01024 else
01025 $p_central_dir['comment'] = '';
01026
01027 $p_central_dir['entries'] = $v_data['entries'];
01028 $p_central_dir['disk_entries'] = $v_data['disk_entries'];
01029 $p_central_dir['offset'] = $v_data['offset'];
01030 $p_central_dir['size'] = $v_data['size'];
01031 $p_central_dir['disk'] = $v_data['disk'];
01032 $p_central_dir['disk_start'] = $v_data['disk_start'];
01033
01034
01035 return $v_result;
01036 }
01037
01045 function _dirCheck($p_dir, $p_is_dir=false) {
01046 $v_result = 1;
01047
01048
01049 if (($p_is_dir) && (substr($p_dir, -1)=='/')) {
01050 $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
01051 }
01052
01053
01054 if ((is_dir($p_dir)) || ($p_dir == "")) {
01055 return 1;
01056 }
01057
01058
01059 $p_parent_dir = dirname($p_dir);
01060
01061
01062 if ($p_parent_dir != $p_dir) {
01063
01064 if ($p_parent_dir != "") {
01065 if (($v_result = $this->_dirCheck($p_parent_dir)) != 1) {
01066 return $v_result;
01067 }
01068 }
01069 }
01070
01071
01072 if (!@mkdir($p_dir, 0777)) {
01073 $this->_errorLog(ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL,
01074 "Unable to create directory '$p_dir'");
01075 return em_unzip::errorCode();
01076 }
01077
01078
01079 return $v_result;
01080 }
01081
01090 function _check_parameters(&$p_params, $p_default) {
01091
01092
01093 if (!is_array($p_params)) {
01094 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
01095 'Unsupported parameter, waiting for an array');
01096 return em_unzip::errorCode();
01097 }
01098
01099
01100 for (reset($p_params); list($v_key, $v_value) = each($p_params); ) {
01101 if (!isset($p_default[$v_key])) {
01102 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
01103 'Unsupported parameter with key \''.$v_key.'\'');
01104
01105 return em_unzip::errorCode();
01106 }
01107 }
01108
01109
01110 for (reset($p_default); list($v_key, $v_value) = each($p_default); ) {
01111 if (!isset($p_params[$v_key])) {
01112 $p_params[$v_key] = $p_default[$v_key];
01113 }
01114 }
01115
01116
01117 $v_callback_list = array ('callback_pre_add','callback_post_add',
01118 'callback_pre_extract','callback_post_extract');
01119 for ($i=0; $i<sizeof($v_callback_list); $i++) {
01120 $v_key=$v_callback_list[$i];
01121 if ( (isset($p_params[$v_key])) && ($p_params[$v_key] != '')) {
01122 if (!function_exists($p_params[$v_key])) {
01123 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE,
01124 "Callback '".$p_params[$v_key]
01125 ."()' is not an existing function for "
01126 ."parameter '".$v_key."'");
01127 return em_unzip::errorCode();
01128 }
01129 }
01130 }
01131
01132 return(1);
01133 }
01134
01143 function _errorLog($p_error_code=0, $p_error_string='') {
01144 $this->_error_code = $p_error_code;
01145 $this->_error_string = $p_error_string;
01146 }
01147
01154 function _errorReset() {
01155 $this->_error_code = 1;
01156 $this->_error_string = '';
01157 }
01158
01165 function _tool_PathReduction($p_dir) {
01166 $v_result = "";
01167
01168
01169 if ($p_dir != "") {
01170
01171 $v_list = explode("/", $p_dir);
01172
01173
01174 for ($i=sizeof($v_list)-1; $i>=0; $i--) {
01175
01176 if ($v_list[$i] == ".") {
01177
01178
01179 } else if ($v_list[$i] == "..") {
01180
01181 $i--;
01182 } else if (($v_list[$i] == "") && ($i!=(sizeof($v_list)-1)) && ($i!=0)) {
01183
01184
01185 } else {
01186 $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
01187 }
01188 }
01189 }
01190
01191
01192 return $v_result;
01193 }
01194
01201 function _tool_PathInclusion($p_dir, $p_path) {
01202 $v_result = 1;
01203
01204
01205 $v_list_dir = explode("/", $p_dir);
01206 $v_list_dir_size = sizeof($v_list_dir);
01207 $v_list_path = explode("/", $p_path);
01208 $v_list_path_size = sizeof($v_list_path);
01209
01210
01211 $i = 0;
01212 $j = 0;
01213 while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
01214
01215 if ($v_list_dir[$i] == '') {
01216 $i++;
01217 continue;
01218 }
01219 if ($v_list_path[$j] == '') {
01220 $j++;
01221 continue;
01222 }
01223
01224
01225 if ( ($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
01226 $v_result = 0;
01227 }
01228
01229
01230 $i++;
01231 $j++;
01232 }
01233
01234
01235 if ($v_result) {
01236
01237 while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
01238 while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
01239
01240 if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
01241
01242 $v_result = 2;
01243 } else if ($i < $v_list_dir_size) {
01244
01245 $v_result = 0;
01246 }
01247 }
01248
01249
01250 return $v_result;
01251 }
01252
01260 function _tool_CopyBlock($p_src, $p_dest, $p_size, $p_mode=0) {
01261 $v_result = 1;
01262
01263 if ($p_mode==0) {
01264 while ($p_size != 0) {
01265 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01266 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01267 $v_buffer = @fread($p_src, $v_read_size);
01268 @fwrite($p_dest, $v_buffer, $v_read_size);
01269 $p_size -= $v_read_size;
01270 }
01271 } else if ($p_mode==1) {
01272 while ($p_size != 0) {
01273 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01274 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01275 $v_buffer = @gzread($p_src, $v_read_size);
01276 @fwrite($p_dest, $v_buffer, $v_read_size);
01277 $p_size -= $v_read_size;
01278 }
01279 } else if ($p_mode==2) {
01280 while ($p_size != 0) {
01281 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01282 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01283 $v_buffer = @fread($p_src, $v_read_size);
01284 @gzwrite($p_dest, $v_buffer, $v_read_size);
01285 $p_size -= $v_read_size;
01286 }
01287 }
01288 else if ($p_mode==3) {
01289 while ($p_size != 0) {
01290 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01291 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01292 $v_buffer = @gzread($p_src, $v_read_size);
01293 @gzwrite($p_dest, $v_buffer, $v_read_size);
01294 $p_size -= $v_read_size;
01295 }
01296 }
01297
01298
01299 return $v_result;
01300 }
01301
01308 function _tool_Rename($p_src, $p_dest) {
01309 $v_result = 1;
01310
01311
01312 if (!@rename($p_src, $p_dest)) {
01313
01314
01315 if (!@copy($p_src, $p_dest)) {
01316 $v_result = 0;
01317 } else if (!@unlink($p_src)) {
01318 $v_result = 0;
01319 }
01320 }
01321
01322
01323 return $v_result;
01324 }
01325
01333 function _tool_TranslateWinPath($p_path, $p_remove_disk_letter=true) {
01334 if (stristr(php_uname(), 'windows')) {
01335
01336 if ( ($p_remove_disk_letter)
01337 && (($v_position = strpos($p_path, ':')) != false)) {
01338 $p_path = substr($p_path, $v_position+1);
01339 }
01340
01341 if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
01342 $p_path = strtr($p_path, '\\', '/');
01343 }
01344 }
01345 return $p_path;
01346 }
01347
01348 }
01349
01350 ?>