#!/usr/bin/perl -T use strict ; use warnings ; use CGI ':standard' ; use Archive::Tar ; use POSIX ; use File::Path ; use Fcntl ':flock' ; my $NAMEWIDTH = 23 ; my $MTIMEWIDTH = 17 ; my $SIZEWIDTH = 6 ; my $tardir = '/home/www/htdocs/slackpack' ; my $tmpdir = '/home/www/tmp/tarpeek' ; my $url = url() ; my $path_info = path_info() ; my (undef, $file, $subfile) = split(/\/+/,$path_info,3) ; my $dir = '' ; while ($subfile and -d "$tardir/$dir$file") { $dir = "$dir$file/" ; ($file, $subfile) = split(/\/+/,$subfile,2) ; } if (!$subfile and $path_info !~ m!/$!) { print redirect("$url$path_info/") ; exit ; } $subfile ||= '' ; if (!$subfile or $subfile =~ /\/$/) { print header('text/html') ; print start_html("Index of $path_info") ; print h1("Index of $path_info") ; print '
' ;
printf "%s %-${NAMEWIDTH}s %-${MTIMEWIDTH}s %${SIZEWIDTH}s\n",
img({-src=>'/icons/blank.gif', -border=>0}),
'Name',
'Last modified',
'Size' ;
print hr() ;
print a({-href=>'..'},[img({-src=>'/icons/back.gif', -border=>0}),'Parent directory'])."\n" if $subfile ;
my @tarfiles =
sort {
$b->{name} =~ m!/$! <=> $a->{name} =~ m!/$!
||
$a->{name} cmp $b->{name}
} grep { $_->{name} =~ m!^\Q$subfile\E[^/]+/?$! } list_archive("$dir$file") ;
foreach my $tarfile (@tarfiles) {
my $size = $tarfile->{size} ;
$size = $size ? sprintf '%dk', ($size>>10) : '-' ;
my $mtime = $tarfile->{mtime} ;
my $filename = $tarfile->{name} ;
next if $filename eq './' ;
$filename =~ m!^\Q$subfile\E([^/]+/?)$! and $filename = $1 ;
my $displayname = $filename ;
substr($displayname, ($NAMEWIDTH - 2)) = '..>' if (length($displayname) > $NAMEWIDTH) ;
my $icon = '/icons/unknown.gif' ;
if ($filename =~ m!/$!) {
$icon = '/icons/folder.gif' ;
} elsif ($filename =~ /(?:\.html?|\.te?xt)/) {
$icon = '/icons/text.gif' ;
}
printf "%s %s%s %s %${SIZEWIDTH}s\n",
img({-src=>$icon, -border=>0}),
$filename,
$displayname,
' 'x($NAMEWIDTH - length $displayname),
strftime('%d-%b-%Y %R', localtime $mtime),
$size;
}
print '' ;
print hr() ;
print end_html() ;
} else {
my $tar = Archive::Tar->new("$tardir/$dir$file") ;
my $content = $tar->get_content($subfile) ;
print $content ? (header('*/*'),$content) : (redirect("$url$path_info/")) ;
}
sub list_archive {
my $tarfile = shift ;
$tarfile =~ s!\.\.!!g ;
if ($tarfile =~ m!((?:[^/]*/?)*)!) {
$tarfile = $1 ;
} else {
die ;
}
my @tarcontents = () ;
mkpath($1,0,0755) if "$tmpdir/$tarfile" =~ m!(.*/)! ;
my $tarfile_mtime = (stat "$tardir/$tarfile")[9] || 0 ;
my $tmpfile_mtime = (stat "$tmpdir/$tarfile")[9] || 0 ;
if ($tarfile_mtime > $tmpfile_mtime) {
@tarcontents = Archive::Tar->list_archive("$tardir/$tarfile",[ 'name','mtime','size' ] ) ;
open TARCONTENTS, '>', "$tmpdir/$tarfile" or return @tarcontents ;
flock TARCONTENTS, LOCK_EX ;
foreach my $tar (@tarcontents) {
print TARCONTENTS "$tar->{name} $tar->{mtime} $tar->{size}\n" ;
}
flock TARCONTENTS, LOCK_UN ;
close TARCONTENTS ;
} else {
open TARCONTENTS, '<', "$tmpdir/$tarfile" or return Archive::Tar->list_archive("$tardir/$tarfile",[ 'name','mtime','size' ] ) ;
flock TARCONTENTS, LOCK_SH ;
while (