--- loncom/interface/loncommon.pm 2012/04/04 23:06:52 1.1064 +++ loncom/interface/loncommon.pm 2012/04/05 13:32:15 1.1065 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.1064 2012/04/04 23:06:52 raeburn Exp $ +# $Id: loncommon.pm,v 1.1065 2012/04/05 13:32:15 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -7022,12 +7022,12 @@ sub print_suppression { $scope .= "/$env{'request.course.sec'}"; if ((&Apache::lonnet::allowed('pav',$scope)) || (&Apache::lonnet::allowed('pfo',$scope))) { - return; + return; } } my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - my $blocked = &blocking_status('printout',$cnum,$cdom); + my $blocked = &blocking_status('printout',$cnum,$cdom); if ($blocked) { my $checkrole = "cm./$cdom/$cnum"; if ($env{'request.course.sec'} ne '') { @@ -9928,21 +9928,92 @@ sub is_archive_file { } sub decompress_form { - my ($mimetype,$archiveurl,$action,$noextract,$hiddenelements) = @_; + my ($mimetype,$archiveurl,$action,$noextract,$hiddenelements,$dirlist) = @_; my %lt = &Apache::lonlocal::texthash ( this => 'This file is an archive file.', + itsc => 'Its contents are as follows:', youm => 'You may wish to extract its contents.', camt => 'Extraction of contents is recommended for Camtasia zip files.', - perm => 'Permanently remove archive file after extraction of contents?', extr => 'Extract contents', yes => 'Yes', no => 'No', ); - my $output = '

'.$lt{'this'}.' '.$lt{'youm'}.'
'; + my $output = '

'.$lt{'this'}; + my $fileloc = &Apache::lonnet::filelocation(undef,$archiveurl); + my (%toplevel,@paths); + my $info = &list_archive_contents($fileloc,\@paths); + if (@paths) { + foreach my $path (@paths) { + $path =~ s{^/}{}; + if ($path =~ m{^([^/]+)/}) { + $toplevel{$1} = $path; + } else { + $toplevel{$path} = $path; + } + } + } + if ($info eq '') { + $output .= ' '.$lt{'youm'}.'

'."\n"; + } else { + $output .= ' '.$lt{'itsc'}.'

'."\n". + '
'.$info.'
'; + } + my $duplicates; + my $num = 0; + if (ref($dirlist) eq 'ARRAY') { + foreach my $item (@{$dirlist}) { + if (ref($item) eq 'ARRAY') { + if (exists($toplevel{$item->[0]})) { + $duplicates .= + &start_data_table_row(). + ''. + ' '. + ''."\n". + ''.$item->[0].''; + if ($item->[2]) { + $duplicates .= ''.&mt('Directory').''; + } else { + $duplicates .= ''.&mt('File').''; + } + $duplicates .= ''.$item->[3].''. + ''. + &Apache::lonlocal::locallocaltime($item->[4]). + ''. + &end_data_table_row(); + $num ++; + } + } + } + } + my $itemcount; + if (@paths > 0) { + $itemcount = scalar(@paths); + } else { + $itemcount = 1; + } + $output .= + ''. + ''."\n"; + if ($duplicates ne '') { + $output .= '

'. + &mt('Warning: decompression of the archive will overwrite the following items which already exist:').'
'. + &start_data_table(). + &start_data_table_header_row(). + ''.&mt('Overwrite?').''. + ''.&mt('Name').''. + ''.&mt('Type').''. + ''.&mt('Size').''. + ''.&mt('Last modified').''. + &end_data_table_header_row(). + $duplicates. + &end_data_table(). + '

'; + } if ($mimetype =~ m{^application/(x\-)?(compressed|zip)}) { - $output .= $lt{'camt'}; + $output .= '

'.$lt{'camt'}.'

'; } - $output .= '

'; $output .= <<"START";
@@ -9954,9 +10025,6 @@ START } } $output .= <<"END"; -$lt{'perm'}  -   -
$noextract @@ -9965,6 +10033,62 @@ END return $output; } +sub decompression_utility { + my ($program) = @_; + my @utilities = ('tar','gunzip','bunzip2','unzip'); + my $location; + if (grep(/^\Q$program\E$/,@utilities)) { + foreach my $dir ('/bin/','/usr/bin/','/usr/local/bin/','/sbin/', + '/usr/sbin/') { + if (-x $dir.$program) { + $location = $dir.$program; + last; + } + } + } + return $location; +} + +sub list_archive_contents { + my ($file,$pathsref) = @_; + my (@cmd,$output); + my $needsregexp; + if ($file =~ /\.zip$/) { + @cmd = (&decompression_utility('unzip'),"-l"); + $needsregexp = 1; + } elsif (($file =~ m/\.tar\.gz$/) || + ($file =~ /\.tgz$/)) { + @cmd = (&decompression_utility('tar'),"-ztf"); + } elsif ($file =~ /\.tar\.bz2$/) { + @cmd = (&decompression_utility('tar'),"-jtf"); + } elsif ($file =~ m|\.tar$|) { + @cmd = (&decompression_utility('tar'),"-tf"); + } + if (@cmd) { + undef($!); + undef($@); + if (open(my $fh,"-|", @cmd, $file)) { + while (my $line = <$fh>) { + $output .= $line; + chomp($line); + my $item; + if ($needsregexp) { + ($item) = ($line =~ /^\s*\d+\s+[\d\-]+\s+[\d:]+\s*(.+)$/); + } else { + $item = $line; + } + if ($item ne '') { + unless (grep(/^\Q$item\E$/,@{$pathsref})) { + push(@{$pathsref},$item); + } + } + } + close($fh); + } + } + return $output; +} + sub decompress_uploaded_file { my ($file,$dir) = @_; &Apache::lonnet::appenv({'cgi.file' => $file}); @@ -9994,8 +10118,6 @@ sub process_decompression { } else { my @ids=&Apache::lonnet::current_machine_ids(); my $currdir = "$dir_root/$destination"; - my ($currdirlistref,$currlisterror) = - &Apache::lonnet::dirlist($currdir,$docudom,$docuname,1); if (grep(/^\Q$docuhome\E$/,@ids)) { $dir = &LONCAPA::propath($docudom,$docuname). "$dir_root/$destination"; @@ -10006,47 +10128,61 @@ sub process_decompression { $error = &mt('Archive file not found.'); } } - if ($dir eq '') { + my (@to_overwrite,@to_skip); + if ($env{'form.archive_overwrite_total'} > 0) { + my $total = $env{'form.archive_overwrite_total'}; + for (my $i=0; $i<$total; $i++) { + if ($env{'form.archive_overwrite_'.$i} == 1) { + push(@to_overwrite,$env{'form.archive_overwrite_name_'.$i}); + } elsif ($env{'form.archive_overwrite_'.$i} == 0) { + push(@to_skip,$env{'form.archive_overwrite_name_'.$i}); + } + } + } + my $numskip = scalar(@to_skip); + if (($numskip > 0) && + ($numskip == $env{'form.archive_itemcount'})) { + $warning = &mt('All items in the archive file already exist, and no overwriting of existing files has been requested.'); + } elsif ($dir eq '') { $error = &mt('Directory containing archive file unavailable.'); } elsif (!$error) { - my ($decompressed,$display) = &decompress_uploaded_file($file,$dir); + my ($decompressed,$display); + if ($numskip > 0) { + my $tempdir = time.'_'.$$.int(rand(10000)); + mkdir("$dir/$tempdir",0755); + system("mv $dir/$file $dir/$tempdir/$file"); + ($decompressed,$display) = + &decompress_uploaded_file($file,"$dir/$tempdir"); + foreach my $item (@to_skip) { + if (($item ne '') && ($item !~ /\.\./)) { + if (-f "$dir/$tempdir/$item") { + unlink("$dir/$tempdir/$item"); + } elsif (-d "$dir/$tempdir/$item") { + system("rm -rf $dir/$tempdir/$item"); + } + } + } + system("mv $dir/$tempdir/* $dir"); + rmdir("$dir/$tempdir"); + } else { + ($decompressed,$display) = + &decompress_uploaded_file($file,$dir); + } if ($decompressed eq 'ok') { - $output = &mt('Files extracted successfully from archive.').'
'; + $output = '

'. + &mt('Files extracted successfully from archive.'). + '

'."\n"; my ($warning,$result,@contents); my ($newdirlistref,$newlisterror) = &Apache::lonnet::dirlist($currdir,$docudom, $docuname,1); my (%is_dir,%changes,@newitems); my $dirptr = 16384; - if (ref($currdirlistref) eq 'ARRAY') { - my @curritems; - foreach my $dir_line (@{$currdirlistref}) { - my ($item,$rest)=split(/\&/,$dir_line,2); - unless ($item =~ /\.+$/) { - push(@curritems,$item); - } - } - if (ref($newdirlistref) eq 'ARRAY') { - foreach my $dir_line (@{$newdirlistref}) { - my ($item,undef,undef,$testdir)=split(/\&/,$dir_line,4); - unless ($item =~ /^\.+$/) { - if ($dirptr&$testdir) { - $is_dir{$item} = 1; - } - push(@newitems,$item); - } - } - my @diffs = &compare_arrays(\@curritems,\@newitems); - if (@diffs > 0) { - foreach my $item (@diffs) { - $changes{$item} = 1; - } - } - } - } elsif (ref($newdirlistref) eq 'ARRAY') { + if (ref($newdirlistref) eq 'ARRAY') { foreach my $dir_line (@{$newdirlistref}) { my ($item,undef,undef,$testdir)=split(/\&/,$dir_line,5); - unless ($item =~ /\.+$/) { + unless (($item =~ /^\.+$/) || ($item eq $file) || + ((@to_skip > 0) && (grep(/^\Q$item\E$/,@to_skip)))) { push(@newitems,$item); if ($dirptr&$testdir) { $is_dir{$item} = 1; @@ -10073,7 +10209,7 @@ sub process_decompression { if ($datatable ne '') { $output .= &archive_options_form('decompressed',$datatable, $count,$hiddenelem); - my $startcount = 4; + my $startcount = 6; $output .= &archive_javascript($startcount,$count, \%titles,\%children); } @@ -10202,6 +10338,9 @@ sub archive_row { my $offset = 0; foreach my $action ('display','dependency','discard') { $offset ++; + if ($action ne 'display') { + $offset ++; + } $output .= ''. '