Project

General

Profile

Revision 230

View differences:

branches/extplorer2/libraries/Tar.php
30 30
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 31
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 32
 *
33
 *
34
 * @category    File_Formats
35
 * @package     Archive_Tar
36
 * @author      Vincent Blavet <vincent@phpconcept.net>
37
 * @copyright   1997-2008 The Authors
38
 * @license     http://www.opensource.org/licenses/bsd-license.php New BSD License
39
 * @version     CVS: $ Id: Tar.php,v 1.43 2008/10/30 17:58:42 dufuz Exp $
40
 * @link        http://pear.php.net/package/Archive_Tar
33
 * @category  File_Formats
34
 * @package   Archive_Tar
35
 * @author    Vincent Blavet <vincent@phpconcept.net>
36
 * @copyright 1997-2010 The Authors
37
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
38
 * @version   CVS: $Id$
39
 * @link      http://pear.php.net/package/Archive_Tar
41 40
 */
41

  
42 42
if( !class_exists('PEAR')) {
43 43
	require_once 'PEAR.php';
44 44
}
45 45

  
46
define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
47
define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
46 48

  
47
define ('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
48
define ('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
49

  
50 49
/**
51 50
* Creates a (compressed) Tar archive
52 51
*
53
* @author   Vincent Blavet <vincent@phpconcept.net>
54
* @version  $Revision$
55
* @license  http://www.opensource.org/licenses/bsd-license.php New BSD License
56
* @package  Archive_Tar
52
* @package Archive_Tar
53
* @author  Vincent Blavet <vincent@phpconcept.net>
54
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
55
* @version $Revision$
57 56
*/
58 57
class Archive_Tar extends PEAR
59 58
{
......
87 86
    */
88 87
    var $_temp_tarname='';
89 88

  
89
    /**
90
    * @var string regular expression for ignoring files or directories
91
    */
92
    var $_ignore_regexp='';
93

  
94
    /**
95
     * @var object PEAR_Error object
96
     */
97
    var $error_object=null; 
98

  
90 99
    // {{{ constructor
91 100
    /**
92 101
    * Archive_Tar Class constructor. This flavour of the constructor only
......
95 104
    * If the compress argument is set the tar will be read or created as a
96 105
    * gzip or bz2 compressed TAR file.
97 106
    *
98
    * @param    string  $p_tarname  The name of the tar archive to create
99
    * @param    string  $p_compress can be null, 'gz' or 'bz2'. This
100
    *                   parameter indicates if gzip or bz2 compression
101
    *                   is required.  For compatibility reason the
102
    *                   boolean value 'true' means 'gz'.
107
    * @param string $p_tarname  The name of the tar archive to create
108
    * @param string $p_compress can be null, 'gz' or 'bz2'. This
109
    *               parameter indicates if gzip or bz2 compression
110
    *               is required.  For compatibility reason the
111
    *               boolean value 'true' means 'gz'.
112
    *
103 113
    * @access public
104 114
    */
105 115
    function Archive_Tar($p_tarname, $p_compress = null)
......
116 126
                    if ($data == "\37\213") {
117 127
                        $this->_compress = true;
118 128
                        $this->_compress_type = 'gz';
119
                    // No sure it's enought for a magic code ....
129
                        // No sure it's enought for a magic code ....
120 130
                    } elseif ($data == "BZ") {
121 131
                        $this->_compress = true;
122 132
                        $this->_compress_type = 'bz2';
......
142 152
                $this->_compress = true;
143 153
                $this->_compress_type = 'bz2';
144 154
            } else {
145
                die("Unsupported compression type '$p_compress'\n".
155
                $this->_error("Unsupported compression type '$p_compress'\n".
146 156
                    "Supported types are 'gz' and 'bz2'.\n");
147 157
                return false;
148 158
            }
......
158 168
                PEAR::loadExtension($extname);
159 169
            }
160 170
            if (!extension_loaded($extname)) {
161
                die("The extension '$extname' couldn't be found.\n".
171
                $this->_error("The extension '$extname' couldn't be found.\n".
162 172
                    "Please make sure your version of PHP was built ".
163 173
                    "with '$extname' support.\n");
164 174
                return false;
......
193 203
    * sub-directories are also added.
194 204
    * See also createModify() method for more details.
195 205
    *
196
    * @param array  $p_filelist An array of filenames and directory names, or a
197
	*                           single string with names separated by a single
198
	*                           blank space.
199
    * @return                   true on success, false on error.
200
    * @see createModify()
206
    * @param array $p_filelist An array of filenames and directory names, or a
207
    *              single string with names separated by a single
208
    *              blank space.
209
    *
210
    * @return true on success, false on error.
211
    * @see    createModify()
201 212
    * @access public
202 213
    */
203 214
    function create($p_filelist)
......
215 226
    * even if a file with the same name is already archived.
216 227
    * See also createModify() method for more details.
217 228
    *
218
    * @param array  $p_filelist An array of filenames and directory names, or a
219
	*                           single string with names separated by a single
220
	*                           blank space.
221
    * @return                   true on success, false on error.
222
    * @see createModify()
229
    * @param array $p_filelist An array of filenames and directory names, or a
230
    *              single string with names separated by a single
231
    *              blank space.
232
    *
233
    * @return true on success, false on error.
234
    * @see    createModify()
223 235
    * @access public
224 236
    */
225 237
    function add($p_filelist)
......
229 241
    // }}}
230 242

  
231 243
    // {{{ extract()
232
    function extract($p_path='')
244
    function extract($p_path='', $p_preserve=false)
233 245
    {
234
        return $this->extractModify($p_path, '');
246
        return $this->extractModify($p_path, '', $p_preserve);
235 247
    }
236 248
    // }}}
237 249

  
......
275 287
    * for extraction in a different path than the origin files are.
276 288
    * See also addModify() method for file adding properties.
277 289
    *
278
    * @param array  $p_filelist     An array of filenames and directory names,
279
	*                               or a single string with names separated by
280
	*                               a single blank space.
281
    * @param string $p_add_dir      A string which contains a path to be added
282
	*                               to the memorized path of each element in
283
	*                               the list.
284
    * @param string $p_remove_dir   A string which contains a path to be
285
	*                               removed from the memorized path of each
286
	*                               element in the list, when relevant.
287
    * @return boolean               true on success, false on error.
290
    * @param array  $p_filelist   An array of filenames and directory names,
291
    *                             or a single string with names separated by
292
    *                             a single blank space.
293
    * @param string $p_add_dir    A string which contains a path to be added
294
    *                             to the memorized path of each element in
295
    *                             the list.
296
    * @param string $p_remove_dir A string which contains a path to be
297
    *                             removed from the memorized path of each
298
    *                             element in the list, when relevant.
299
    *
300
    * @return boolean true on success, false on error.
288 301
    * @access public
289 302
    * @see addModify()
290 303
    */
......
347 360
    * If a file/dir is not readable the file/dir is ignored. However an
348 361
    * error text is send to PEAR error.
349 362
    *
350
    * @param array      $p_filelist     An array of filenames and directory
351
	*                                   names, or a single string with names
352
	*                                   separated by a single blank space.
353
    * @param string     $p_add_dir      A string which contains a path to be
354
	*                                   added to the memorized path of each
355
	*                                   element in the list.
356
    * @param string     $p_remove_dir   A string which contains a path to be
357
	*                                   removed from the memorized path of
358
	*                                   each element in the list, when
359
    *                                   relevant.
360
    * @return                           true on success, false on error.
363
    * @param array  $p_filelist   An array of filenames and directory
364
    *                             names, or a single string with names
365
    *                             separated by a single blank space.
366
    * @param string $p_add_dir    A string which contains a path to be
367
    *                             added to the memorized path of each
368
    *                             element in the list.
369
    * @param string $p_remove_dir A string which contains a path to be
370
    *                             removed from the memorized path of
371
    *                             each element in the list, when
372
    *                             relevant.
373
    *
374
    * @return true on success, false on error.
361 375
    * @access public
362 376
    */
363 377
    function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
......
366 380

  
367 381
        if (!$this->_isArchive())
368 382
            $v_result = $this->createModify($p_filelist, $p_add_dir,
369
			                                $p_remove_dir);
383
                                            $p_remove_dir);
370 384
        else {
371 385
            if (is_array($p_filelist))
372 386
                $v_list = $p_filelist;
......
390 404
    * end of the existing archive. If the archive does not yet exists it
391 405
    * is created.
392 406
    *
393
    * @param string     $p_filename     A string which contains the full
394
	*                                   filename path that will be associated
395
	*                                   with the string.
396
    * @param string     $p_string       The content of the file added in
397
	*                                   the archive.
398
    * @return                           true on success, false on error.
407
    * @param string $p_filename A string which contains the full
408
    *                           filename path that will be associated
409
    *                           with the string.
410
    * @param string $p_string   The content of the file added in
411
    *                           the archive.
412
    * @param int    $p_datetime A custom date/time (unix timestamp)
413
    *                           for the file (optional).
414
    *
415
    * @return true on success, false on error.
399 416
    * @access public
400 417
    */
401
    function addString($p_filename, $p_string)
418
    function addString($p_filename, $p_string, $p_datetime = false)
402 419
    {
403 420
        $v_result = true;
404 421

  
......
413 430
            return false;
414 431

  
415 432
        // Need to check the get back to the temporary file ? ....
416
        $v_result = $this->_addString($p_filename, $p_string);
433
        $v_result = $this->_addString($p_filename, $p_string, $p_datetime);
417 434

  
418 435
        $this->_writeFooter();
419 436

  
......
448 465
    * is returned. However the result can be a partial extraction that may
449 466
    * need to be manually cleaned.
450 467
    *
451
    * @param string $p_path         The path of the directory where the
452
	*                               files/dir need to by extracted.
453
    * @param string $p_remove_path  Part of the memorized path that can be
454
	*                               removed if present at the beginning of
455
	*                               the file/dir path.
456
    * @return boolean               true on success, false on error.
468
    * @param string  $p_path        The path of the directory where the
469
    *                               files/dir need to by extracted.
470
    * @param string  $p_remove_path Part of the memorized path that can be
471
    *                               removed if present at the beginning of
472
    *                               the file/dir path.
473
    * @param boolean $p_preserve    Preserve user/group ownership of files
474
    *
475
    * @return boolean true on success, false on error.
457 476
    * @access public
458
    * @see extractList()
477
    * @see    extractList()
459 478
    */
460
    function extractModify($p_path, $p_remove_path)
479
    function extractModify($p_path, $p_remove_path, $p_preserve=false)
461 480
    {
462 481
        $v_result = true;
463 482
        $v_list_detail = array();
464 483

  
465 484
        if ($v_result = $this->_openRead()) {
466 485
            $v_result = $this->_extractList($p_path, $v_list_detail,
467
			                                "complete", 0, $p_remove_path);
486
                "complete", 0, $p_remove_path, $p_preserve);
468 487
            $this->_close();
469 488
        }
470 489

  
......
476 495
    /**
477 496
    * This method extract from the archive one file identified by $p_filename.
478 497
    * The return value is a string with the file content, or NULL on error.
479
    * @param string $p_filename     The path of the file to extract in a string.
480
    * @return                       a string with the file content or NULL.
498
    *
499
    * @param string $p_filename The path of the file to extract in a string.
500
    *
501
    * @return a string with the file content or NULL.
481 502
    * @access public
482 503
    */
483 504
    function extractInString($p_filename)
......
486 507
            $v_result = $this->_extractInString($p_filename);
487 508
            $this->_close();
488 509
        } else {
489
            $v_result = NULL;
510
            $v_result = null;
490 511
        }
491 512

  
492 513
        return $v_result;
......
500 521
    * in the directory indicated by the optional $p_path parameter.
501 522
    * If indicated the $p_remove_path can be used in the same way as it is
502 523
    * used in extractModify() method.
503
    * @param array  $p_filelist     An array of filenames and directory names,
504
	*                               or a single string with names separated
505
	*                               by a single blank space.
506
    * @param string $p_path         The path of the directory where the
507
	*                               files/dir need to by extracted.
508
    * @param string $p_remove_path  Part of the memorized path that can be
509
	*                               removed if present at the beginning of
510
	*                               the file/dir path.
511
    * @return                       true on success, false on error.
524
    *
525
    * @param array   $p_filelist    An array of filenames and directory names,
526
    *                               or a single string with names separated
527
    *                               by a single blank space.
528
    * @param string  $p_path        The path of the directory where the
529
    *                               files/dir need to by extracted.
530
    * @param string  $p_remove_path Part of the memorized path that can be
531
    *                               removed if present at the beginning of
532
    *                               the file/dir path.
533
    * @param boolean $p_preserve    Preserve user/group ownership of files
534
    *
535
    * @return true on success, false on error.
512 536
    * @access public
513
    * @see extractModify()
537
    * @see    extractModify()
514 538
    */
515
    function extractList($p_filelist, $p_path='', $p_remove_path='')
539
    function extractList($p_filelist, $p_path='', $p_remove_path='', $p_preserve=false)
516 540
    {
517 541
        $v_result = true;
518 542
        $v_list_detail = array();
......
528 552

  
529 553
        if ($v_result = $this->_openRead()) {
530 554
            $v_result = $this->_extractList($p_path, $v_list_detail, "partial",
531
			                                $v_list, $p_remove_path);
555
                $v_list, $p_remove_path, $p_preserve);
532 556
            $this->_close();
533 557
        }
534 558

  
......
541 565
    * This method set specific attributes of the archive. It uses a variable
542 566
    * list of parameters, in the format attribute code + attribute values :
543 567
    * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
544
    * @param mixed $argv            variable list of attributes and values
545
    * @return                       true on success, false on error.
568
    *
569
    * @param mixed $argv variable list of attributes and values
570
    *
571
    * @return true on success, false on error.
546 572
    * @access public
547 573
    */
548 574
    function setAttribute()
......
590 616
    }
591 617
    // }}}
592 618

  
619
    // {{{ setIgnoreRegexp()
620
    /**
621
    * This method sets the regular expression for ignoring files and directories
622
    * at import, for example:
623
    * $arch->setIgnoreRegexp("#CVS|\.svn#");
624
    *
625
    * @param string $regexp regular expression defining which files or directories to ignore
626
    *
627
    * @access public
628
    */
629
    function setIgnoreRegexp($regexp)
630
    {
631
    	$this->_ignore_regexp = $regexp;
632
    }
633
    // }}}
634

  
635
    // {{{ setIgnoreList()
636
    /**
637
    * This method sets the regular expression for ignoring all files and directories
638
    * matching the filenames in the array list at import, for example:
639
    * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
640
    *
641
    * @param array $list a list of file or directory names to ignore
642
    *
643
    * @access public
644
    */
645
    function setIgnoreList($list)
646
    {
647
    	$regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
648
    	$regexp = '#/'.join('$|/', $list).'#';
649
    	$this->setIgnoreRegexp($regexp);
650
    }
651
    // }}}
652

  
593 653
    // {{{ _error()
594 654
    function _error($p_message)
595 655
    {
596
        // ----- To be completed
597
        $this->raiseError($p_message);
656
        $this->error_object = &$this->raiseError($p_message); 
598 657
    }
599 658
    // }}}
600 659

  
601 660
    // {{{ _warning()
602 661
    function _warning($p_message)
603 662
    {
604
        // ----- To be completed
605
        $this->raiseError($p_message);
663
        $this->error_object = &$this->raiseError($p_message); 
606 664
    }
607 665
    // }}}
608 666

  
609 667
    // {{{ _isArchive()
610
    function _isArchive($p_filename=NULL)
668
    function _isArchive($p_filename=null)
611 669
    {
612
        if ($p_filename == NULL) {
670
        if ($p_filename == null) {
613 671
            $p_filename = $this->_tarname;
614 672
        }
615 673
        clearstatcache();
......
620 678
    // {{{ _openWrite()
621 679
    function _openWrite()
622 680
    {
623
        if ($this->_compress_type == 'gz')
681
        if ($this->_compress_type == 'gz' && function_exists('gzopen'))
624 682
            $this->_file = @gzopen($this->_tarname, "wb9");
625
        else if ($this->_compress_type == 'bz2')
683
        else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
626 684
            $this->_file = @bzopen($this->_tarname, "w");
627 685
        else if ($this->_compress_type == 'none')
628 686
            $this->_file = @fopen($this->_tarname, "wb");
629
        else
687
        else {
630 688
            $this->_error('Unknown or missing compression type ('
631 689
			              .$this->_compress_type.')');
690
            return false;
691
        }
632 692

  
633 693
        if ($this->_file == 0) {
634 694
            $this->_error('Unable to open in write mode \''
......
673 733
          // ----- File to open if the normal Tar file
674 734
          $v_filename = $this->_tarname;
675 735

  
676
        if ($this->_compress_type == 'gz')
736
        if ($this->_compress_type == 'gz' && function_exists('gzopen'))
677 737
            $this->_file = @gzopen($v_filename, "rb");
678
        else if ($this->_compress_type == 'bz2')
738
        else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
679 739
            $this->_file = @bzopen($v_filename, "r");
680 740
        else if ($this->_compress_type == 'none')
681 741
            $this->_file = @fopen($v_filename, "rb");
682
        else
742
        else {
683 743
            $this->_error('Unknown or missing compression type ('
684 744
			              .$this->_compress_type.')');
745
            return false;
746
        }
685 747

  
686 748
        if ($this->_file == 0) {
687 749
            $this->_error('Unable to open in read mode \''.$v_filename.'\'');
......
703 765
            return false;
704 766
        } else if ($this->_compress_type == 'none')
705 767
            $this->_file = @fopen($this->_tarname, "r+b");
706
        else
768
        else {
707 769
            $this->_error('Unknown or missing compression type ('
708 770
			              .$this->_compress_type.')');
771
            return false;
772
        }
709 773

  
710 774
        if ($this->_file == 0) {
711 775
            $this->_error('Unable to open in read/write mode \''
......
831 895
              for ($i=0; $i<$p_len; $i++)
832 896
                  $this->_readBlock();
833 897
          } else if ($this->_compress_type == 'none')
834
              @fseek($this->_file, ftell($this->_file)+($p_len*512));
898
              @fseek($this->_file, $p_len*512, SEEK_CUR);
835 899
          else
836 900
              $this->_error('Unknown or missing compression type ('
837 901
			                .$this->_compress_type.')');
......
883 947
        if ($v_filename == '')
884 948
            continue;
885 949

  
886
        if (!file_exists($v_filename)) {
950
       	// ----- ignore files and directories matching the ignore regular expression
951
       	if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/'.$v_filename)) {
952
            $this->_warning("File '$v_filename' ignored");
953
       	    continue;
954
       	}
955

  
956
        if (!file_exists($v_filename) && !is_link($v_filename)) {
887 957
            $this->_warning("File '$v_filename' does not exist");
888 958
            continue;
889 959
        }
......
984 1054
    // }}}
985 1055

  
986 1056
    // {{{ _addString()
987
    function _addString($p_filename, $p_string)
1057
    function _addString($p_filename, $p_string, $p_datetime = false)
988 1058
    {
989 1059
      if (!$this->_file) {
990 1060
          $this->_error('Invalid file descriptor');
......
998 1068

  
999 1069
      // ----- Calculate the stored filename
1000 1070
      $p_filename = $this->_translateWinPath($p_filename, false);;
1071
      
1072
      // ----- If datetime is not specified, set current time
1073
      if ($p_datetime === false) {
1074
          $p_datetime = time();
1075
      }
1001 1076

  
1002 1077
      if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
1003
	                                  time(), 384, "", 0, 0))
1078
                                    $p_datetime, 384, "", 0, 0))
1004 1079
          return false;
1005 1080

  
1006 1081
      $i=0;
......
1026 1101
        }
1027 1102

  
1028 1103
        $v_info = lstat($p_filename);
1029
        $v_uid = sprintf("%6s ", DecOct($v_info[4]));
1030
        $v_gid = sprintf("%6s ", DecOct($v_info[5]));
1031
        $v_perms = sprintf("%6s ", DecOct($v_info['mode']));
1104
        $v_uid = sprintf("%07s", DecOct($v_info[4]));
1105
        $v_gid = sprintf("%07s", DecOct($v_info[5]));
1106
        $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
1032 1107

  
1033
        $v_mtime = sprintf("%11s", DecOct($v_info['mode']));
1108
        $v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
1034 1109

  
1035 1110
        $v_linkname = '';
1036 1111

  
1037 1112
        if (@is_link($p_filename)) {
1038 1113
          $v_typeflag = '2';
1039 1114
          $v_linkname = readlink($p_filename);
1040
          $v_size = sprintf("%11s ", DecOct(0));
1115
          $v_size = sprintf("%011s", DecOct(0));
1041 1116
        } elseif (@is_dir($p_filename)) {
1042 1117
          $v_typeflag = "5";
1043
          $v_size = sprintf("%11s ", DecOct(0));
1118
          $v_size = sprintf("%011s", DecOct(0));
1044 1119
        } else {
1045
          $v_typeflag = '';
1120
          $v_typeflag = '0';
1046 1121
          clearstatcache();
1047
          $v_size = sprintf("%11s ", DecOct($v_info['size']));
1122
          $v_size = sprintf("%011s", DecOct($v_info['size']));
1048 1123
        }
1049 1124

  
1050
        $v_magic = '';
1125
        $v_magic = 'ustar ';
1051 1126

  
1052
        $v_version = '';
1127
        $v_version = ' ';
1128
        
1129
        if (function_exists('posix_getpwuid'))
1130
        {
1131
          $userinfo = posix_getpwuid($v_info[4]);
1132
          $groupinfo = posix_getgrgid($v_info[5]);
1133
          
1134
          $v_uname = $userinfo['name'];
1135
          $v_gname = $groupinfo['name'];
1136
        }
1137
        else
1138
        {
1139
          $v_uname = '';
1140
          $v_gname = '';
1141
        }
1053 1142

  
1054
        $v_uname = '';
1055

  
1056
        $v_gname = '';
1057

  
1058 1143
        $v_devmajor = '';
1059 1144

  
1060 1145
        $v_devminor = '';
1061 1146

  
1062 1147
        $v_prefix = '';
1063 1148

  
1064
        $v_binary_data_first = pack("a100a8a8a8a12A12",
1149
        $v_binary_data_first = pack("a100a8a8a8a12a12",
1065 1150
		                            $v_reduce_filename, $v_perms, $v_uid,
1066 1151
									$v_gid, $v_size, $v_mtime);
1067 1152
        $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
......
1085 1170
        $this->_writeBlock($v_binary_data_first, 148);
1086 1171

  
1087 1172
        // ----- Write the calculated checksum
1088
        $v_checksum = sprintf("%6s ", DecOct($v_checksum));
1173
        $v_checksum = sprintf("%06s ", DecOct($v_checksum));
1089 1174
        $v_binary_data = pack("a8", $v_checksum);
1090 1175
        $this->_writeBlock($v_binary_data, 8);
1091 1176

  
......
1108 1193
        }
1109 1194

  
1110 1195
        if ($p_type == "5") {
1111
          $v_size = sprintf("%11s ", DecOct(0));
1196
          $v_size = sprintf("%011s", DecOct(0));
1112 1197
        } else {
1113
          $v_size = sprintf("%11s ", DecOct($p_size));
1198
          $v_size = sprintf("%011s", DecOct($p_size));
1114 1199
        }
1115 1200

  
1116
        $v_uid = sprintf("%6s ", DecOct($p_uid));
1117
        $v_gid = sprintf("%6s ", DecOct($p_gid));
1118
        $v_perms = sprintf("%6s ", DecOct($p_perms));
1201
        $v_uid = sprintf("%07s", DecOct($p_uid));
1202
        $v_gid = sprintf("%07s", DecOct($p_gid));
1203
        $v_perms = sprintf("%07s", DecOct($p_perms & 000777));
1119 1204

  
1120 1205
        $v_mtime = sprintf("%11s", DecOct($p_mtime));
1121 1206

  
1122 1207
        $v_linkname = '';
1123 1208

  
1124
        $v_magic = '';
1209
        $v_magic = 'ustar ';
1125 1210

  
1126
        $v_version = '';
1211
        $v_version = ' ';
1127 1212

  
1128
        $v_uname = '';
1129

  
1130
        $v_gname = '';
1131

  
1213
        if (function_exists('posix_getpwuid'))
1214
        {
1215
          $userinfo = posix_getpwuid($p_uid);
1216
          $groupinfo = posix_getgrgid($p_gid);
1217
          
1218
          $v_uname = $userinfo['name'];
1219
          $v_gname = $groupinfo['name'];
1220
        }
1221
        else
1222
        {
1223
          $v_uname = '';
1224
          $v_gname = '';
1225
        }
1226
        
1132 1227
        $v_devmajor = '';
1133 1228

  
1134 1229
        $v_devminor = '';
......
1159 1254
        $this->_writeBlock($v_binary_data_first, 148);
1160 1255

  
1161 1256
        // ----- Write the calculated checksum
1162
        $v_checksum = sprintf("%6s ", DecOct($v_checksum));
1257
        $v_checksum = sprintf("%06s ", DecOct($v_checksum));
1163 1258
        $v_binary_data = pack("a8", $v_checksum);
1164 1259
        $this->_writeBlock($v_binary_data, 8);
1165 1260

  
......
1193 1288

  
1194 1289
        $v_prefix = '';
1195 1290

  
1196
        $v_binary_data_first = pack("a100a8a8a8a12A12",
1291
        $v_binary_data_first = pack("a100a8a8a8a12a12",
1197 1292
		                            '././@LongLink', 0, 0, 0, $v_size, 0);
1198 1293
        $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
1199 1294
		                           $v_typeflag, $v_linkname, $v_magic,
......
1216 1311
        $this->_writeBlock($v_binary_data_first, 148);
1217 1312

  
1218 1313
        // ----- Write the calculated checksum
1219
        $v_checksum = sprintf("%6s ", DecOct($v_checksum));
1314
        $v_checksum = sprintf("%06s ", DecOct($v_checksum));
1220 1315
        $v_binary_data = pack("a8", $v_checksum);
1221 1316
        $this->_writeBlock($v_binary_data, 8);
1222 1317

  
......
1263 1358
        for ($i=156; $i<512; $i++)
1264 1359
           $v_checksum+=ord(substr($v_binary_data,$i,1));
1265 1360

  
1266
        $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/"
1267
		                 ."a8checksum/a1typeflag/a100link/a6magic/a2version/"
1268
						 ."a32uname/a32gname/a8devmajor/a8devminor",
1269
						 $v_binary_data);
1361
        if (version_compare(PHP_VERSION,"5.5.0-dev")<0) {
1362
            $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
1363
                   "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
1364
                   "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
1365
        } else {
1366
            $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
1367
                   "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
1368
                   "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
1369
        }
1370
        $v_data = unpack($fmt, $v_binary_data);
1270 1371

  
1372
        if (strlen($v_data["prefix"]) > 0) {
1373
            $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
1374
        }
1375

  
1271 1376
        // ----- Extract the checksum
1272 1377
        $v_header['checksum'] = OctDec(trim($v_data['checksum']));
1273 1378
        if ($v_header['checksum'] != $v_checksum) {
......
1284 1389
        }
1285 1390

  
1286 1391
        // ----- Extract the properties
1287
        $v_header['filename'] = trim($v_data['filename']);
1392
        $v_header['filename'] = $v_data['filename'];
1288 1393
        if ($this->_maliciousFilename($v_header['filename'])) {
1289 1394
            $this->_error('Malicious .tar detected, file "' . $v_header['filename'] .
1290 1395
                '" will not install in desired directory tree');
......
1318 1423
     * Detect and report a malicious file name
1319 1424
     *
1320 1425
     * @param string $file
1426
     *
1321 1427
     * @return bool
1322 1428
     * @access private
1323 1429
     */
......
1344 1450
      }
1345 1451
      if (($v_header['size'] % 512) != 0) {
1346 1452
        $v_content = $this->_readBlock();
1347
        $v_filename .= $v_content;
1453
        $v_filename .= trim($v_content);
1348 1454
      }
1349 1455

  
1350 1456
      // ----- Read the next header
......
1368 1474
    // {{{ _extractInString()
1369 1475
    /**
1370 1476
    * This method extract from the archive one file identified by $p_filename.
1371
    * The return value is a string with the file content, or NULL on error.
1372
    * @param string $p_filename     The path of the file to extract in a string.
1373
    * @return                       a string with the file content or NULL.
1477
    * The return value is a string with the file content, or null on error.
1478
    *
1479
    * @param string $p_filename The path of the file to extract in a string.
1480
    *
1481
    * @return a string with the file content or null.
1374 1482
    * @access private
1375 1483
    */
1376 1484
    function _extractInString($p_filename)
......
1380 1488
        While (strlen($v_binary_data = $this->_readBlock()) != 0)
1381 1489
        {
1382 1490
          if (!$this->_readHeader($v_binary_data, $v_header))
1383
            return NULL;
1491
            return null;
1384 1492

  
1385 1493
          if ($v_header['filename'] == '')
1386 1494
            continue;
......
1388 1496
          // ----- Look for long filename
1389 1497
          if ($v_header['typeflag'] == 'L') {
1390 1498
            if (!$this->_readLongHeader($v_header))
1391
              return NULL;
1499
              return null;
1392 1500
          }
1393 1501

  
1394 1502
          if ($v_header['filename'] == $p_filename) {
1395 1503
              if ($v_header['typeflag'] == "5") {
1396 1504
                  $this->_error('Unable to extract in string a directory '
1397 1505
				                .'entry {'.$v_header['filename'].'}');
1398
                  return NULL;
1506
                  return null;
1399 1507
              } else {
1400 1508
                  $n = floor($v_header['size']/512);
1401 1509
                  for ($i=0; $i<$n; $i++) {
......
1413 1521
          }
1414 1522
        }
1415 1523

  
1416
        return NULL;
1524
        return null;
1417 1525
    }
1418 1526
    // }}}
1419 1527

  
1420 1528
    // {{{ _extractList()
1421 1529
    function _extractList($p_path, &$p_list_detail, $p_mode,
1422
	                      $p_file_list, $p_remove_path)
1530
                          $p_file_list, $p_remove_path, $p_preserve=false)
1423 1531
    {
1424 1532
    $v_result=true;
1425 1533
    $v_nb = 0;
......
1440 1548

  
1441 1549
    switch ($p_mode) {
1442 1550
      case "complete" :
1443
        $v_extract_all = TRUE;
1444
        $v_listing = FALSE;
1551
        $v_extract_all = true;
1552
        $v_listing = false;
1445 1553
      break;
1446 1554
      case "partial" :
1447
          $v_extract_all = FALSE;
1448
          $v_listing = FALSE;
1555
          $v_extract_all = false;
1556
          $v_listing = false;
1449 1557
      break;
1450 1558
      case "list" :
1451
          $v_extract_all = FALSE;
1452
          $v_listing = TRUE;
1559
          $v_extract_all = false;
1560
          $v_listing = true;
1453 1561
      break;
1454 1562
      default :
1455 1563
        $this->_error('Invalid extract mode ('.$p_mode.')');
......
1487 1595
            if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
1488 1596
			    && (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
1489 1597
				    == $p_file_list[$i])) {
1490
              $v_extract_file = TRUE;
1598
              $v_extract_file = true;
1491 1599
              break;
1492 1600
            }
1493 1601
          }
1494 1602

  
1495 1603
          // ----- It is a file, so compare the file names
1496 1604
          elseif ($p_file_list[$i] == $v_header['filename']) {
1497
            $v_extract_file = TRUE;
1605
            $v_extract_file = true;
1498 1606
            break;
1499 1607
          }
1500 1608
        }
1501 1609
      } else {
1502
        $v_extract_file = TRUE;
1610
        $v_extract_file = true;
1503 1611
      }
1504 1612

  
1505 1613
      // ----- Look if this file need to be extracted
1506 1614
      if (($v_extract_file) && (!$v_listing))
1507 1615
      {
1508 1616
        if (($p_remove_path != '')
1509
            && (substr($v_header['filename'], 0, $p_remove_path_size)
1510
			    == $p_remove_path))
1617
            && (substr($v_header['filename'].'/', 0, $p_remove_path_size)
1618
			    == $p_remove_path)) {
1511 1619
          $v_header['filename'] = substr($v_header['filename'],
1512 1620
		                                 $p_remove_path_size);
1621
          if( $v_header['filename'] == '' ){
1622
            continue;
1623
          }
1624
        }
1513 1625
        if (($p_path != './') && ($p_path != '/')) {
1514 1626
          while (substr($p_path, -1) == '/')
1515 1627
            $p_path = substr($p_path, 0, strlen($p_path)-1);
......
1586 1698
            }
1587 1699

  
1588 1700
            @fclose($v_dest_file);
1701
            
1702
            if ($p_preserve) {
1703
                @chown($v_header['filename'], $v_header['uid']);
1704
                @chgrp($v_header['filename'], $v_header['gid']);
1705
            }
1589 1706

  
1590 1707
            // ----- Change the file mode, mtime
1591 1708
            @touch($v_header['filename'], $v_header['mtime']);
......
1598 1715

  
1599 1716
          // ----- Check the file size
1600 1717
          clearstatcache();
1601
          if (filesize($v_header['filename']) != $v_header['size']) {
1718
          if (!is_file($v_header['filename'])) {
1602 1719
              $this->_error('Extracted file '.$v_header['filename']
1603
			                .' does not have the correct file size \''
1604
							.filesize($v_header['filename'])
1605
							.'\' ('.$v_header['size']
1606
							.' expected). Archive may be corrupted.');
1720
                            .'does not exist. Archive may be corrupted.');
1607 1721
              return false;
1608 1722
          }
1723
          
1724
          $filesize = filesize($v_header['filename']);
1725
          if ($filesize != $v_header['size']) {
1726
              $this->_error('Extracted file '.$v_header['filename']
1727
                            .' does not have the correct file size \''
1728
                            .$filesize
1729
                            .'\' ('.$v_header['size']
1730
                            .' expected). Archive may be corrupted.');
1731
              return false;
1609 1732
          }
1733
          }
1610 1734
        } else {
1611 1735
          $this->_jumpBlock(ceil(($v_header['size']/512)));
1612 1736
        }
......
1674 1798
            }
1675 1799

  
1676 1800
            if ($this->_compress_type == 'gz') {
1801
                $end_blocks = 0;
1802
                
1677 1803
                while (!@gzeof($v_temp_tar)) {
1678 1804
                    $v_buffer = @gzread($v_temp_tar, 512);
1679
                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
1805
                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
1806
                        $end_blocks++;
1680 1807
                        // do not copy end blocks, we will re-make them
1681 1808
                        // after appending
1682 1809
                        continue;
1810
                    } elseif ($end_blocks > 0) {
1811
                        for ($i = 0; $i < $end_blocks; $i++) {
1812
                            $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
1813
                        }
1814
                        $end_blocks = 0;
1683 1815
                    }
1684 1816
                    $v_binary_data = pack("a512", $v_buffer);
1685 1817
                    $this->_writeBlock($v_binary_data);
......
1688 1820
                @gzclose($v_temp_tar);
1689 1821
            }
1690 1822
            elseif ($this->_compress_type == 'bz2') {
1823
                $end_blocks = 0;
1824
                
1691 1825
                while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
1692
                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
1826
                    if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
1827
                        $end_blocks++;
1828
                        // do not copy end blocks, we will re-make them
1829
                        // after appending
1693 1830
                        continue;
1831
                    } elseif ($end_blocks > 0) {
1832
                        for ($i = 0; $i < $end_blocks; $i++) {
1833
                            $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
1834
                        }
1835
                        $end_blocks = 0;
1694 1836
                    }
1695 1837
                    $v_binary_data = pack("a512", $v_buffer);
1696 1838
                    $this->_writeBlock($v_binary_data);
......
1752 1894
     *
1753 1895
     * @param string $p_dir directory to check
1754 1896
     *
1755
     * @return bool TRUE if the directory exists or was created
1897
     * @return bool true if the directory exists or was created
1756 1898
     */
1757 1899
    function _dirCheck($p_dir)
1758 1900
    {
......
1821 1963
                }
1822 1964
            }
1823 1965
        }
1824
        $v_result = strtr($v_result, '\\', '/');
1966
        
1967
        if (defined('OS_WINDOWS') && OS_WINDOWS) {
1968
            $v_result = strtr($v_result, '\\', '/');
1969
        }
1970
        
1825 1971
        return $v_result;
1826 1972
    }
1827 1973

  
......
1846 1992
    // }}}
1847 1993

  
1848 1994
}
1849
?>
branches/extplorer2/CHANGELOG.txt
2 2
Changelog for eXtplorer
3 3
Version $Id$
4 4
****************************
5
--- version 2.1.4 ---
6
- update to the latest version of Archive_Tar
7
- fixed version check link, now points to extplorer.net
8

  
5 9
--- version 2.1.3 ---
6 10
- fixed serious login vulnerability reported by Brendan Coles of itsecuritysolutions.org (the only changed file is /include/users.php)
7 11

  
branches/extplorer2/include/system_info.php
313 313
	<br />
314 314
	".ext_Lang::msg('your_version').": <a href=\"".$GLOBALS['ext_home']."\" target=\"_blank\">eXtplorer {$GLOBALS['ext_version']}</a>
315 315
	<br />
316
 (<a href=\"http://virtuemart.net/index2.php?option=com_versions&amp;catid=5&amp;myVersion=". $GLOBALS['ext_version'] ."\" onclick=\"javascript:void window.open('http://virtuemart.net/index2.php?option=com_versions&catid=5&myVersion=". $GLOBALS['ext_version'] ."', 'win2', 'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=580,directories=no,location=no'); return false;\" title=\"".$GLOBALS["messages"]["check_version"]."\">".$GLOBALS["messages"]["check_version"]."</a>)
316
 (<a href=\"http://extplorer.net/version_check?myVersion=". $GLOBALS['ext_version'] ."\" onclick=\"javascript:void window.open('http://extplorer.net/version_check?myVersion=". $GLOBALS['ext_version'] ."', 'win2', 'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=580,directories=no,location=no'); return false;\" title=\"".$GLOBALS["messages"]["check_version"]."\">".$GLOBALS["messages"]["check_version"]."</a>)
317 317

  
318 318
	";
319 319
	

Also available in: Unified diff