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 $v_header = '';
00511 if (($v_result = $this->_readFileHeader($v_header)) != 1)
00512 {
00513
00514 return $v_result;
00515 }
00516
00517
00518
00519
00520
00521
00522 if ($p_remove_all_path == true) {
00523
00524 $p_entry['filename'] = basename($p_entry['filename']);
00525 }
00526
00527
00528 else if ($p_remove_path != "")
00529 {
00530
00531 if ($this->_tool_PathInclusion($p_remove_path, $p_entry['filename']) == 2)
00532 {
00533
00534
00535 $p_entry['status'] = "filtered";
00536
00537
00538 return $v_result;
00539 }
00540
00541 $p_remove_path_size = strlen($p_remove_path);
00542 if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
00543 {
00544
00545
00546 $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
00547
00548 }
00549 }
00550
00551
00552 if ($p_path != '')
00553 {
00554 $p_entry['filename'] = $p_path."/".$p_entry['filename'];
00555 }
00556
00557
00558 if ( (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT]))
00559 && ($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] != '')) {
00560
00561
00562 $v_local_header = array();
00563 $this->_convertHeader2FileInfo($p_entry, $v_local_header);
00564
00565
00566
00567
00568 eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT].'(ARCHIVE_ZIP_PARAM_PRE_EXTRACT, $v_local_header);');
00569 if ($v_result == 0) {
00570
00571 $p_entry['status'] = "skipped";
00572 $v_result = 1;
00573 }
00574
00575
00576
00577 $p_entry['filename'] = $v_local_header['filename'];
00578 }
00579
00580
00581
00582
00583 if ($p_entry['status'] == 'ok') {
00584
00585
00586 if (file_exists($p_entry['filename'])) {
00587
00588 if (is_dir($p_entry['filename'])) {
00589
00590 $p_entry['status'] = "already_a_directory";
00591
00592
00593
00594 }
00595
00596 else if (!is_writeable($p_entry['filename'])) {
00597
00598 $p_entry['status'] = "write_protected";
00599
00600
00601
00602 }
00603
00604
00605 else if (filemtime($p_entry['filename']) > $p_entry['mtime']) {
00606
00607 $p_entry['status'] = "newer_exist";
00608
00609
00610
00611 }
00612 }
00613
00614
00615 else {
00616 if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
00617 $v_dir_to_check = $p_entry['filename'];
00618 else if (!strstr($p_entry['filename'], "/"))
00619 $v_dir_to_check = "";
00620 else
00621 $v_dir_to_check = dirname($p_entry['filename']);
00622
00623 if (($v_result = $this->_dirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
00624
00625 $p_entry['status'] = "path_creation_fail";
00626
00627
00628
00629 $v_result = 1;
00630 }
00631 }
00632 }
00633
00634
00635 if ($p_entry['status'] == 'ok') {
00636
00637 if (!(($p_entry['external']&0x00000010)==0x00000010)) {
00638
00639 if ($p_entry['compressed_size'] == $p_entry['size']) {
00640
00641 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
00642
00643 $p_entry['status'] = "write_error";
00644
00645
00646 return $v_result;
00647 }
00648
00649
00650
00651 $v_size = $p_entry['compressed_size'];
00652 while ($v_size != 0) {
00653 $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
00654 $v_buffer = fread($this->_zip_fd, $v_read_size);
00655 $v_binary_data = pack('a'.$v_read_size, $v_buffer);
00656 @fwrite($v_dest_file, $v_binary_data, $v_read_size);
00657 $v_size -= $v_read_size;
00658 }
00659
00660
00661 fclose($v_dest_file);
00662
00663
00664 touch($p_entry['filename'], $p_entry['mtime']);
00665 } else {
00666
00667
00668
00669 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
00670
00671
00672 $p_entry['status'] = "write_error";
00673
00674 return $v_result;
00675 }
00676
00677
00678
00679 $v_buffer = @fread($this->_zip_fd, $p_entry['compressed_size']);
00680
00681
00682 $v_file_content = gzinflate($v_buffer);
00683 unset($v_buffer);
00684
00685
00686 @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
00687 unset($v_file_content);
00688
00689
00690 @fclose($v_dest_file);
00691
00692
00693 @touch($p_entry['filename'], $p_entry['mtime']);
00694 }
00695
00696
00697 if ( (isset($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]))
00698 && ($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD] != 0)) {
00699
00700
00701 chmod($p_entry['filename'], $p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]);
00702 }
00703
00704 }
00705 }
00706
00707
00708 if ( (isset($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT]))
00709 && ($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] != '')) {
00710
00711
00712 $v_local_header = array();
00713 $this->_convertHeader2FileInfo($p_entry, $v_local_header);
00714
00715
00716
00717
00718 eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT].'(ARCHIVE_ZIP_PARAM_POST_EXTRACT, $v_local_header);');
00719 }
00720
00721
00722 return $v_result;
00723 }
00724
00731 function _readFileHeader(&$p_header) {
00732 $v_result=1;
00733
00734
00735 $v_binary_data = @fread($this->_zip_fd, 4);
00736 $v_data = unpack('Vid', $v_binary_data);
00737
00738
00739 if ($v_data['id'] != 0x04034b50) {
00740
00741
00742 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
00743
00744
00745 return em_unzip::errorCode();
00746 }
00747
00748
00749 $v_binary_data = fread($this->_zip_fd, 26);
00750
00751
00752 if (strlen($v_binary_data) != 26) {
00753 $p_header['filename'] = "";
00754 $p_header['status'] = "invalid_header";
00755
00756
00757 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
00758
00759
00760 return em_unzip::errorCode();
00761 }
00762
00763
00764 $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
00765
00766
00767 $p_header['filename'] = fread($this->_zip_fd, $v_data['filename_len']);
00768
00769
00770 if ($v_data['extra_len'] != 0) {
00771 $p_header['extra'] = fread($this->_zip_fd, $v_data['extra_len']);
00772 }
00773 else {
00774 $p_header['extra'] = '';
00775 }
00776
00777
00778 $p_header['compression'] = $v_data['compression'];
00779 $p_header['size'] = $v_data['size'];
00780 $p_header['compressed_size'] = $v_data['compressed_size'];
00781 $p_header['crc'] = $v_data['crc'];
00782 $p_header['flag'] = $v_data['flag'];
00783
00784
00785 $p_header['mdate'] = $v_data['mdate'];
00786 $p_header['mtime'] = $v_data['mtime'];
00787 if ($p_header['mdate'] && $p_header['mtime']) {
00788
00789 $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
00790 $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
00791 $v_seconde = ($p_header['mtime'] & 0x001F)*2;
00792
00793
00794 $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
00795 $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
00796 $v_day = $p_header['mdate'] & 0x001F;
00797
00798
00799 $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
00800
00801 } else {
00802 $p_header['mtime'] = time();
00803 }
00804
00805
00806
00807
00808
00809
00810
00811
00812 $p_header['stored_filename'] = $p_header['filename'];
00813
00814
00815 $p_header['status'] = "ok";
00816
00817
00818 return $v_result;
00819 }
00820
00827 function _readCentralFileHeader(&$p_header) {
00828 $v_result=1;
00829
00830
00831 $v_binary_data = @fread($this->_zip_fd, 4);
00832 $v_data = unpack('Vid', $v_binary_data);
00833
00834
00835 if ($v_data['id'] != 0x02014b50) {
00836
00837
00838 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
00839
00840
00841 return em_unzip::errorCode();
00842 }
00843
00844
00845 $v_binary_data = fread($this->_zip_fd, 42);
00846
00847
00848 if (strlen($v_binary_data) != 42) {
00849 $p_header['filename'] = "";
00850 $p_header['status'] = "invalid_header";
00851
00852
00853 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
00854
00855
00856 return em_unzip::errorCode();
00857 }
00858
00859
00860 $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);
00861
00862
00863 if ($p_header['filename_len'] != 0)
00864 $p_header['filename'] = fread($this->_zip_fd, $p_header['filename_len']);
00865 else
00866 $p_header['filename'] = '';
00867
00868
00869 if ($p_header['extra_len'] != 0)
00870 $p_header['extra'] = fread($this->_zip_fd, $p_header['extra_len']);
00871 else
00872 $p_header['extra'] = '';
00873
00874
00875 if ($p_header['comment_len'] != 0)
00876 $p_header['comment'] = fread($this->_zip_fd, $p_header['comment_len']);
00877 else
00878 $p_header['comment'] = '';
00879
00880
00881
00882
00883 if ($p_header['mdate'] && $p_header['mtime']) {
00884
00885 $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
00886 $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
00887 $v_seconde = ($p_header['mtime'] & 0x001F)*2;
00888
00889
00890 $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
00891 $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
00892 $v_day = $p_header['mdate'] & 0x001F;
00893
00894
00895 $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
00896
00897 } else {
00898 $p_header['mtime'] = time();
00899 }
00900
00901
00902 $p_header['stored_filename'] = $p_header['filename'];
00903
00904
00905 $p_header['status'] = 'ok';
00906
00907
00908 if (substr($p_header['filename'], -1) == '/') {
00909 $p_header['external'] = 0x41FF0010;
00910 }
00911
00912
00913
00914 return $v_result;
00915 }
00916
00923 function _readEndCentralDir(&$p_central_dir) {
00924 $v_result=1;
00925
00926
00927 $v_size = filesize($this->_zipname);
00928 @fseek($this->_zip_fd, $v_size);
00929 if (@ftell($this->_zip_fd) != $v_size) {
00930 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00931 'Unable to go to the end of the archive \''
00932 .$this->_zipname.'\'');
00933 return em_unzip::errorCode();
00934 }
00935
00936
00937
00938
00939 $v_found = 0;
00940 if ($v_size > 26) {
00941 @fseek($this->_zip_fd, $v_size-22);
00942 if (($v_pos = @ftell($this->_zip_fd)) != ($v_size-22)) {
00943 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00944 'Unable to seek back to the middle of the archive \''
00945 .$this->_zipname.'\'');
00946 return em_unzip::errorCode();
00947 }
00948
00949
00950 $v_binary_data = @fread($this->_zip_fd, 4);
00951 $v_data = unpack('Vid', $v_binary_data);
00952
00953
00954 if ($v_data['id'] == 0x06054b50) {
00955 $v_found = 1;
00956 }
00957
00958 $v_pos = ftell($this->_zip_fd);
00959 }
00960
00961
00962 if (!$v_found) {
00963 $v_maximum_size = 65557;
00964 if ($v_maximum_size > $v_size)
00965 $v_maximum_size = $v_size;
00966 @fseek($this->_zip_fd, $v_size-$v_maximum_size);
00967 if (@ftell($this->_zip_fd) != ($v_size-$v_maximum_size)) {
00968 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00969 'Unable to seek back to the middle of the archive \''
00970 .$this->_zipname.'\'');
00971 return em_unzip::errorCode();
00972 }
00973
00974
00975 $v_pos = ftell($this->_zip_fd);
00976 $v_bytes = 0x00000000;
00977 while ($v_pos < $v_size) {
00978
00979 $v_byte = @fread($this->_zip_fd, 1);
00980
00981
00982 $v_bytes = ($v_bytes << 8) | Ord($v_byte);
00983
00984
00985 if ($v_bytes == 0x504b0506) {
00986 $v_pos++;
00987 break;
00988 }
00989
00990 $v_pos++;
00991 }
00992
00993
00994 if ($v_pos == $v_size) {
00995 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00996 "Unable to find End of Central Dir Record signature");
00997 return em_unzip::errorCode();
00998 }
00999 }
01000
01001
01002 $v_binary_data = fread($this->_zip_fd, 18);
01003
01004
01005 if (strlen($v_binary_data) != 18) {
01006 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
01007 "Invalid End of Central Dir Record size : "
01008 .strlen($v_binary_data));
01009 return em_unzip::errorCode();
01010 }
01011
01012
01013 $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
01014
01015
01016 if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
01017 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
01018 "Fail to find the right signature");
01019 return em_unzip::errorCode();
01020 }
01021
01022
01023 if ($v_data['comment_size'] != 0)
01024 $p_central_dir['comment'] = fread($this->_zip_fd, $v_data['comment_size']);
01025 else
01026 $p_central_dir['comment'] = '';
01027
01028 $p_central_dir['entries'] = $v_data['entries'];
01029 $p_central_dir['disk_entries'] = $v_data['disk_entries'];
01030 $p_central_dir['offset'] = $v_data['offset'];
01031 $p_central_dir['size'] = $v_data['size'];
01032 $p_central_dir['disk'] = $v_data['disk'];
01033 $p_central_dir['disk_start'] = $v_data['disk_start'];
01034
01035
01036 return $v_result;
01037 }
01038
01046 function _dirCheck($p_dir, $p_is_dir=false) {
01047 $v_result = 1;
01048
01049
01050 if (($p_is_dir) && (substr($p_dir, -1)=='/')) {
01051 $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
01052 }
01053
01054
01055 if ((is_dir($p_dir)) || ($p_dir == "")) {
01056 return 1;
01057 }
01058
01059
01060 $p_parent_dir = dirname($p_dir);
01061
01062
01063 if ($p_parent_dir != $p_dir) {
01064
01065 if ($p_parent_dir != "") {
01066 if (($v_result = $this->_dirCheck($p_parent_dir)) != 1) {
01067 return $v_result;
01068 }
01069 }
01070 }
01071
01072
01073 if (!@mkdir($p_dir, 0777)) {
01074 $this->_errorLog(ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL,
01075 "Unable to create directory '$p_dir'");
01076 return em_unzip::errorCode();
01077 }
01078
01079
01080 return $v_result;
01081 }
01082
01091 function _check_parameters(&$p_params, $p_default) {
01092
01093
01094 if (!is_array($p_params)) {
01095 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
01096 'Unsupported parameter, waiting for an array');
01097 return em_unzip::errorCode();
01098 }
01099
01100
01101 for (reset($p_params); list($v_key, $v_value) = each($p_params); ) {
01102 if (!isset($p_default[$v_key])) {
01103 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
01104 'Unsupported parameter with key \''.$v_key.'\'');
01105
01106 return em_unzip::errorCode();
01107 }
01108 }
01109
01110
01111 for (reset($p_default); list($v_key, $v_value) = each($p_default); ) {
01112 if (!isset($p_params[$v_key])) {
01113 $p_params[$v_key] = $p_default[$v_key];
01114 }
01115 }
01116
01117
01118 $v_callback_list = array ('callback_pre_add','callback_post_add',
01119 'callback_pre_extract','callback_post_extract');
01120 for ($i=0; $i<sizeof($v_callback_list); $i++) {
01121 $v_key=$v_callback_list[$i];
01122 if ( (isset($p_params[$v_key])) && ($p_params[$v_key] != '')) {
01123 if (!function_exists($p_params[$v_key])) {
01124 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE,
01125 "Callback '".$p_params[$v_key]
01126 ."()' is not an existing function for "
01127 ."parameter '".$v_key."'");
01128 return em_unzip::errorCode();
01129 }
01130 }
01131 }
01132
01133 return(1);
01134 }
01135
01144 function _errorLog($p_error_code=0, $p_error_string='') {
01145 $this->_error_code = $p_error_code;
01146 $this->_error_string = $p_error_string;
01147 }
01148
01155 function _errorReset() {
01156 $this->_error_code = 1;
01157 $this->_error_string = '';
01158 }
01159
01166 function _tool_PathReduction($p_dir) {
01167 $v_result = "";
01168
01169
01170 if ($p_dir != "") {
01171
01172 $v_list = explode("/", $p_dir);
01173
01174
01175 for ($i=sizeof($v_list)-1; $i>=0; $i--) {
01176
01177 if ($v_list[$i] == ".") {
01178
01179
01180 } else if ($v_list[$i] == "..") {
01181
01182 $i--;
01183 } else if (($v_list[$i] == "") && ($i!=(sizeof($v_list)-1)) && ($i!=0)) {
01184
01185
01186 } else {
01187 $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
01188 }
01189 }
01190 }
01191
01192
01193 return $v_result;
01194 }
01195
01202 function _tool_PathInclusion($p_dir, $p_path) {
01203 $v_result = 1;
01204
01205
01206 $v_list_dir = explode("/", $p_dir);
01207 $v_list_dir_size = sizeof($v_list_dir);
01208 $v_list_path = explode("/", $p_path);
01209 $v_list_path_size = sizeof($v_list_path);
01210
01211
01212 $i = 0;
01213 $j = 0;
01214 while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
01215
01216 if ($v_list_dir[$i] == '') {
01217 $i++;
01218 continue;
01219 }
01220 if ($v_list_path[$j] == '') {
01221 $j++;
01222 continue;
01223 }
01224
01225
01226 if ( ($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
01227 $v_result = 0;
01228 }
01229
01230
01231 $i++;
01232 $j++;
01233 }
01234
01235
01236 if ($v_result) {
01237
01238 while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
01239 while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
01240
01241 if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
01242
01243 $v_result = 2;
01244 } else if ($i < $v_list_dir_size) {
01245
01246 $v_result = 0;
01247 }
01248 }
01249
01250
01251 return $v_result;
01252 }
01253
01261 function _tool_CopyBlock($p_src, $p_dest, $p_size, $p_mode=0) {
01262 $v_result = 1;
01263
01264 if ($p_mode==0) {
01265 while ($p_size != 0) {
01266 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01267 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01268 $v_buffer = @fread($p_src, $v_read_size);
01269 @fwrite($p_dest, $v_buffer, $v_read_size);
01270 $p_size -= $v_read_size;
01271 }
01272 } else if ($p_mode==1) {
01273 while ($p_size != 0) {
01274 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01275 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01276 $v_buffer = @gzread($p_src, $v_read_size);
01277 @fwrite($p_dest, $v_buffer, $v_read_size);
01278 $p_size -= $v_read_size;
01279 }
01280 } else if ($p_mode==2) {
01281 while ($p_size != 0) {
01282 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01283 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01284 $v_buffer = @fread($p_src, $v_read_size);
01285 @gzwrite($p_dest, $v_buffer, $v_read_size);
01286 $p_size -= $v_read_size;
01287 }
01288 }
01289 else if ($p_mode==3) {
01290 while ($p_size != 0) {
01291 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01292 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01293 $v_buffer = @gzread($p_src, $v_read_size);
01294 @gzwrite($p_dest, $v_buffer, $v_read_size);
01295 $p_size -= $v_read_size;
01296 }
01297 }
01298
01299
01300 return $v_result;
01301 }
01302
01309 function _tool_Rename($p_src, $p_dest) {
01310 $v_result = 1;
01311
01312
01313 if (!@rename($p_src, $p_dest)) {
01314
01315
01316 if (!@copy($p_src, $p_dest)) {
01317 $v_result = 0;
01318 } else if (!@unlink($p_src)) {
01319 $v_result = 0;
01320 }
01321 }
01322
01323
01324 return $v_result;
01325 }
01326
01334 function _tool_TranslateWinPath($p_path, $p_remove_disk_letter=true) {
01335 if (stristr(php_uname(), 'windows')) {
01336
01337 if ( ($p_remove_disk_letter)
01338 && (($v_position = strpos($p_path, ':')) != false)) {
01339 $p_path = substr($p_path, $v_position+1);
01340 }
01341
01342 if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
01343 $p_path = strtr($p_path, '\\', '/');
01344 }
01345 }
01346 return $p_path;
01347 }
01348
01349 }
01350
01351 ?>