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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00083
00084
00085
00086
00087
00088
00089 class em_unzip {
00090
00091
00092
00093
00094
00095 var $_zipname='';
00096
00097
00098
00099
00100
00101
00102 var $_zip_fd=0;
00103
00104
00105
00106
00107 var $_error_code=1;
00108
00109
00110
00111
00112 var $_error_string='';
00113
00114
00115
00116
00117
00118
00119
00120
00121
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
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
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
00192
00193
00194
00195
00196
00197
00198 function errorCode() {
00199 return($this->_error_code);
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
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
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
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
00254
00255
00256
00257
00258
00259
00260
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
00297
00298
00299
00300
00301
00302
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
00325
00326
00327
00328
00329
00330
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
00344
00345
00346
00347
00348
00349
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
00384
00385
00386
00387
00388
00389
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
00500
00501
00502
00503
00504
00505
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
00725
00726
00727
00728
00729
00730
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
00821
00822
00823
00824
00825
00826
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
00917
00918
00919
00920
00921
00922
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
01039
01040
01041
01042
01043
01044
01045
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
01083
01084
01085
01086
01087
01088
01089
01090
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
01136
01137
01138
01139
01140
01141
01142
01143
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
01149
01150
01151
01152
01153
01154
01155 function _errorReset() {
01156 $this->_error_code = 1;
01157 $this->_error_string = '';
01158 }
01159
01160
01161
01162
01163
01164
01165
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
01196
01197
01198
01199
01200
01201
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
01254
01255
01256
01257
01258
01259
01260
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
01303
01304
01305
01306
01307
01308
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
01327
01328
01329
01330
01331
01332
01333
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 ?>