00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 include_once( 'lib/ezfile/classes/ezarchivehandler.php' );
00023
00024
00025
00026
00027
00028
00029
00030
00031 class eZTARArchiveHandler extends eZArchiveHandler
00032 {
00033
00034
00035
00036 var $_tarname='';
00037
00038
00039
00040
00041 var $_compress=false;
00042
00043
00044
00045
00046
00047
00048
00049
00050 var $_compress_type='none';
00051
00052
00053
00054
00055 var $_temp_tarname='';
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 function eZTARArchiveHandler( &$fileHandler, $p_tarname, $p_compress = false )
00073 {
00074 $this->eZArchiveHandler( $fileHandler );
00075
00076 $this->_tarname = $p_tarname;
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 $this->_compress = $p_compress;
00091 }
00092
00093
00094
00095 function _eZTARArchiveHandler()
00096 {
00097 $this->_close();
00098
00099 if ( $this->_temp_tarname != '' )
00100 $this->fileUnlink( $this->_temp_tarname );
00101
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 function create($p_filelist)
00127 {
00128 return $this->createModify($p_filelist, '', '');
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 function add($p_filelist)
00148 {
00149 return $this->addModify($p_filelist, '', '');
00150 }
00151
00152
00153
00154 function extract($p_path='')
00155 {
00156 return $this->extractModify($p_path, '');
00157 }
00158
00159
00160
00161 function listContent()
00162 {
00163 $v_list_detail = array();
00164
00165 if ($this->_openRead()) {
00166 if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
00167 unset($v_list_detail);
00168 $v_list_detail = 0;
00169 }
00170 $this->_close();
00171 }
00172
00173 return $v_list_detail;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 function createModify($p_filelist, $p_add_dir, $p_remove_dir='')
00212 {
00213 $v_result = true;
00214
00215 if (!$this->_openWrite())
00216 return false;
00217
00218 if ($p_filelist != '') {
00219 if (is_array($p_filelist))
00220 $v_list = $p_filelist;
00221 elseif (is_string($p_filelist))
00222 $v_list = explode(" ", $p_filelist);
00223 else {
00224 $this->_cleanFile();
00225 $this->_error('Invalid file list');
00226 return false;
00227 }
00228
00229 $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
00230 }
00231
00232 if ($v_result) {
00233 $this->_writeFooter();
00234 $this->_close();
00235 } else
00236 $this->_cleanFile();
00237
00238 return $v_result;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
00281 {
00282 $v_result = true;
00283
00284 if (!@is_file($this->_tarname))
00285 $v_result = $this->createModify($p_filelist, $p_add_dir, $p_remove_dir);
00286 else {
00287 if (is_array($p_filelist))
00288 $v_list = $p_filelist;
00289 elseif (is_string($p_filelist))
00290 $v_list = explode(" ", $p_filelist);
00291 else {
00292 $this->_error('Invalid file list');
00293 return false;
00294 }
00295
00296 $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
00297 }
00298
00299 return $v_result;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 function addString($p_filename, $p_string)
00316 {
00317 $v_result = true;
00318
00319 if (!@is_file($this->_tarname)) {
00320 if (!$this->_openWrite()) {
00321 return false;
00322 }
00323 $this->_close();
00324 }
00325
00326 if (!$this->_openAppend())
00327 return false;
00328
00329
00330 $v_result = $this->_addString($p_filename, $p_string);
00331
00332 $this->_writeFooter();
00333
00334 $this->_close();
00335
00336 return $v_result;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 function extractModify($p_path, $p_remove_path)
00374 {
00375 $v_result = true;
00376 $v_list_detail = array();
00377
00378 if ($v_result = $this->_openRead()) {
00379 $v_result = $this->_extractList($p_path, $v_list_detail, "complete", 0, $p_remove_path);
00380 $this->_close();
00381 }
00382
00383 return $v_result;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 function extractInString($p_filename)
00396 {
00397 if ($this->_openRead()) {
00398 $v_result = $this->_extractInString($p_filename);
00399 $this->_close();
00400 } else {
00401 $v_result = NULL;
00402 }
00403
00404 return $v_result;
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 function extractList($p_filelist, $p_path='', $p_remove_path='')
00426 {
00427 $v_result = true;
00428 $v_list_detail = array();
00429
00430 if (is_array($p_filelist))
00431 $v_list = $p_filelist;
00432 elseif (is_string($p_filelist))
00433 $v_list = explode(" ", $p_filelist);
00434 else {
00435 $this->_error('Invalid string list');
00436 return false;
00437 }
00438
00439 if ($v_result = $this->_openRead()) {
00440 $v_result = $this->_extractList($p_path, $v_list_detail, "partial", $v_list, $p_remove_path);
00441 $this->_close();
00442 }
00443
00444 return $v_result;
00445 }
00446
00447
00448
00449 function _error($p_message)
00450 {
00451
00452
00453 eZDebug::writeError( $p_message, 'eZTARArchiveHandler' );
00454 }
00455
00456
00457
00458 function _warning($p_message)
00459 {
00460
00461
00462 eZDebug::writeWarning( $p_message, 'eZTARArchiveHandler' );
00463 }
00464
00465
00466
00467 function _openWrite()
00468 {
00469 $result = $this->fileOpen( $this->_tarname, 'w' );
00470
00471
00472
00473
00474
00475 if ( $result == 0 )
00476 {
00477 $this->_error('Unable to open in write mode \''.$this->_tarname.'\'');
00478 return false;
00479 }
00480
00481 return true;
00482 }
00483
00484
00485
00486 function _openRead()
00487 {
00488 if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
00489
00490
00491 if ($this->_temp_tarname == '')
00492 {
00493 $this->_temp_tarname = uniqid('tar').'.tmp';
00494 eZFileHandler::copy( $this->_tarname,
00495 $this->_temp_tarname );
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 }
00513
00514
00515 $v_filename = $this->_temp_tarname;
00516
00517 } else
00518
00519 $v_filename = $this->_tarname;
00520
00521 $result = $this->fileOpen( $v_filename, 'rb' );
00522
00523
00524
00525
00526
00527 if ( $result == 0 )
00528 {
00529 $this->_error('Unable to open in read mode \''.$v_filename.'\'');
00530 return false;
00531 }
00532
00533 return true;
00534 }
00535
00536
00537
00538 function _openReadWrite()
00539 {
00540 $result = $this->fileOpen( $this->_tarname, 'r+b' );
00541
00542
00543
00544
00545
00546 if ( $result == 0 )
00547 {
00548 $this->_error('Unable to open in read/write mode \''.$this->_tarname.'\'');
00549 return false;
00550 }
00551
00552 return true;
00553 }
00554
00555
00556
00557 function _close()
00558 {
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 $this->fileClose();
00569
00570
00571
00572 if ( $this->_temp_tarname != '' )
00573 {
00574 $this->fileUnlink( $this->_temp_tarname );
00575 $this->_temp_tarname = '';
00576 }
00577
00578 return true;
00579 }
00580
00581
00582
00583 function _cleanFile()
00584 {
00585 $this->_close();
00586
00587
00588 if ($this->_temp_tarname != '')
00589 {
00590
00591 $this->fileUnlink( $this->_temp_tarname );
00592 $this->_temp_tarname = '';
00593 }
00594 else
00595 {
00596
00597 $this->fileUnlink();
00598 }
00599 $this->_tarname = '';
00600
00601 return true;
00602 }
00603
00604
00605
00606 function _writeBlock($p_binary_data, $p_len=null)
00607 {
00608 if ($this->_file) {
00609 if ($p_len === null) {
00610 if ($this->_compress_type == 'gz')
00611 @gzputs($this->_file, $p_binary_data);
00612 else if ($this->_compress_type == 'bz2')
00613 @bzwrite($this->_file, $p_binary_data);
00614 else if ($this->_compress_type == 'none')
00615 @fputs($this->_file, $p_binary_data);
00616 else
00617 $this->_error('Unknown or missing compression type ('.$this->_compress_type.')');
00618 } else {
00619 if ($this->_compress_type == 'gz')
00620 @gzputs($this->_file, $p_binary_data, $p_len);
00621 else if ($this->_compress_type == 'bz2')
00622 @bzwrite($this->_file, $p_binary_data, $p_len);
00623 else if ($this->_compress_type == 'none')
00624 @fputs($this->_file, $p_binary_data, $p_len);
00625 else
00626 $this->_error('Unknown or missing compression type ('.$this->_compress_type.')');
00627
00628 }
00629 }
00630 return true;
00631 }
00632
00633
00634
00635 function _readBlock($p_len=null)
00636 {
00637 $v_block = null;
00638 if ($this->_file) {
00639 if ($p_len === null)
00640 $p_len = 512;
00641
00642 if ($this->_compress_type == 'gz')
00643 $v_block = @gzread($this->_file, 512);
00644 else if ($this->_compress_type == 'bz2')
00645 $v_block = @bzread($this->_file, 512);
00646 else if ($this->_compress_type == 'none')
00647 $v_block = @fread($this->_file, 512);
00648 else
00649 $this->_error('Unknown or missing compression type ('.$this->_compress_type.')');
00650
00651 }
00652 return $v_block;
00653 }
00654
00655
00656
00657 function _jumpBlock($p_len=null)
00658 {
00659 if ($this->_file) {
00660 if ($p_len === null)
00661 $p_len = 1;
00662
00663 if ($this->_compress_type == 'gz')
00664 @gzseek($this->_file, @gztell($this->_file)+($p_len*512));
00665 else if ($this->_compress_type == 'bz2') {
00666
00667 for ($i=0; $i<$p_len; $i++)
00668 $this->_readBlock();
00669 } else if ($this->_compress_type == 'none')
00670 @fseek($this->_file, @ftell($this->_file)+($p_len*512));
00671 else
00672 $this->_error('Unknown or missing compression type ('.$this->_compress_type.')');
00673
00674 }
00675 return true;
00676 }
00677
00678
00679
00680 function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir)
00681 {
00682
00683
00684
00685
00686
00687 if ( !$this->fileIsOpen() )
00688 {
00689 $this->_error( 'File is not open' );
00690 return false;
00691 }
00692
00693 if ($p_filename == '')
00694 {
00695 $this->_error('Invalid file name');
00696 return false;
00697 }
00698
00699
00700 $p_filename = $this->_translateWinPath($p_filename, false);
00701 $v_stored_filename = $p_filename;
00702 if (strcmp($p_filename, $p_remove_dir) == 0)
00703 {
00704 return true;
00705 }
00706 if ($p_remove_dir != '')
00707 {
00708 if (substr($p_remove_dir, -1) != '/')
00709 $p_remove_dir .= '/';
00710
00711 if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
00712 $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
00713 }
00714 $v_stored_filename = $this->_translateWinPath($v_stored_filename);
00715 if ($p_add_dir != '') {
00716 if (substr($p_add_dir, -1) == '/')
00717 $v_stored_filename = $p_add_dir.$v_stored_filename;
00718 else
00719 $v_stored_filename = $p_add_dir.'/'.$v_stored_filename;
00720 }
00721
00722 $isFile = $this->fileIsFile( $p_filename );
00723 if ( !$isFile )
00724 {
00725
00726 if ( $v_stored_filename[ strlen( $v_stored_filename ) - 1 ] != '/' )
00727 $v_stored_filename .= '/';
00728 }
00729
00730 if (strlen($v_stored_filename) > 99)
00731 {
00732 $this->_warning("Stored file name is too long (max. 99) : '$v_stored_filename'");
00733
00734
00735 return true;
00736 }
00737 $v_stored_filename = $this->_pathReduction($v_stored_filename);
00738
00739 if ( $isFile )
00740 {
00741 if (($v_file = @fopen($p_filename, "rb")) == 0)
00742 {
00743 $this->_warning("Unable to open file '$p_filename' in binary read mode");
00744 return true;
00745 }
00746
00747 if (!$this->_writeHeader($p_filename, $v_stored_filename))
00748 return false;
00749
00750 while (($v_buffer = fread($v_file, 512)) != '')
00751 {
00752 $v_binary_data = pack("a512", "$v_buffer");
00753
00754
00755
00756
00757 $this->fileWrite( $v_binary_data );
00758 }
00759
00760 fclose($v_file);
00761
00762 }
00763 else
00764 {
00765
00766 if (!$this->_writeHeader($p_filename, $v_stored_filename))
00767 return false;
00768 }
00769
00770 return true;
00771 }
00772
00773
00774
00775 function _addString($p_filename, $p_string)
00776 {
00777 if (!$this->_file) {
00778 $this->_error('Invalid file descriptor');
00779 return false;
00780 }
00781
00782 if ($p_filename == '') {
00783 $this->_error('Invalid file name');
00784 return false;
00785 }
00786
00787
00788 $p_filename = $this->_translateWinPath($p_filename, false);
00789
00790 if (!$this->_writeHeaderBlock($p_filename, strlen($p_string), 0, 0, "", 0, 0))
00791 return false;
00792
00793 $i=0;
00794 while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') {
00795 $v_binary_data = pack("a512", $v_buffer);
00796 $this->_writeBlock($v_binary_data);
00797 }
00798
00799 return true;
00800 }
00801
00802
00803
00804 function _writeFooter()
00805 {
00806 if ( $this->fileIsOpen() )
00807 {
00808 $endBlocks = ( filesize( $this->_tarname ) / 512 ) + 1;
00809 $blockPadding = 20;
00810 $modulo = $endBlocks % $blockPadding;
00811 if ( $modulo == 0 )
00812 {
00813 $blockCount = $blockPadding;
00814 }
00815 else
00816 {
00817 $blockCount = ( $blockPadding - $modulo ) + 1;
00818 }
00819
00820 for ( $i = 0; $i < $blockCount; ++$i )
00821 {
00822 $v_binary_data = pack("a512", '');
00823 $this->fileWrite( $v_binary_data );
00824 }
00825 }
00826 return true;
00827 }
00828
00829
00830
00831 function _addList($p_list, $p_add_dir, $p_remove_dir)
00832 {
00833 $v_result=true;
00834 $v_header = array();
00835
00836
00837
00838
00839
00840
00841 if ( !$this->fileIsOpen() )
00842 {
00843 $this->_error( 'File is not open' );
00844
00845
00846
00847
00848
00849
00850 return false;
00851 }
00852
00853 if ( sizeof($p_list) == 0 )
00854 return true;
00855
00856 for ( $j = 0; ( $j < count( $p_list ) ) && ( $v_result ); $j++ )
00857 {
00858 $v_filename = $p_list[$j];
00859
00860
00861 if ($v_filename == $this->_tarname)
00862 continue;
00863
00864 if ($v_filename == '')
00865 continue;
00866
00867 if ( !$this->fileExists( $v_filename ) )
00868 {
00869 $this->_warning("File '$v_filename' does not exist");
00870 continue;
00871 }
00872
00873
00874 if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir))
00875 return false;
00876
00877 if ( $this->fileIsDirectory( $v_filename ) )
00878 {
00879 if (!($p_hdir = opendir($v_filename)))
00880 {
00881 $this->_warning("Directory '$v_filename' can not be read");
00882 continue;
00883 }
00884 while (false !== ($p_hitem = readdir($p_hdir))) {
00885 if ( $p_hitem == '.' || $p_hitem == '..' )
00886 continue;
00887
00888 if ($v_filename != ".")
00889 $p_temp_list[0] = $v_filename.'/'.$p_hitem;
00890 else
00891 $p_temp_list[0] = $p_hitem;
00892
00893 $v_result = $this->_addList($p_temp_list, $p_add_dir, $p_remove_dir);
00894 }
00895
00896 unset($p_temp_list);
00897 unset($p_hdir);
00898 unset($p_hitem);
00899 }
00900 }
00901
00902 return $v_result;
00903 }
00904
00905
00906
00907 function _writeHeader($p_filename, $p_stored_filename)
00908 {
00909 if ($p_stored_filename == '')
00910 $p_stored_filename = $p_filename;
00911 $v_reduce_filename = $this->_pathReduction($p_stored_filename);
00912
00913 $v_info = $this->fileStatistics( $p_filename );
00914 if (strlen($v_reduce_filename) > 99) {
00915 if (!$this->_writeLongHeader($v_reduce_filename))
00916 return false;
00917 }
00918
00919 $v_info = stat($p_filename);
00920 $v_uid = sprintf("%6s ", DecOct($v_info[4]));
00921 $v_gid = sprintf("%6s ", DecOct($v_info[5]));
00922 $v_perms = sprintf("%6s ", DecOct(fileperms($p_filename)));
00923
00924 $v_mtime = sprintf("%11s", DecOct(filemtime($p_filename)));
00925
00926 if ( $this->fileIsDirectory( $p_filename ))
00927 {
00928 $v_typeflag = "5";
00929 $v_size = sprintf("%11s ", DecOct(0));
00930 }
00931 else
00932 {
00933 $v_typeflag = '';
00934 clearstatcache();
00935 $v_size = sprintf("%11s ", DecOct(filesize($p_filename)));
00936 }
00937
00938 $v_linkname = '';
00939
00940 $v_magic = '';
00941
00942 $v_version = '';
00943
00944 $v_uname = '';
00945
00946 $v_gname = '';
00947
00948 $v_devmajor = '';
00949
00950 $v_devminor = '';
00951
00952 $v_prefix = '';
00953
00954 $v_binary_data_first = pack("a100a8a8a8a12A12", $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
00955 $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '');
00956
00957
00958 $v_checksum = 0;
00959
00960 for ($i=0; $i<148; $i++)
00961 $v_checksum += ord(substr($v_binary_data_first,$i,1));
00962
00963 for ($i=148; $i<156; $i++)
00964 $v_checksum += ord(' ');
00965
00966 for ($i=156, $j=0; $i<512; $i++, $j++)
00967 $v_checksum += ord(substr($v_binary_data_last,$j,1));
00968
00969
00970
00971
00972
00973
00974 $this->fileWrite( $v_binary_data_first, 148 );
00975
00976
00977 $v_checksum = sprintf("%6s ", DecOct($v_checksum));
00978 $v_binary_data = pack("a8", $v_checksum);
00979
00980
00981
00982
00983 $this->fileWrite( $v_binary_data, 8 );
00984
00985
00986
00987
00988
00989
00990 $this->fileWrite( $v_binary_data_last, 356 );
00991
00992 return true;
00993 }
00994
00995
00996
00997 function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0, $p_type='', $p_uid=0, $p_gid=0)
00998 {
00999 $p_filename = $this->_pathReduction($p_filename);
01000
01001 if (strlen($p_filename) > 99) {
01002 if (!$this->_writeLongHeader($p_filename))
01003 return false;
01004 }
01005
01006 if ($p_type == "5") {
01007 $v_size = sprintf("%11s ", DecOct(0));
01008 } else {
01009 $v_size = sprintf("%11s ", DecOct($p_size));
01010 }
01011
01012 $v_uid = sprintf("%6s ", DecOct($p_uid));
01013 $v_gid = sprintf("%6s ", DecOct($p_gid));
01014 $v_perms = sprintf("%6s ", DecOct($p_perms));
01015
01016 $v_mtime = sprintf("%11s", DecOct($p_mtime));
01017
01018 $v_linkname = '';
01019
01020 $v_magic = '';
01021
01022 $v_version = '';
01023
01024 $v_uname = '';
01025
01026 $v_gname = '';
01027
01028 $v_devmajor = '';
01029
01030 $v_devminor = '';
01031
01032 $v_prefix = '';
01033
01034 $v_binary_data_first = pack("a100a8a8a8a12A12", $p_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
01035 $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $p_type, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '');
01036
01037
01038 $v_checksum = 0;
01039
01040 for ($i=0; $i<148; $i++)
01041 $v_checksum += ord(substr($v_binary_data_first,$i,1));
01042
01043 for ($i=148; $i<156; $i++)
01044 $v_checksum += ord(' ');
01045
01046 for ($i=156, $j=0; $i<512; $i++, $j++)
01047 $v_checksum += ord(substr($v_binary_data_last,$j,1));
01048
01049
01050 $this->_writeBlock($v_binary_data_first, 148);
01051
01052
01053 $v_checksum = sprintf("%6s ", DecOct($v_checksum));
01054 $v_binary_data = pack("a8", $v_checksum);
01055 $this->_writeBlock($v_binary_data, 8);
01056
01057
01058 $this->_writeBlock($v_binary_data_last, 356);
01059
01060 return true;
01061 }
01062
01063
01064
01065 function _writeLongHeader($p_filename)
01066 {
01067 $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
01068
01069 $v_typeflag = 'L';
01070
01071 $v_linkname = '';
01072
01073 $v_magic = '';
01074
01075 $v_version = '';
01076
01077 $v_uname = '';
01078
01079 $v_gname = '';
01080
01081 $v_devmajor = '';
01082
01083 $v_devminor = '';
01084
01085 $v_prefix = '';
01086
01087 $v_binary_data_first = pack("a100a8a8a8a12A12", '././@LongLink', 0, 0, 0, $v_size, 0);
01088 $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '');
01089
01090
01091 $v_checksum = 0;
01092
01093 for ($i=0; $i<148; $i++)
01094 $v_checksum += ord(substr($v_binary_data_first,$i,1));
01095
01096 for ($i=148; $i<156; $i++)
01097 $v_checksum += ord(' ');
01098
01099 for ($i=156, $j=0; $i<512; $i++, $j++)
01100 $v_checksum += ord(substr($v_binary_data_last,$j,1));
01101
01102
01103 $this->_writeBlock($v_binary_data_first, 148);
01104
01105
01106 $v_checksum = sprintf("%6s ", DecOct($v_checksum));
01107 $v_binary_data = pack("a8", $v_checksum);
01108 $this->_writeBlock($v_binary_data, 8);
01109
01110
01111 $this->_writeBlock($v_binary_data_last, 356);
01112
01113
01114 $i=0;
01115 while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') {
01116 $v_binary_data = pack("a512", "$v_buffer");
01117 $this->_writeBlock($v_binary_data);
01118 }
01119
01120 return true;
01121 }
01122
01123
01124
01125 function _readHeader($v_binary_data, &$v_header)
01126 {
01127 if (strlen($v_binary_data)==0) {
01128 $v_header['filename'] = '';
01129 return true;
01130 }
01131
01132 if (strlen($v_binary_data) != 512) {
01133 $v_header['filename'] = '';
01134 $this->_error('Invalid block size : '.strlen($v_binary_data));
01135 return false;
01136 }
01137
01138
01139 $v_checksum = 0;
01140
01141 for ($i=0; $i<148; $i++)
01142 $v_checksum+=ord(substr($v_binary_data,$i,1));
01143
01144 for ($i=148; $i<156; $i++)
01145 $v_checksum += ord(' ');
01146
01147 for ($i=156; $i<512; $i++)
01148 $v_checksum+=ord(substr($v_binary_data,$i,1));
01149
01150 $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $v_binary_data);
01151
01152
01153 $v_header['checksum'] = OctDec(trim($v_data['checksum']));
01154 if ($v_header['checksum'] != $v_checksum) {
01155 $v_header['filename'] = '';
01156
01157
01158 if (($v_checksum == 256) && ($v_header['checksum'] == 0))
01159 return true;
01160
01161 $this->_error('Invalid checksum for file "'.$v_data['filename'].'" : '.$v_checksum.' calculated, '.$v_header['checksum'].' expected');
01162 return false;
01163 }
01164
01165
01166 $v_header['filename'] = trim($v_data['filename']);
01167 $v_header['mode'] = OctDec(trim($v_data['mode']));
01168 $v_header['uid'] = OctDec(trim($v_data['uid']));
01169 $v_header['gid'] = OctDec(trim($v_data['gid']));
01170 $v_header['size'] = OctDec(trim($v_data['size']));
01171 $v_header['mtime'] = OctDec(trim($v_data['mtime']));
01172 if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
01173 $v_header['size'] = 0;
01174 }
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185 return true;
01186 }
01187
01188
01189
01190 function _readLongHeader(&$v_header)
01191 {
01192 $v_filename = '';
01193 $n = floor($v_header['size']/512);
01194 for ($i=0; $i<$n; $i++) {
01195 $v_content = $this->_readBlock();
01196 $v_filename .= $v_content;
01197 }
01198 if (($v_header['size'] % 512) != 0) {
01199 $v_content = $this->_readBlock();
01200 $v_filename .= $v_content;
01201 }
01202
01203
01204 $v_binary_data = $this->_readBlock();
01205
01206 if (!$this->_readHeader($v_binary_data, $v_header))
01207 return false;
01208
01209 $v_header['filename'] = $v_filename;
01210
01211 return true;
01212 }
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 function _extractInString($p_filename)
01224 {
01225 $v_result_str = "";
01226
01227 While (strlen($v_binary_data = $this->_readBlock()) != 0)
01228 {
01229 if (!$this->_readHeader($v_binary_data, $v_header))
01230 return NULL;
01231
01232 if ($v_header['filename'] == '')
01233 continue;
01234
01235
01236 if ($v_header['typeflag'] == 'L') {
01237 if (!$this->_readLongHeader($v_header))
01238 return NULL;
01239 }
01240
01241 if ($v_header['filename'] == $p_filename) {
01242 if ($v_header['typeflag'] == "5") {
01243 $this->_error('Unable to extract in string a directory entry {'.$v_header['filename'].'}');
01244 return NULL;
01245 } else {
01246 $n = floor($v_header['size']/512);
01247 for ($i=0; $i<$n; $i++) {
01248 $v_result_str .= $this->_readBlock();
01249 }
01250 if (($v_header['size'] % 512) != 0) {
01251 $v_content = $this->_readBlock();
01252 $v_result_str .= substr($v_content, 0, ($v_header['size'] % 512));
01253 }
01254 return $v_result_str;
01255 }
01256 } else {
01257 $this->_jumpBlock(ceil(($v_header['size']/512)));
01258 }
01259 }
01260
01261 return NULL;
01262 }
01263
01264
01265
01266 function _extractList($p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path)
01267 {
01268 $v_result=true;
01269 $v_nb = 0;
01270 $v_extract_all = true;
01271 $v_listing = false;
01272
01273
01274 if ( eZSys::osType() == 'win32' && strpos($p_path, '\\'))
01275 {
01276 str_replace('\\', '/', $p_path);
01277 }
01278
01279 if ($p_path == '' || (substr($p_path, 0, 1) != '/' && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
01280 $p_path = "./".$p_path;
01281 }
01282 $p_remove_path = $this->_translateWinPath($p_remove_path);
01283
01284
01285 if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/'))
01286 $p_remove_path .= '/';
01287 $p_remove_path_size = strlen($p_remove_path);
01288
01289 switch ($p_mode) {
01290 case "complete" :
01291 $v_extract_all = TRUE;
01292 $v_listing = FALSE;
01293 break;
01294 case "partial" :
01295 $v_extract_all = FALSE;
01296 $v_listing = FALSE;
01297 break;
01298 case "list" :
01299 $v_extract_all = FALSE;
01300 $v_listing = TRUE;
01301 break;
01302 default :
01303 $this->_error('Invalid extract mode ('.$p_mode.')');
01304 return false;
01305 }
01306
01307 clearstatcache();
01308
01309
01310 while (!($v_end_of_file = ($this->fileEOF())))
01311 {
01312 $v_extract_file = FALSE;
01313 $v_extraction_stopped = 0;
01314
01315
01316
01317
01318
01319 $v_binary_data = $this->fileRead( 512 );
01320
01321 if (!$this->_readHeader($v_binary_data, $v_header))
01322 return false;
01323
01324 if ($v_header['filename'] == '')
01325 continue;
01326
01327
01328 if ($v_header['typeflag'] == 'L') {
01329 if (!$this->_readLongHeader($v_header))
01330 return false;
01331 }
01332
01333 if ((!$v_extract_all) && (is_array($p_file_list))) {
01334
01335 $v_extract_file = false;
01336
01337 for ($i=0; $i<sizeof($p_file_list); $i++) {
01338
01339 if (substr($p_file_list[$i], -1) == '/') {
01340
01341 if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i])) {
01342 $v_extract_file = TRUE;
01343 break;
01344 }
01345 }
01346
01347
01348 elseif ($p_file_list[$i] == $v_header['filename']) {
01349 $v_extract_file = TRUE;
01350 break;
01351 }
01352 }
01353 } else {
01354 $v_extract_file = TRUE;
01355 }
01356
01357
01358 if (($v_extract_file) && (!$v_listing))
01359 {
01360 if (($p_remove_path != '')
01361 && (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path))
01362 $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
01363 if (($p_path != './') && ($p_path != '/')) {
01364 while (substr($p_path, -1) == '/')
01365 $p_path = substr($p_path, 0, strlen($p_path)-1);
01366
01367 if (substr($v_header['filename'], 0, 1) == '/')
01368 $v_header['filename'] = $p_path.$v_header['filename'];
01369 else
01370 $v_header['filename'] = $p_path.'/'.$v_header['filename'];
01371 }
01372 if (file_exists($v_header['filename'])) {
01373 if ((@is_dir($v_header['filename'])) && ($v_header['typeflag'] == '')) {
01374 $this->_error('File '.$v_header['filename'].' already exists as a directory');
01375 return false;
01376 }
01377 if ((is_file($v_header['filename'])) && ($v_header['typeflag'] == "5")) {
01378 $this->_error('Directory '.$v_header['filename'].' already exists as a file');
01379 return false;
01380 }
01381 if (!is_writeable($v_header['filename'])) {
01382 $this->_error('File '.$v_header['filename'].' already exists and is write protected');
01383 return false;
01384 }
01385 if (filemtime($v_header['filename']) > $v_header['mtime']) {
01386
01387 }
01388 }
01389
01390
01391 elseif (($v_result = $this->_dirCheck(($v_header['typeflag'] == "5"?$v_header['filename']:dirname($v_header['filename'])))) != 1) {
01392 $this->_error('Unable to create path for '.$v_header['filename']);
01393 return false;
01394 }
01395
01396 if ($v_extract_file) {
01397 if ($v_header['typeflag'] == "5") {
01398 if (!@file_exists($v_header['filename'])) {
01399 if (!@mkdir($v_header['filename'], 0777)) {
01400 $this->_error('Unable to create directory {'.$v_header['filename'].'}');
01401 return false;
01402 }
01403 }
01404 } else {
01405 if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
01406 $this->_error('Error while opening {'.$v_header['filename'].'} in write binary mode');
01407 return false;
01408 } else {
01409 $n = floor($v_header['size']/512);
01410 for ($i=0; $i<$n; $i++) {
01411
01412
01413
01414
01415 $v_content = $this->fileRead( 512 );
01416 fwrite($v_dest_file, $v_content, 512);
01417 }
01418 if (($v_header['size'] % 512) != 0) {
01419
01420
01421
01422
01423 $v_content = $this->fileRead( 512 );
01424 fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
01425 }
01426
01427 @fclose($v_dest_file);
01428
01429
01430 @touch($v_header['filename'], $v_header['mtime']);
01431 if ($v_header['mode'] & 0111) {
01432
01433 $mode = fileperms($v_header['filename']) | (~umask() & 0111);
01434 @chmod($v_header['filename'], $mode);
01435 }
01436 }
01437
01438
01439 clearstatcache();
01440 if (filesize($v_header['filename']) != $v_header['size']) {
01441 $this->_error('Extracted file '.$v_header['filename'].' does not have the correct file size \''.filesize($v_filename).'\' ('.$v_header['size'].' expected). Archive may be corrupted.');
01442 return false;
01443 }
01444 }
01445 } else {
01446 // ----- Jump to next file
01447 // if ($this->_compress)
01448 // @gzseek($this->_file, @gztell($this->_file)+(ceil(($v_header['size']/512))*512));
01449 // else
01450 // @fseek($this->_file, @ftell($this->_file)+(ceil(($v_header['size']/512))*512));
01451 $seekPosition = $this->fileTell() + ( ceil( ( $v_header['size'] / 512 ) ) * 512 );
01452 $this->fileSeek( $seekPosition );
01453 }
01454 } else {
01455 // ----- Jump to next file
01456 // if ($this->_compress)
01457 // @gzseek($this->_file, @gztell($this->_file)+(ceil(($v_header['size']/512))*512));
01458 // else
01459 // @fseek($this->_file, @ftell($this->_file)+(ceil(($v_header['size']/512))*512));
01460 $seekPosition = $this->fileTell() + ( ceil ( ( $v_header['size'] / 512 ) ) * 512 );
01461 $this->fileSeek( $seekPosition );
01462 }
01463
01464 // if ($this->_compress)
01465 // $v_end_of_file = @gzeof($this->_file);
01466 // else
01467 // $v_end_of_file = @feof($this->_file);
01468 $v_end_of_file = $this->fileEOF();
01469
01470 if ($v_listing || $v_extract_file || $v_extraction_stopped) {
01471 // ----- Log extracted files
01472 if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename'])
01473 $v_file_dir = '';
01474 if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == ''))
01475 $v_file_dir = '/';
01476
01477 $p_list_detail[$v_nb++] = $v_header;
01478 }
01479 }
01480
01481 return true;
01482 }
01483 // }}}
01484
01485 // {{{ _openAppend()
01486 function _openAppend()
01487 {
01488 if (filesize($this->_tarname) == 0)
01489 return $this->_openWrite();
01490
01491 if ($this->_compress)
01492 {
01493 // Rename to temporary file.
01494 $this->fileClose();
01495 $temporaryHandler =& $this->detachHandler();
01496 $temporaryHandler->rename( $this->_tarname . '.tmp' );
01497 if ( !$this->_openWrite() )
01498 {
01499 $temporaryHandler->rename( $this->_tarname );
01500 // @rename($this->_tarname.".tmp", $this->_tarname);
01501 return false;
01502 }
01503 $temporaryHandler->fileOpen( false, 'rb' );
01504
01505 // $v_buffer = @gzread($v_temp_tar, 512);
01506 $v_buffer = $temporaryHandler->read( 512 );
01507
01508 // ----- Read the following blocks but not the last one
01509 // if (!@gzeof($v_temp_tar)) {
01510 // do{
01511 // $v_binary_data = pack("a512", "$v_buffer");
01512 // @gzputs($this->_file, $v_binary_data);
01513 // $v_buffer = @gzread($v_temp_tar, 512);
01514
01515 //<<<<<<< .working
01516 // } while (!@gzeof($v_temp_tar));
01517 // }
01518 if ( !$temporaryHandler->eof() )
01519 {
01520 do
01521 {
01522 $v_binary_data = pack( 'a512', "$v_buffer" );
01523 $this->fileWrite( $v_binary_data );
01524 $v_buffer = $temporaryHandler->read( 512 );
01525 } while( !$temporaryHandler->eof() );
01526 }
01527 // elseif ($this->_compress_type == 'bz2') {
01528 // $v_buffered_lines = array();
01529 // $v_buffered_lines[] = @bzread($v_temp_tar, 512);
01530 //
01531 // // ----- Read the following blocks but not the last one
01532 // while (strlen($v_buffered_lines[] = @bzread($v_temp_tar, 512)) > 0) {
01533 // $v_binary_data = pack("a512", array_shift($v_buffered_lines));
01534 // $this->_writeBlock($v_binary_data);
01535 // }
01536 // @bzclose($v_temp_tar);
01537 // }
01538
01539 $this->_close();
01540
01541 // if (!@unlink($this->_tarname.".tmp"))
01542 if ( !$temporaryHandler->unlink() )
01543 {
01544 $this->_error('Error while deleting temporary file \''.$this->_tarname.'.tmp\'');
01545 }
01546 }
01547 else
01548 {
01549
01550 if (!$this->_openReadWrite())
01551 return false;
01552
01553 clearstatcache();
01554 $v_size = filesize($this->_tarname);
01555
01556 $this->fileSeek( $v_size - 512 );
01557
01558 }
01559
01560 return true;
01561 }
01562
01563
01564
01565 function _append($p_filelist, $p_add_dir='', $p_remove_dir='')
01566 {
01567 if (!$this->_openAppend())
01568 return false;
01569
01570 if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir))
01571 $this->_writeFooter();
01572
01573 $this->_close();
01574
01575 return true;
01576 }
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589 function _dirCheck($p_dir)
01590 {
01591 if ((@is_dir($p_dir)) || ($p_dir == ''))
01592 return true;
01593
01594 $p_parent_dir = dirname($p_dir);
01595
01596 if (($p_parent_dir != $p_dir) &&
01597 ($p_parent_dir != '') &&
01598 (!$this->_dirCheck($p_parent_dir)))
01599 return false;
01600
01601 if (!@mkdir($p_dir, 0777)) {
01602 $this->_error("Unable to create directory '$p_dir'");
01603 return false;
01604 }
01605
01606 return true;
01607 }
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 function _pathReduction($p_dir)
01625 {
01626 $v_result = '';
01627
01628
01629 if ($p_dir != '') {
01630
01631 $v_list = explode('/', $p_dir);
01632
01633
01634 for ($i=sizeof($v_list)-1; $i>=0; $i--) {
01635
01636 if ($v_list[$i] == ".") {
01637
01638
01639 }
01640 else if ($v_list[$i] == "..") {
01641
01642 $i--;
01643 }
01644 else if (($v_list[$i] == '') && ($i!=(sizeof($v_list)-1)) && ($i!=0)) {
01645
01646
01647 } else {
01648 $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'.$v_result:'');
01649 }
01650 }
01651 }
01652 $v_result = strtr($v_result, '\\', '/');
01653 return $v_result;
01654 }
01655
01656
01657
01658
01659 function _translateWinPath($p_path, $p_remove_disk_letter=true)
01660 {
01661
01662 if ( eZSys::osType() == 'win32' )
01663 {
01664
01665 if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
01666 $p_path = substr($p_path, $v_position+1);
01667 }
01668
01669 if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
01670 $p_path = strtr($p_path, '\\', '/');
01671 }
01672 }
01673 return $p_path;
01674 }
01675
01676
01677 }
01678 ?>