1BEGIN { chdir 't' if -d 't' }
2
3use Test::More      'no_plan';
4use File::Basename  'basename';
5use strict;
6use lib '../lib';
7
8my $NO_UNLINK   = @ARGV ? 1 : 0;
9
10my $Class       = 'Archive::Tar';
11my $FileClass   = $Class . '::File';
12
13use_ok( $Class );
14use_ok( $FileClass );
15
16### bug #13636
17### tests for @longlink behaviour on files that have a / at the end
18### of their shortened path, making them appear to be directories
19{   ok( 1,                      "Testing bug 13636" );
20
21    ### dont use the prefix, otherwise A::T will not use @longlink
22    ### encoding style
23    local $Archive::Tar::DO_NOT_USE_PREFIX = 1;
24    local $Archive::Tar::DO_NOT_USE_PREFIX = 1;
25
26    my $dir =   'Catalyst-Helper-Controller-Scaffold-HTML-Template-0_03/' .
27                'lib/Catalyst/Helper/Controller/Scaffold/HTML/';
28    my $file =  'Template.pm';
29    my $out =   $$ . '.tar';
30
31    ### first create the file
32    {   my $tar = $Class->new;
33
34        isa_ok( $tar, $Class,   "   Object" );
35        ok( $tar->add_data( $dir.$file => $$ ),
36                                "       Added long file" );
37
38        ok( $tar->write($out),  "       File written to $out" );
39    }
40
41    ### then read it back in
42    {   my $tar = $Class->new;
43        isa_ok( $tar, $Class,   "   Object" );
44        ok( $tar->read( $out ), "       Read in $out again" );
45
46        my @files = $tar->get_files;
47        is( scalar(@files), 1,  "       Only 1 entry found" );
48
49        my $entry = shift @files;
50        ok( $entry->is_file,    "       Entry is a file" );
51        is( $entry->name, $dir.$file,
52                                "       With the proper name" );
53    }
54
55    ### remove the file
56    unless( $NO_UNLINK ) { 1 while unlink $out }
57}
58
59### bug #14922
60### There's a bug in Archive::Tar that causes a file like: foo/foo.txt
61### to be stored in the tar file as: foo/.txt
62### XXX could not be reproduced in 1.26 -- leave test to be sure
63{   ok( 1,                      "Testing bug 14922" );
64
65    my $dir     = $$ . '/';
66    my $file    = $$ . '.txt';
67    my $out     = $$ . '.tar';
68
69    ### first create the file
70    {   my $tar = $Class->new;
71
72        isa_ok( $tar, $Class,   "   Object" );
73        ok( $tar->add_data( $dir.$file => $$ ),
74                                "       Added long file" );
75
76        ok( $tar->write($out),  "       File written to $out" );
77    }
78
79    ### then read it back in
80    {   my $tar = $Class->new;
81        isa_ok( $tar, $Class,   "   Object" );
82        ok( $tar->read( $out ), "       Read in $out again" );
83
84        my @files = $tar->get_files;
85        is( scalar(@files), 1,  "       Only 1 entry found" );
86
87        my $entry = shift @files;
88        ok( $entry->is_file,    "       Entry is a file" );
89        is( $entry->full_path, $dir.$file,
90                                "       With the proper name" );
91    }
92
93    ### remove the file
94    unless( $NO_UNLINK ) { 1 while unlink $out }
95}
96
97### bug #30380: directory traversal vulnerability in Archive-Tar
98### Archive::Tar allowed files to be extracted to a dir outside
99### it's cwd(), effectively allowing you to overwrite any files
100### on the system, given the right permissions.
101{   ok( 1,                      "Testing bug 30880" );
102
103    my $tar = $Class->new;
104    isa_ok( $tar, $Class,       "   Object" );
105
106    ### absolute paths are already taken care of. Only relative paths
107    ### matter
108    my $in_file     = basename($0);
109    my $out_file    = '../' . $in_file . "_$$";
110
111    ok( $tar->add_files( $in_file ),
112                                "       Added '$in_file'" );
113
114    ok( $tar->chmod( $in_file, '1777'),
115                                "       chmod 177 $in_file" );
116
117    ok( $tar->chown( $in_file, 'root' ),
118                                "       chown to root" );
119
120    ok( $tar->chown( $in_file, 'root', 'root' ),
121                                "       chown to root:root" );
122
123    ok( $tar->rename( $in_file, $out_file ),
124                                "       Renamed to '$out_file'" );
125
126    ### first, test with strict extract permissions on
127    {   local $Archive::Tar::INSECURE_EXTRACT_MODE = 0;
128
129        ### we quell the error on STDERR
130        local $Archive::Tar::WARN = 0;
131        local $Archive::Tar::WARN = 0;
132
133        ok( 1,                  "   Extracting in secure mode" );
134
135        ok( ! $tar->extract_file( $out_file ),
136                                "       File not extracted" );
137        ok( ! -e $out_file,     "       File '$out_file' does not exist" );
138
139        ok( $tar->error,        "       Error message stored" );
140        like( $tar->error, qr/attempting to leave/,
141                                "           Proper violation detected" );
142    }
143
144    ### now disable those
145    {   local $Archive::Tar::INSECURE_EXTRACT_MODE = 1;
146        ok( 1,                  "   Extracting in insecure mode" );
147
148        ok( $tar->extract_file( $out_file ),
149                                "       File extracted" );
150        ok( -e $out_file,       "       File '$out_file' exists" );
151
152        ### and clean up
153        unless( $NO_UNLINK ) { 1 while unlink $out_file };
154    }
155}
156
157### bug #43513: [PATCH] Accept wrong checksums from SunOS and HP-UX tar
158### like GNU tar does. See here for details:
159### http://www.gnu.org/software/tar/manual/tar.html#SEC139
160{   ok( 1,                      "Testing bug 43513" );
161
162    my $src = File::Spec->catfile( qw[src header signed.tar] );
163    my $tar = $Class->new;
164
165    isa_ok( $tar, $Class,       "   Object" );
166    ok( $tar->read( $src ),     "   Read non-Posix file with signed Checksum" );
167
168    for my $file ( $tar->get_files ) {
169        ok( $file,              "       File object retrieved" );
170        ok( $file->validate,    "           File validates" );
171    }
172}
173
174### return error properly on corrupted archives
175### Addresses RT #44680: Improve error reporting on short corrupted archives
176{   ok( 1,                      "Testing bug 44680" );
177
178    {   ### XXX whitebox test -- resetting the error string
179        no warnings 'once';
180        $Archive::Tar::error = "";
181    }
182
183    my $src = File::Spec->catfile( qw[src short b] );
184    my $tar = $Class->new;
185
186    isa_ok( $tar, $Class,       "   Object" );
187
188
189    ### we quell the error on STDERR
190    local $Archive::Tar::WARN = 0;
191
192    ok( !$tar->read( $src ),    "   No files in the corrupted archive" );
193    like( $tar->error, qr/enough bytes/,
194                                "       Expected error reported" );
195}
196
197### bug #78030
198### tests for symlinks with relative paths
199### seen on MSWin32
200{   ok( 1,                      "Testing bug 78030" );
201		my $archname = 'tmp-symlink.tar.gz';
202		{	#build archive
203			unlink $archname if -e $archname;
204			local $Archive::Tar::DO_NOT_USE_PREFIX = 1;
205			my $t=Archive::Tar->new;
206			my $f = $t->add_data( 'tmp/a/b/link.txt', '',
207				{
208					linkname => '../c/ori.txt',
209					type     => 2,
210				} );
211			#why doesn't it keep my wish?
212			$f->{name}   = 'tmp/a/b/link.txt';
213			$f->{prefix} = '';
214			$t->add_data( 'tmp/a/c/ori.txt', 'test case' );
215			$t->write( $archname, 1 );
216		}
217
218    { #use case 1 - in memory extraction
219			my $t=Archive::Tar->new;
220			$t->read( $archname );
221			my $r = eval{ $t->extract };
222			ok( $r && !$@,            "   In memory extraction/symlinks" );
223			ok((stat 'tmp/a/b/link.txt')[7] == 9,
224			                          "       Linked content" ) unless $r;
225			clean_78030();
226		}
227
228		{ #use case 2 - iter extraction
229		  #$DB::single = 2;
230			my $next=Archive::Tar->iter( $archname, 1 );
231			my $failed = 0;
232			#use Data::Dumper;
233			while(my $f = $next->() ){
234			#  print "\$f = ", Dumper( $f ), $/;
235				eval{ $f->extract } or $failed++;
236			}
237			ok( !$failed,             "   From disk extraction/symlinks" );
238			ok((stat 'tmp/a/b/link.txt')[7] == 9,
239			                          "       Linked content" ) unless $failed;
240		}
241
242    #remove tmp files
243		sub clean_78030{
244			unlink for ('tmp/a/c/ori.txt', 'tmp/a/b/link.txt');
245			rmdir for ('tmp/a/c', 'tmp/a/b', 'tmp/a', 'tmp');
246		}
247		clean_78030();
248		unlink $archname;
249}
250
251### bug 97748
252### retain leading '/' for absolute pathnames.
253{   ok( 1,                      "Testing bug 97748" );
254	my $path= '/absolute/path';
255	my $tar = $Class->new;
256	isa_ok( $tar, $Class,       "   Object" );
257	my $file;
258
259	ok( $file = $tar->add_data( $path, '' ),
260		"       Added $path" );
261
262	ok( $file->full_path eq $path,
263		"	Paths mismatch <" . $file->full_path . "> ne <$path>" );
264}
265
266### bug 103279
267### retain trailing whitespace on filename
268{
269  ok( 1,                      "Testing bug 103279" );
270	my $tar = $Class->new;
271	isa_ok( $tar, $Class,       "   Object" );
272	ok( $tar->add_data( 'white_space   ', '' ),
273				    "   Add file <white_space   > containing filename with trailing whitespace");
274	ok( $tar->extract(),        "	Extract filename with trailing whitespace" );
275  SKIP: {
276    skip "Windows tries to be clever", 1 if $^O eq 'MSWin32';
277	  ok( ! -e 'white_space',     "	<white_space> should not exist" );
278  }
279	ok( -e 'white_space   ',    "	<white_space   > should exist" );
280	unlink foreach ('white_space   ', 'white_space');
281}
282