diff options
-rw-r--r-- | _test/tests/inc/tar.test.php | 17 | ||||
-rw-r--r-- | _test/tests/inc/tar/longpath-gnu.tgz | bin | 0 -> 413 bytes | |||
-rw-r--r-- | _test/tests/inc/tar/longpath-ustar.tgz | bin | 0 -> 311 bytes | |||
-rw-r--r-- | inc/Tar.class.php | 43 |
4 files changed, 44 insertions, 16 deletions
diff --git a/_test/tests/inc/tar.test.php b/_test/tests/inc/tar.test.php index 4de9e668d..9abd27612 100644 --- a/_test/tests/inc/tar.test.php +++ b/_test/tests/inc/tar.test.php @@ -218,7 +218,6 @@ class Tar_TestCase extends DokuWikiTest { } } - /** * Check the extension to compression guesser */ @@ -234,4 +233,20 @@ class Tar_TestCase extends DokuWikiTest { $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tar.BZ2')); $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tar.bz2')); } + + public function test_longpathextract(){ + $dir = dirname(__FILE__).'/tar'; + $out = sys_get_temp_dir().'/dwtartest'.md5(time()); + + foreach(array('ustar','gnu') as $format){ + $tar = new Tar(); + $tar->open("$dir/longpath-$format.tgz"); + $tar->extract($out); + + $this->assertFileExists($out.'/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/test.txt'); + + TestUtils::rdelete($out); + } + } + }
\ No newline at end of file diff --git a/_test/tests/inc/tar/longpath-gnu.tgz b/_test/tests/inc/tar/longpath-gnu.tgz Binary files differnew file mode 100644 index 000000000..6c937c8fe --- /dev/null +++ b/_test/tests/inc/tar/longpath-gnu.tgz diff --git a/_test/tests/inc/tar/longpath-ustar.tgz b/_test/tests/inc/tar/longpath-ustar.tgz Binary files differnew file mode 100644 index 000000000..59efbff66 --- /dev/null +++ b/_test/tests/inc/tar/longpath-ustar.tgz diff --git a/inc/Tar.class.php b/inc/Tar.class.php index 7f5e5af4a..8da30e736 100644 --- a/inc/Tar.class.php +++ b/inc/Tar.class.php @@ -204,7 +204,7 @@ class Tar { // is this a file? if(!$header['typeflag']){ - $fp = @fopen($output, "wb"); + $fp = fopen($output, "wb"); if(!$fp) throw(new TarIOException('Could not open file for writing: '.$output)); $size = floor($header['size'] / 512); @@ -508,7 +508,6 @@ class Tar { /** * Decode the given tar file header * - * @todo how to handle filenames >100 chars? * @param string $block a 512 byte block containign the header data * @return array|bool */ @@ -521,22 +520,36 @@ class Tar { for($i = 156, $chks += 256; $i < 512; $i++) $chks += ord($block[$i]); - $headers = @unpack("a100filename/a8perm/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $block); - if(!$headers) return false; + $header = @unpack("a100filename/a8perm/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix", $block); + if(!$header) return false; - $return['checksum'] = OctDec(trim($headers['checksum'])); + $return['checksum'] = OctDec(trim($header['checksum'])); if($return['checksum'] != $chks) return false; - $return['filename'] = trim($headers['filename']); - $return['perm'] = OctDec(trim($headers['perm'])); - $return['uid'] = OctDec(trim($headers['uid'])); - $return['gid'] = OctDec(trim($headers['gid'])); - $return['size'] = OctDec(trim($headers['size'])); - $return['mtime'] = OctDec(trim($headers['mtime'])); - $return['typeflag'] = $headers['typeflag']; - $return['link'] = trim($headers['link']); - $return['uname'] = trim($headers['uname']); - $return['gname'] = trim($headers['gname']); + $return['filename'] = trim($header['filename']); + $return['perm'] = OctDec(trim($header['perm'])); + $return['uid'] = OctDec(trim($header['uid'])); + $return['gid'] = OctDec(trim($header['gid'])); + $return['size'] = OctDec(trim($header['size'])); + $return['mtime'] = OctDec(trim($header['mtime'])); + $return['typeflag'] = $header['typeflag']; + $return['link'] = trim($header['link']); + $return['uname'] = trim($header['uname']); + $return['gname'] = trim($header['gname']); + + // Handle ustar Posix compliant path prefixes + if(trim($header['prefix'])) $return['filename'] = trim($header['prefix']).'/'.$return['filename']; + + // Handle Long-Link entries from GNU Tar + if($return['typeflag'] == 'L'){ + // following data block(s) is the filename + $filename = trim($this->readbytes(ceil($header['size'] / 512) * 512)); + // next block is the real header + $block = $this->readbytes(512); + $return = $this->parseHeader($block); + // overwrite the filename + $return['filename'] = $filename; + } return $return; } |