";
+ if ($bgcolor ne '') {
+ $tdcol = "background-color: $bgcolor;";
+ }
+ return <<"END";
+
+END
}
sub end_scrollbox {
@@ -7586,8 +7895,7 @@ role status: active, previous or future.
sub check_user_status {
my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
- my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
- my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,$extra);
+ my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
my @uroles = keys %userinfo;
my $srchstr;
my $active_chk = 'none';
@@ -8818,6 +9126,8 @@ sub get_future_slots {
=pod
+=back
+
=head1 HTTP Helpers
=over 4
@@ -8956,13 +9266,20 @@ sub get_env_multiple {
sub ask_for_embedded_content {
my ($actionurl,$state,$allfiles,$codebase,$args)=@_;
- my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges);
- my $num = 0;
+ my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges,
+ %currsubfile,%unused);
+ my $counter = 0;
+ my $numnew = 0;
my $numremref = 0;
my $numinvalid = 0;
my $numpathchg = 0;
my $numexisting = 0;
- my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath);
+ my $numunused = 0;
+ my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath,$cdom,$cnum,
+ $fileloc,$filename,$delete_output,$modify_output,$title,$symb,$path);
+ my $heading = &mt('Upload embedded files');
+ my $buttontext = &mt('Upload');
+
if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
my $current_path='/';
if ($env{'form.currentpath'}) {
@@ -8990,8 +9307,24 @@ sub ask_for_embedded_content {
}
} elsif ($actionurl eq '/adm/coursedocs') {
if (ref($args) eq 'HASH') {
- $url = $args->{'docs_url'};
- $toplevel = $url;
+ $url = $args->{'docs_url'};
+ $toplevel = $url;
+ }
+ } elsif ($actionurl eq '/adm/dependencies') {
+ if ($env{'request.course.id'} ne '') {
+ $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ if (ref($args) eq 'HASH') {
+ $url = $args->{'docs_url'};
+ $title = $args->{'docs_title'};
+ $toplevel = "/$url";
+ ($path) =
+ ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});
+ $fileloc = &Apache::lonnet::filelocation('',$toplevel);
+ $fileloc =~ s{^/}{};
+ ($filename) = ($fileloc =~ m{.+/([^/]+)$});
+ $heading = &mt('Status of dependencies in [_1]',"$title ($filename)");
+ }
}
}
my $now = time();
@@ -9030,25 +9363,44 @@ sub ask_for_embedded_content {
}
}
}
+ my $dirptr = 16384;
foreach my $path (keys(%subdependencies)) {
- my %currsubfile;
+ $currsubfile{$path} = {};
if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
my ($sublistref,$listerror) =
&Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);
if (ref($sublistref) eq 'ARRAY') {
foreach my $line (@{$sublistref}) {
my ($file_name,$rest) = split(/\&/,$line,2);
- $currsubfile{$file_name} = 1;
+ $currsubfile{$path}{$file_name} = 1;
}
}
} elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
if (opendir(my $dir,$url.'/'.$path)) {
my @subdir_list = grep(!/^\./,readdir($dir));
- map {$currsubfile{$_} = 1;} @subdir_list;
+ map {$currsubfile{$path}{$_} = 1;} @subdir_list;
+ }
+ } elsif ($actionurl eq '/adm/dependencies') {
+ if ($env{'request.course.id'} ne '') {
+ my ($dir) = ($fileloc =~ m{^(.+/)[^/]+$});
+ if ($dir ne '') {
+ my ($sublistref,$listerror) =
+ &Apache::lonnet::dirlist($dir.$path,$cdom,$cnum,$getpropath,undef,'/');
+ if (ref($sublistref) eq 'ARRAY') {
+ foreach my $line (@{$sublistref}) {
+ my ($file_name,$dom,undef,$testdir,undef,undef,undef,undef,$size,
+ undef,$mtime)=split(/\&/,$line,12);
+ unless (($testdir&$dirptr) ||
+ ($file_name =~ /^\.\.?$/)) {
+ $currsubfile{$path}{$file_name} = [$size,$mtime];
+ }
+ }
+ }
+ }
}
}
foreach my $file (keys(%{$subdependencies{$path}})) {
- if ($currsubfile{$file}) {
+ if (exists($currsubfile{$path}{$file})) {
my $item = $path.'/'.$file;
unless ($mapping{$item} eq $item) {
$pathchanges{$item} = 1;
@@ -9059,6 +9411,17 @@ sub ask_for_embedded_content {
$newfiles{$path.'/'.$file} = 1;
}
}
+ if ($actionurl eq '/adm/dependencies') {
+ foreach my $path (keys(%currsubfile)) {
+ if (ref($currsubfile{$path}) eq 'HASH') {
+ foreach my $file (keys(%{$currsubfile{$path}})) {
+ unless ($subdependencies{$path}{$file}) {
+ $unused{$path.'/'.$file} = 1;
+ }
+ }
+ }
+ }
+ }
}
my %currfile;
if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
@@ -9075,9 +9438,27 @@ sub ask_for_embedded_content {
my @dir_list = grep(!/^\./,readdir($dir));
map {$currfile{$_} = 1;} @dir_list;
}
+ } elsif ($actionurl eq '/adm/dependencies') {
+ if ($env{'request.course.id'} ne '') {
+ my ($dir) = ($fileloc =~ m{^(.+/)[^/]+$});
+ if ($dir ne '') {
+ my ($dirlistref,$listerror) =
+ &Apache::lonnet::dirlist($dir,$cdom,$cnum,$getpropath,undef,'/');
+ if (ref($dirlistref) eq 'ARRAY') {
+ foreach my $line (@{$dirlistref}) {
+ my ($file_name,$dom,undef,$testdir,undef,undef,undef,undef,
+ $size,undef,$mtime)=split(/\&/,$line,12);
+ unless (($testdir&$dirptr) ||
+ ($file_name =~ /^\.\.?$/)) {
+ $currfile{$file_name} = [$size,$mtime];
+ }
+ }
+ }
+ }
+ }
}
foreach my $file (keys(%dependencies)) {
- if ($currfile{$file}) {
+ if (exists($currfile{$file})) {
unless ($mapping{$file} eq $file) {
$pathchanges{$file} = 1;
}
@@ -9087,15 +9468,25 @@ sub ask_for_embedded_content {
$newfiles{$file} = 1;
}
}
+ foreach my $file (keys(%currfile)) {
+ unless (($file eq $filename) ||
+ ($file eq $filename.'.bak') ||
+ ($dependencies{$file})) {
+ $unused{$file} = 1;
+ }
+ }
foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) {
+ if ($actionurl eq '/adm/dependencies') {
+ next if ($embed_file =~ m{^\w+://});
+ }
$upload_output .= &start_data_table_row().
- ' '.$embed_file.'';
+ ' | '.
+ ''.$embed_file.'';
unless ($mapping{$embed_file} eq $embed_file) {
$upload_output .= ' '.&mt('changed from: [_1]',$mapping{$embed_file}).'';
}
$upload_output .= ' | ';
- if ($args->{'ignore_remote_references'}
- && $embed_file =~ m{^\w+://}) {
+ if ($args->{'ignore_remote_references'} && $embed_file =~ m{^\w+://}) {
$upload_output.=''.&mt("URL points to other server.").'';
$numremref++;
} elsif ($args->{'error_on_invalid_names'}
@@ -9104,24 +9495,84 @@ sub ask_for_embedded_content {
$upload_output.=''.&mt('Invalid characters').'';
$numinvalid++;
} else {
- $upload_output .= &embedded_file_element('upload_embedded',$num,
+ $upload_output .= &embedded_file_element('upload_embedded',$counter,
$embed_file,\%mapping,
- $allfiles,$codebase);
- $num++;
+ $allfiles,$codebase,'upload');
+ $counter ++;
+ $numnew ++;
}
$upload_output .= ' | '.&Apache::loncommon::end_data_table_row()."\n";
}
foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%existing)) {
- $upload_output .= &start_data_table_row().
- ' '.$embed_file.' | '.
- ' '.&mt('Already exists').' | '.
- &Apache::loncommon::end_data_table_row()."\n";
+ if ($actionurl eq '/adm/dependencies') {
+ my ($size,$mtime) = &get_dependency_details(\%currfile,\%currsubfile,$embed_file);
+ $modify_output .= &start_data_table_row().
+ ' '.
+ ''.
+ ' '.$embed_file.' | '.
+ ' '.$size.' | '.
+ ' '.$mtime.' | '.
+ ' '.
+ ' '.
+ &embedded_file_element('upload_embedded',$counter,
+ $embed_file,\%mapping,
+ $allfiles,$codebase,'modify').
+ ' | '.
+ &end_data_table_row()."\n";
+ $counter ++;
+ } else {
+ $upload_output .= &start_data_table_row().
+ ' '.$embed_file.' | ';
+ ' '.&mt('Already exists').' | '.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
+ }
+ my $delidx = $counter;
+ foreach my $oldfile (sort {lc($a) cmp lc($b)} keys(%unused)) {
+ my ($size,$mtime) = &get_dependency_details(\%currfile,\%currsubfile,$oldfile);
+ $delete_output .= &start_data_table_row().
+ ' '.
+ ' '.$oldfile.' | '.
+ ' '.$size.' | '.
+ ' '.$mtime.' | '.
+ ' '.
+ &embedded_file_element('upload_embedded',$delidx,
+ $oldfile,\%mapping,$allfiles,
+ $codebase,'delete').' | '.
+ &end_data_table_row()."\n";
+ $numunused ++;
+ $delidx ++;
}
if ($upload_output) {
$upload_output = &start_data_table().
$upload_output.
&end_data_table()."\n";
}
+ if ($modify_output) {
+ $modify_output = &start_data_table().
+ &start_data_table_header_row().
+ ' '.&mt('File').' | '.
+ ' '.&mt('Size (KB)').' | '.
+ ' '.&mt('Modified').' | '.
+ ' '.&mt('Upload replacement?').' | '.
+ &end_data_table_header_row().
+ $modify_output.
+ &end_data_table()."\n";
+ }
+ if ($delete_output) {
+ $delete_output = &start_data_table().
+ &start_data_table_header_row().
+ ' '.&mt('File').' | '.
+ ' '.&mt('Size (KB)').' | '.
+ ' '.&mt('Modified').' | '.
+ ' '.&mt('Delete?').' | '.
+ &end_data_table_header_row().
+ $delete_output.
+ &end_data_table()."\n";
+ }
my $applies = 0;
if ($numremref) {
$applies ++;
@@ -9132,15 +9583,37 @@ sub ask_for_embedded_content {
if ($numexisting) {
$applies ++;
}
- if ($num) {
+ if ($counter || $numunused) {
$output = ' '."\n";
+ $output .= ' '."\n".''."\n";
} elsif ($numpathchg) {
my %pathchange = ();
$output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);
@@ -9210,15 +9684,15 @@ sub ask_for_embedded_content {
$output .= ' '.&mt('or').' ';
}
}
- return ($output,$num,$numpathchg);
+ return ($output,$counter,$numpathchg);
}
sub embedded_file_element {
- my ($context,$num,$embed_file,$mapping,$allfiles,$codebase) = @_;
+ my ($context,$num,$embed_file,$mapping,$allfiles,$codebase,$type) = @_;
return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&
(ref($codebase) eq 'HASH'));
my $output;
- if ($context eq 'upload_embedded') {
+ if (($context eq 'upload_embedded') && ($type ne 'delete')) {
$output = ' '."\n";
}
$output .= ' 0) {
+ $showmtime = &Apache::lonlocal::locallocaltime($mtime);
+ }
+ }
+ return ($showsize,$showmtime);
+}
+
+sub ask_embedded_js {
+ return <<"END";
+
+
+END
+}
+
sub upload_embedded {
my ($context,$dirpath,$uname,$udom,$dir_root,$url_root,$group,$disk_quota,
$current_disk_usage,$hiddenstate,$actionurl) = @_;
@@ -9303,7 +9821,6 @@ sub upload_embedded {
$output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).' ';
next;
}
-
$env{'form.embedded_item_'.$i.'.filename'}=$fname;
if ($context eq 'portfolio') {
my $result;
@@ -9360,13 +9877,15 @@ sub upload_embedded {
if (!open($fh,'>'.$dest)) {
&Apache::lonnet::logthis('Failed to create '.$dest);
$output .= ' '.
- &mt('An error occurred while trying to upload [_1] for embedded element [_2].',$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}).
+ &mt('An error occurred while trying to upload [_1] for embedded element [_2].',
+ $orig_uploaded_filename,$env{'form.embedded_orig_'.$i}).
'';
} else {
if (!print $fh $env{'form.embedded_item_'.$i}) {
&Apache::lonnet::logthis('Failed to write to '.$dest);
$output .= ' '.
- &mt('An error occurred while writing the file [_1] for embedded element [_2].',$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}).
+ &mt('An error occurred while writing the file [_1] for embedded element [_2].',
+ $orig_uploaded_filename,$env{'form.embedded_orig_'.$i}).
'';
} else {
$output .= &mt('Uploaded [_1]',' '.
@@ -9388,15 +9907,17 @@ sub upload_embedded {
}
$output .= &modify_html_form('upload_embedded',$actionurl,$hiddenstate,\%pathchange);
$returnflag = 'ok';
- if (keys(%pathchange) > 0) {
+ my $numpathchgs = scalar(keys(%pathchange));
+ if ($numpathchgs > 0) {
if ($context eq 'portfolio') {
$output .= ''.&mt('or').' ';
} elsif ($context eq 'testbank') {
- $output .= ''.&mt('Or [_1]continue[_2] the testbank import without modifying the reference(s).','','').' ';
+ $output .= ''.&mt('Or [_1]continue[_2] the testbank import without modifying the reference(s).',
+ '','').' ';
$returnflag = 'modify_orightml';
}
}
- return ($output.$footer,$returnflag);
+ return ($output.$footer,$returnflag,$numpathchgs);
}
sub modify_html_form {
@@ -9431,7 +9952,7 @@ sub modify_html_form {
' | '.
&end_data_table_row();
- }
+ }
}
} else {
$modifyform = $pathchgtable;
@@ -9442,6 +9963,9 @@ sub modify_html_form {
}
}
if ($modifyform) {
+ if ($actionurl eq '/adm/dependencies') {
+ $hiddenstate .= '';
+ }
return ''.&mt('Changes in content of HTML file required').''."\n".
''.&mt('Changes need to be made to the reference(s) used for one or more of the dependencies, if your HTML file is to work correctly:').' '."\n".
'- '.&mt('For consistency between the reference(s) and the location of the corresponding stored file within LON-CAPA.').'
'."\n".
@@ -9470,23 +9994,55 @@ sub modify_html_refs {
$container = $env{'form.container'};
} elsif ($context eq 'coursedoc') {
$container = $env{'form.primaryurl'};
+ } elsif ($context eq 'manage_dependencies') {
+ (undef,undef,$container) = &Apache::lonnet::decode_symb($env{'form.symb'});
+ $container = "/$container";
} else {
$container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'};
}
my (%allfiles,%codebase,$output,$content);
my @changes = &get_env_multiple('form.namechange');
- return unless (@changes > 0);
- if (($context eq 'portfolio') || ($context eq 'coursedoc')) {
- return unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/});
+ unless (@changes > 0) {
+ if (wantarray) {
+ return ('',0,0);
+ } else {
+ return;
+ }
+ }
+ if (($context eq 'portfolio') || ($context eq 'coursedoc') ||
+ ($context eq 'manage_dependencies')) {
+ unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/}) {
+ if (wantarray) {
+ return ('',0,0);
+ } else {
+ return;
+ }
+ }
$content = &Apache::lonnet::getfile($container);
- return if ($content eq '-1');
+ if ($content eq '-1') {
+ if (wantarray) {
+ return ('',0,0);
+ } else {
+ return;
+ }
+ }
} else {
- return unless ($container =~ /^\Q$dir_root\E/);
+ unless ($container =~ /^\Q$dir_root\E/) {
+ if (wantarray) {
+ return ('',0,0);
+ } else {
+ return;
+ }
+ }
if (open(my $fh,"<$container")) {
$content = join('', <$fh>);
close($fh);
} else {
- return;
+ if (wantarray) {
+ return ('',0,0);
+ } else {
+ return;
+ }
}
}
my ($count,$codebasecount) = (0,0);
@@ -9520,13 +10076,14 @@ sub modify_html_refs {
}
if ($count || $codebasecount) {
my $saveresult;
- if ($context eq 'portfolio' || $context eq 'coursedoc') {
+ if (($context eq 'portfolio') || ($context eq 'coursedoc') ||
+ ($context eq 'manage_dependencies')) {
my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
if ($url eq $container) {
my ($fname) = ($container =~ m{/([^/]+)$});
$output = ''.&mt('Updated [quant,_1,reference] in [_2].',
$count,''.
- $fname.'').' ';
+ $fname.'').'';
} else {
$output = ''.
&mt('Error: update failed for: [_1].',
@@ -9553,7 +10110,11 @@ sub modify_html_refs {
' to modify references: '.$parse_result);
}
}
- return $output;
+ if (wantarray) {
+ return ($output,$count,$codebasecount);
+ } else {
+ return $output;
+ }
}
sub check_for_existing {
@@ -9709,6 +10270,1162 @@ sub check_for_traversal {
return $cleanpath;
}
+sub is_archive_file {
+ my ($mimetype) = @_;
+ if (($mimetype eq 'application/octet-stream') ||
+ ($mimetype eq 'application/x-stuffit') ||
+ ($mimetype =~ m{^application/(x\-)?(compressed|tar|zip|tgz|gz|gtar|gzip|gunzip|bz|bz2|bzip2)})) {
+ return 1;
+ }
+ return;
+}
+
+sub decompress_form {
+ my ($mimetype,$archiveurl,$action,$noextract,$hiddenelements,$dirlist) = @_;
+ my %lt = &Apache::lonlocal::texthash (
+ this => 'This file is an archive file.',
+ camt => 'This file is a Camtasia archive file.',
+ itsc => 'Its contents are as follows:',
+ youm => 'You may wish to extract its contents.',
+ extr => 'Extract contents',
+ auto => 'LON-CAPA can process the files automatically, or you can decide how each should be handled.',
+ proa => 'Process automatically?',
+ yes => 'Yes',
+ no => 'No',
+ fold => 'Title for folder containing movie',
+ movi => 'Title for page containing embedded movie',
+ );
+ my $fileloc = &Apache::lonnet::filelocation(undef,$archiveurl);
+ my ($is_camtasia,$topdir,%toplevel,@paths);
+ my $info = &list_archive_contents($fileloc,\@paths);
+ if (@paths) {
+ foreach my $path (@paths) {
+ $path =~ s{^/}{};
+ if ($path =~ m{^([^/]+)/$}) {
+ $topdir = $1;
+ }
+ if ($path =~ m{^([^/]+)/}) {
+ $toplevel{$1} = $path;
+ } else {
+ $toplevel{$path} = $path;
+ }
+ }
+ }
+ if ($mimetype =~ m{^application/(x\-)?(compressed|zip)}) {
+ my @camtasia = ("$topdir/","$topdir/index.html",
+ "$topdir/media/",
+ "$topdir/media/$topdir.mp4",
+ "$topdir/media/FirstFrame.png",
+ "$topdir/media/player.swf",
+ "$topdir/media/swfobject.js",
+ "$topdir/media/expressInstall.swf");
+ my @diffs = &compare_arrays(\@paths,\@camtasia);
+ if (@diffs == 0) {
+ $is_camtasia = 1;
+ }
+ }
+ my $output;
+ if ($is_camtasia) {
+ $output = <<"ENDCAM";
+
+ $lt{'camt'}
+ENDCAM
+ } else {
+ $output = ''.$lt{'this'};
+ if ($info eq '') {
+ $output .= ' '.$lt{'youm'}.' '."\n";
+ } else {
+ $output .= ' '.$lt{'itsc'}.''."\n".
+ '';
+ }
+ }
+ $output .= '
+$noextract
+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});
+ &Apache::lonnet::appenv({'cgi.dir' => $dir});
+ my $result = &Apache::lonnet::ssi_body('/cgi-bin/decompress.pl');
+ my ($handle) = ($env{'user.environment'} =~m{/([^/]+)\.id$});
+ my $lonidsdir = $Apache::lonnet::perlvar{'lonIDsDir'};
+ &Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle,1);
+ my $decompressed = $env{'cgi.decompressed'};
+ &Apache::lonnet::delenv('cgi.file');
+ &Apache::lonnet::delenv('cgi.dir');
+ &Apache::lonnet::delenv('cgi.decompressed');
+ return ($decompressed,$result);
+}
+
+sub process_decompression {
+ my ($docudom,$docuname,$file,$destination,$dir_root,$hiddenelem) = @_;
+ my ($dir,$error,$warning,$output);
+ if ($file !~ /\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/) {
+ $error = &mt('File name not a supported archive file type.').
+ ' '.&mt('File name should end with one of: [_1].',
+ '.zip, .tar, .bz2, .gz, .tar.gz, .tar.bz2, .tgz');
+ } else {
+ my $docuhome = &Apache::lonnet::homeserver($docuname,$docudom);
+ if ($docuhome eq 'no_host') {
+ $error = &mt('Could not determine home server for course.');
+ } else {
+ my @ids=&Apache::lonnet::current_machine_ids();
+ my $currdir = "$dir_root/$destination";
+ if (grep(/^\Q$docuhome\E$/,@ids)) {
+ $dir = &LONCAPA::propath($docudom,$docuname).
+ "$dir_root/$destination";
+ } else {
+ $dir = $Apache::lonnet::perlvar{'lonDocRoot'}.
+ "$dir_root/$docudom/$docuname/$destination";
+ unless (&Apache::lonnet::repcopy_userfile("$dir/$file") eq 'ok') {
+ $error = &mt('Archive file not found.');
+ }
+ }
+ 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);
+ 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.').
+ ' '."\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($newdirlistref) eq 'ARRAY') {
+ foreach my $dir_line (@{$newdirlistref}) {
+ my ($item,undef,undef,$testdir)=split(/\&/,$dir_line,5);
+ unless (($item =~ /^\.+$/) || ($item eq $file) ||
+ ((@to_skip > 0) && (grep(/^\Q$item\E$/,@to_skip)))) {
+ push(@newitems,$item);
+ if ($dirptr&$testdir) {
+ $is_dir{$item} = 1;
+ }
+ $changes{$item} = 1;
+ }
+ }
+ }
+ if (keys(%changes) > 0) {
+ foreach my $item (sort(@newitems)) {
+ if ($changes{$item}) {
+ push(@contents,$item);
+ }
+ }
+ }
+ if (@contents > 0) {
+ my $wantform;
+ unless ($env{'form.autoextract_camtasia'}) {
+ $wantform = 1;
+ }
+ my (%children,%parent,%dirorder,%titles);
+ my ($count,$datatable) = &get_extracted($docudom,$docuname,
+ $currdir,\%is_dir,
+ \%children,\%parent,
+ \@contents,\%dirorder,
+ \%titles,$wantform);
+ if ($datatable ne '') {
+ $output .= &archive_options_form('decompressed',$datatable,
+ $count,$hiddenelem);
+ my $startcount = 6;
+ $output .= &archive_javascript($startcount,$count,
+ \%titles,\%children);
+ }
+ if ($env{'form.autoextract_camtasia'}) {
+ my %displayed;
+ my $total = 1;
+ $env{'form.archive_directory'} = [];
+ foreach my $i (sort { $a <=> $b } keys(%dirorder)) {
+ my $path = join('/',map { $titles{$_}; } @{$dirorder{$i}});
+ $path =~ s{/$}{};
+ my $item;
+ if ($path ne '') {
+ $item = "$path/$titles{$i}";
+ } else {
+ $item = $titles{$i};
+ }
+ $env{'form.archive_content_'.$i} = "$dir_root/$destination/$item";
+ if ($item eq $contents[0]) {
+ push(@{$env{'form.archive_directory'}},$i);
+ $env{'form.archive_'.$i} = 'display';
+ $env{'form.archive_title_'.$i} = $env{'form.camtasia_foldername'};
+ $displayed{'folder'} = $i;
+ } elsif ($item eq "$contents[0]/index.html") {
+ $env{'form.archive_'.$i} = 'display';
+ $env{'form.archive_title_'.$i} = $env{'form.camtasia_moviename'};
+ $displayed{'web'} = $i;
+ } else {
+ if ($item eq "$contents[0]/media") {
+ push(@{$env{'form.archive_directory'}},$i);
+ }
+ $env{'form.archive_'.$i} = 'dependency';
+ }
+ $total ++;
+ }
+ for (my $i=1; $i<$total; $i++) {
+ next if ($i == $displayed{'web'});
+ next if ($i == $displayed{'folder'});
+ $env{'form.archive_dependent_on_'.$i} = $displayed{'web'};
+ }
+ $env{'form.phase'} = 'decompress_cleanup';
+ $env{'form.archivedelete'} = 1;
+ $env{'form.archive_count'} = $total-1;
+ $output .=
+ &process_extracted_files('coursedocs',$docudom,
+ $docuname,$destination,
+ $dir_root,$hiddenelem);
+ }
+ } else {
+ $warning = &mt('No new items extracted from archive file.');
+ }
+ } else {
+ $output = $display;
+ $error = &mt('An error occurred during extraction from the archive file.');
+ }
+ }
+ }
+ }
+ if ($error) {
+ $output .= ''.&mt('Not extracted.').' '.
+ $error.' '."\n";
+ }
+ if ($warning) {
+ $output .= ''.$warning.' '."\n";
+ }
+ return $output;
+}
+
+sub get_extracted {
+ my ($docudom,$docuname,$currdir,$is_dir,$children,$parent,$contents,$dirorder,
+ $titles,$wantform) = @_;
+ my $count = 0;
+ my $depth = 0;
+ my $datatable;
+ my @hierarchy;
+ return unless ((ref($is_dir) eq 'HASH') && (ref($children) eq 'HASH') &&
+ (ref($parent) eq 'HASH') && (ref($contents) eq 'ARRAY') &&
+ (ref($dirorder) eq 'HASH') && (ref($titles) eq 'HASH'));
+ foreach my $item (@{$contents}) {
+ $count ++;
+ @{$dirorder->{$count}} = @hierarchy;
+ $titles->{$count} = $item;
+ &archive_hierarchy($depth,$count,$parent,$children);
+ if ($wantform) {
+ $datatable .= &archive_row($is_dir->{$item},$item,
+ $currdir,$depth,$count);
+ }
+ if ($is_dir->{$item}) {
+ $depth ++;
+ push(@hierarchy,$count);
+ $parent->{$depth} = $count;
+ $datatable .=
+ &recurse_extracted_archive("$currdir/$item",$docudom,$docuname,
+ \$depth,\$count,\@hierarchy,$dirorder,
+ $children,$parent,$titles,$wantform);
+ $depth --;
+ pop(@hierarchy);
+ }
+ }
+ return ($count,$datatable);
+}
+
+sub recurse_extracted_archive {
+ my ($currdir,$docudom,$docuname,$depth,$count,$hierarchy,$dirorder,
+ $children,$parent,$titles,$wantform) = @_;
+ my $result='';
+ unless ((ref($depth)) && (ref($count)) && (ref($hierarchy) eq 'ARRAY') &&
+ (ref($children) eq 'HASH') && (ref($parent) eq 'HASH') &&
+ (ref($dirorder) eq 'HASH')) {
+ return $result;
+ }
+ my $dirptr = 16384;
+ my ($newdirlistref,$newlisterror) =
+ &Apache::lonnet::dirlist($currdir,$docudom,$docuname,1);
+ if (ref($newdirlistref) eq 'ARRAY') {
+ foreach my $dir_line (@{$newdirlistref}) {
+ my ($item,undef,undef,$testdir)=split(/\&/,$dir_line,5);
+ unless ($item =~ /^\.+$/) {
+ $$count ++;
+ @{$dirorder->{$$count}} = @{$hierarchy};
+ $titles->{$$count} = $item;
+ &archive_hierarchy($$depth,$$count,$parent,$children);
+
+ my $is_dir;
+ if ($dirptr&$testdir) {
+ $is_dir = 1;
+ }
+ if ($wantform) {
+ $result .= &archive_row($is_dir,$item,$currdir,$$depth,$$count);
+ }
+ if ($is_dir) {
+ $$depth ++;
+ push(@{$hierarchy},$$count);
+ $parent->{$$depth} = $$count;
+ $result .=
+ &recurse_extracted_archive("$currdir/$item",$docudom,
+ $docuname,$depth,$count,
+ $hierarchy,$dirorder,$children,
+ $parent,$titles,$wantform);
+ $$depth --;
+ pop(@{$hierarchy});
+ }
+ }
+ }
+ }
+ return $result;
+}
+
+sub archive_hierarchy {
+ my ($depth,$count,$parent,$children) =@_;
+ if ((ref($parent) eq 'HASH') && (ref($children) eq 'HASH')) {
+ if (exists($parent->{$depth})) {
+ $children->{$parent->{$depth}} .= $count.':';
+ }
+ }
+ return;
+}
+
+sub archive_row {
+ my ($is_dir,$item,$currdir,$depth,$count) = @_;
+ my ($name) = ($item =~ m{([^/]+)$});
+ my %choices = &Apache::lonlocal::texthash (
+ 'display' => 'Add as file',
+ 'dependency' => 'Include as dependency',
+ 'discard' => 'Discard',
+ );
+ if ($is_dir) {
+ $choices{'display'} = &mt('Add as folder');
+ }
+ my $output = &start_data_table_row().''.$count.' | '."\n";
+ my $offset = 0;
+ foreach my $action ('display','dependency','discard') {
+ $offset ++;
+ if ($action ne 'display') {
+ $offset ++;
+ }
+ $output .= ''.
+ '';
+ if ($action eq 'dependency') {
+ $output .= ' '."\n".
+ &mt('Used by:').' '."\n".
+ ' ';
+ } elsif ($action eq 'display') {
+ $output .= ''."\n".
+ &mt('Title:').' '."\n".
+ ' ';
+ }
+ $output .= ' | ';
+ }
+ $output .= '&').'" />'.(' ' x 2);
+ for (my $i=0; $i<$depth; $i++) {
+ $output .= ('' x2)."\n";
+ }
+ if ($is_dir) {
+ $output .= ' '."\n".
+ ''."\n";
+ } else {
+ $output .= ''."\n";
+ }
+ $output .= ' '.$name.' | '."\n".
+ &end_data_table_row();
+ return $output;
+}
+
+sub archive_options_form {
+ my ($form,$display,$count,$hiddenelem) = @_;
+ my %lt = &Apache::lonlocal::texthash(
+ perm => 'Permanently remove archive file?',
+ hows => 'How should each extracted item be incorporated in the course?',
+ cont => 'Content actions for all',
+ addf => 'Add as folder/file',
+ incd => 'Include as dependency for a displayed file',
+ disc => 'Discard',
+ no => 'No',
+ yes => 'Yes',
+ save => 'Save',
+ );
+ my $output = <<"END";
+';
+}
+
+sub archive_javascript {
+ my ($startcount,$numitems,$titles,$children) = @_;
+ return unless ((ref($titles) eq 'HASH') && (ref($children) eq 'HASH'));
+ my $maintitle = $env{'form.comment'};
+ my $scripttag = <
+// 0) {
+ var startelement = $startcount + ((count-1) * 7);
+ for (var j=1; j<6; j++) {
+ if ((j != 2) && (j != 4)) {
+ var item = startelement + j;
+ if (form.elements[item].type == 'radio') {
+ if (form.elements[item].checked) {
+ containerCheck(form,count,j);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+numitems = $numitems
+var titles = new Array(numitems);
+var parents = new Array(numitems);
+for (var i=0; i $b } (keys(%{$children}))) {
+ my @contents = split(/:/,$children->{$container});
+ for (my $i=0; $i<@contents; $i ++) {
+ $scripttag .= 'parents['.$container.']['.$i.'] = '.$contents[$i]."\n";
+ }
+ }
+
+ foreach my $key (sort { $a <=> $b } (keys(%{$titles}))) {
+ $scripttag .= "titles[$key] = '".$titles->{$key}."';\n";
+ }
+
+ $scripttag .= < 0) {
+ dependencyCheck(form,count,offset);
+ var item = (offset+$startcount)+7*(count-1);
+ form.elements[item].checked = true;
+ if(Object.prototype.toString.call(parents[count]) === '[object Array]') {
+ if (parents[count].length > 0) {
+ for (var j=0; j 0) {
+ var chosen = (offset+$startcount)+7*(count-1);
+ var depitem = $startcount + ((count-1) * 7) + 4;
+ var currtype = form.elements[depitem].type;
+ if (form.elements[chosen].value == 'dependency') {
+ document.getElementById('arc_depon_'+count).style.display='block';
+ form.elements[depitem].options.length = 0;
+ form.elements[depitem].options[0] = new Option('Select','',true,true);
+ for (var i=1; i 0) {
+ var item = (1+offset+$startcount)+7*(count-1);
+ var picked = form.elements[item].options[form.elements[item].selectedIndex].value;
+ if (Object.prototype.toString.call(parents[count]) === '[object Array]') {
+ if (parents[count].length > 0) {
+ for (var j=0; j 0) {
+ var item = (offset+$startcount)+7*(count-1);
+ if (form.elements[item].type == 'radio') {
+ if (form.elements[item].value == 'dependency') {
+ if (form.elements[item+1].type == 'select-one') {
+ for (var i=0; i 0) {
+ for (var j=0; j 0) {
+ var chosen = (offset+$startcount)+7*(count-1);
+ var depitem = $startcount + ((count-1) * 7) + 2;
+ var currtype = form.elements[depitem].type;
+ if (form.elements[chosen].value == 'display') {
+ document.getElementById('arc_title_'+count).style.display='block';
+ if ((count==1) && ((parents[count].length > 0) || (numitems == 1))) {
+ document.getElementById('archive_title_'+count).value=maintitle;
+ }
+ } else {
+ document.getElementById('arc_title_'+count).style.display='none';
+ if (currtype == 'text') {
+ document.getElementById('archive_title_'+count).value='';
+ }
+ }
+ }
+ return;
+}
+
+// ]]>
+
+END
+ return $scripttag;
+}
+
+sub process_extracted_files {
+ my ($context,$docudom,$docuname,$destination,$dir_root,$hiddenelem) = @_;
+ my $numitems = $env{'form.archive_count'};
+ return unless ($numitems);
+ my @ids=&Apache::lonnet::current_machine_ids();
+ my ($prefix,$pathtocheck,$dir,$ishome,$error,$warning,%toplevelitems,%is_dir,
+ %folders,%containers,%mapinner,%prompttofetch);
+ my $docuhome = &Apache::lonnet::homeserver($docuname,$docudom);
+ if (grep(/^\Q$docuhome\E$/,@ids)) {
+ $prefix = &LONCAPA::propath($docudom,$docuname);
+ $pathtocheck = "$dir_root/$destination";
+ $dir = $dir_root;
+ $ishome = 1;
+ } else {
+ $prefix = $Apache::lonnet::perlvar{'lonDocRoot'};
+ $pathtocheck = "$dir_root/$docudom/$docuname/$destination";
+ $dir = "$dir_root/$docudom/$docuname";
+ }
+ my $currdir = "$dir_root/$destination";
+ (my $docstype,$mapinner{'0'}) = ($destination =~ m{^(docs|supplemental)/(\w+)/});
+ if ($env{'form.folderpath'}) {
+ my @items = split('&',$env{'form.folderpath'});
+ $folders{'0'} = $items[-2];
+ $containers{'0'}='sequence';
+ } elsif ($env{'form.pagepath'}) {
+ my @items = split('&',$env{'form.pagepath'});
+ $folders{'0'} = $items[-2];
+ $containers{'0'}='page';
+ }
+ my @archdirs = &get_env_multiple('form.archive_directory');
+ if ($numitems) {
+ for (my $i=1; $i<=$numitems; $i++) {
+ my $path = $env{'form.archive_content_'.$i};
+ if ($path =~ m{^\Q$pathtocheck\E/([^/]+)$}) {
+ my $item = $1;
+ $toplevelitems{$item} = $i;
+ if (grep(/^\Q$i\E$/,@archdirs)) {
+ $is_dir{$item} = 1;
+ }
+ }
+ }
+ }
+ my ($output,%children,%parent,%titles,%dirorder,$result);
+ if (keys(%toplevelitems) > 0) {
+ my @contents = sort(keys(%toplevelitems));
+ (my $count,undef) = &get_extracted($docudom,$docuname,$currdir,\%is_dir,\%children,
+ \%parent,\@contents,\%dirorder,\%titles);
+ }
+ my (%referrer,%orphaned,%todelete,%todeletedir,%newdest,%newseqid);
+ if ($numitems) {
+ for (my $i=1; $i<=$numitems; $i++) {
+ my $path = $env{'form.archive_content_'.$i};
+ if ($path =~ /^\Q$pathtocheck\E/) {
+ if ($env{'form.archive_'.$i} eq 'discard') {
+ if ($prefix ne '' && $path ne '') {
+ if (-e $prefix.$path) {
+ if ((@archdirs > 0) &&
+ (grep(/^\Q$i\E$/,@archdirs))) {
+ $todeletedir{$prefix.$path} = 1;
+ } else {
+ $todelete{$prefix.$path} = 1;
+ }
+ }
+ }
+ } elsif ($env{'form.archive_'.$i} eq 'display') {
+ my ($docstitle,$title,$url,$outer);
+ ($title) = ($path =~ m{/([^/]+)$});
+ $docstitle = $env{'form.archive_title_'.$i};
+ if ($docstitle eq '') {
+ $docstitle = $title;
+ }
+ $outer = 0;
+ if (ref($dirorder{$i}) eq 'ARRAY') {
+ if (@{$dirorder{$i}} > 0) {
+ foreach my $item (reverse(@{$dirorder{$i}})) {
+ if ($env{'form.archive_'.$item} eq 'display') {
+ $outer = $item;
+ last;
+ }
+ }
+ }
+ }
+ my ($errtext,$fatal) =
+ &LONCAPA::map::mapread('/uploaded/'.$docudom.'/'.$docuname.
+ '/'.$folders{$outer}.'.'.
+ $containers{$outer});
+ next if ($fatal);
+ if ((@archdirs > 0) && (grep(/^\Q$i\E$/,@archdirs))) {
+ if ($context eq 'coursedocs') {
+ $mapinner{$i} = time;
+ $folders{$i} = 'default_'.$mapinner{$i};
+ $containers{$i} = 'sequence';
+ my $url = '/uploaded/'.$docudom.'/'.$docuname.'/'.
+ $folders{$i}.'.'.$containers{$i};
+ my $newidx = &LONCAPA::map::getresidx();
+ $LONCAPA::map::resources[$newidx]=
+ $docstitle.':'.$url.':false:normal:res';
+ push(@LONCAPA::map::order,$newidx);
+ my ($outtext,$errtext) =
+ &LONCAPA::map::storemap('/uploaded/'.$docudom.'/'.
+ $docuname.'/'.$folders{$outer}.
+ '.'.$containers{$outer},1);
+ $newseqid{$i} = $newidx;
+ unless ($errtext) {
+ $result .= ''.&mt('Folder: [_1] added to course',$docstitle).''."\n";
+ }
+ }
+ } else {
+ if ($context eq 'coursedocs') {
+ my $newidx=&LONCAPA::map::getresidx();
+ my $url = '/uploaded/'.$docudom.'/'.$docuname.'/'.
+ $docstype.'/'.$mapinner{$outer}.'/'.$newidx.'/'.
+ $title;
+ if (!-e "$prefix$dir/$docstype/$mapinner{$outer}") {
+ mkdir("$prefix$dir/$docstype/$mapinner{$outer}",0755);
+ }
+ if (!-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx") {
+ mkdir("$prefix$dir/$docstype/$mapinner{$outer}/$newidx");
+ }
+ if (-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx") {
+ system("mv $prefix$path $prefix$dir/$docstype/$mapinner{$outer}/$newidx/$title");
+ $newdest{$i} = "$prefix$dir/$docstype/$mapinner{$outer}/$newidx";
+ unless ($ishome) {
+ my $fetch = "$newdest{$i}/$title";
+ $fetch =~ s/^\Q$prefix$dir\E//;
+ $prompttofetch{$fetch} = 1;
+ }
+ }
+ $LONCAPA::map::resources[$newidx]=
+ $docstitle.':'.$url.':false:normal:res';
+ push(@LONCAPA::map::order, $newidx);
+ my ($outtext,$errtext)=
+ &LONCAPA::map::storemap('/uploaded/'.$docudom.'/'.
+ $docuname.'/'.$folders{$outer}.
+ '.'.$containers{$outer},1);
+ unless ($errtext) {
+ if (-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx/$title") {
+ $result .= ''.&mt('File: [_1] added to course',$docstitle).''."\n";
+ }
+ }
+ }
+ }
+ } elsif ($env{'form.archive_'.$i} eq 'dependency') {
+ my ($title) = ($path =~ m{/([^/]+)$});
+ $referrer{$i} = $env{'form.archive_dependent_on_'.$i};
+ if ($env{'form.archive_'.$referrer{$i}} eq 'display') {
+ if (ref($dirorder{$i}) eq 'ARRAY') {
+ my ($itemidx,$fullpath,$relpath);
+ for (my $j=0; $j<@{$dirorder{$i}}; $j++) {
+ if (ref($dirorder{$referrer{$i}}) eq 'ARRAY') {
+ my $container = $dirorder{$referrer{$i}}->[-1];
+ for (my $j=0; $j<@{$dirorder{$i}}; $j++) {
+ if ($dirorder{$i}->[$j] eq $container) {
+ $itemidx = $j;
+ }
+ }
+ }
+ }
+ if ($itemidx ne '') {
+ if (grep(/^\Q$referrer{$i}\E$/,@archdirs)) {
+ if ($mapinner{$referrer{$i}}) {
+ $fullpath = "$prefix$dir/$docstype/$mapinner{$referrer{$i}}";
+ for (my $j=$itemidx; $j<@{$dirorder{$i}}; $j++) {
+ if (grep(/^\Q$dirorder{$i}->[$j]\E$/,@archdirs)) {
+ unless (defined($newseqid{$dirorder{$i}->[$j]})) {
+ $fullpath .= '/'.$titles{$dirorder{$i}->[$j]};
+ $relpath .= '/'.$titles{$dirorder{$i}->[$j]};
+ if (!-e $fullpath) {
+ mkdir($fullpath,0755);
+ }
+ }
+ } else {
+ last;
+ }
+ }
+ }
+ } elsif ($newdest{$referrer{$i}}) {
+ $fullpath = $newdest{$referrer{$i}};
+ for (my $j=$itemidx; $j<@{$dirorder{$i}}; $j++) {
+ if ($env{'form.archive_'.$dirorder{$i}->[$j]} eq 'discard') {
+ $orphaned{$i} = $env{'form.archive_'.$dirorder{$i}->[$j]};
+ last;
+ } elsif (grep(/^\Q$dirorder{$i}->[$j]\E$/,@archdirs)) {
+ unless (defined($newseqid{$dirorder{$i}->[$j]})) {
+ $fullpath .= '/'.$titles{$dirorder{$i}->[$j]};
+ $relpath .= '/'.$titles{$dirorder{$i}->[$j]};
+ if (!-e $fullpath) {
+ mkdir($fullpath,0755);
+ }
+ }
+ } else {
+ last;
+ }
+ }
+ }
+ if ($fullpath ne '') {
+ if (-e "$prefix$path") {
+ system("mv $prefix$path $fullpath/$title");
+ }
+ if (-e "$fullpath/$title") {
+ my $showpath;
+ if ($relpath ne '') {
+ $showpath = "$relpath/$title";
+ } else {
+ $showpath = "/$title";
+ }
+ $result .= ''.&mt('[_1] included as a dependency',$showpath).''."\n";
+ }
+ unless ($ishome) {
+ my $fetch = "$fullpath/$title";
+ $fetch =~ s/^\Q$prefix$dir\E//;
+ $prompttofetch{$fetch} = 1;
+ }
+ }
+ }
+ }
+ } elsif ($env{'form.archive_'.$referrer{$i}} eq 'discard') {
+ $warning .= &mt('[_1] is a dependency of [_2], which was discarded.',
+ $path,$env{'form.archive_content_'.$referrer{$i}}).' ';
+ }
+ }
+ } else {
+ $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).' ';
+ }
+ }
+ if (keys(%todelete)) {
+ foreach my $key (keys(%todelete)) {
+ unlink($key);
+ }
+ }
+ if (keys(%todeletedir)) {
+ foreach my $key (keys(%todeletedir)) {
+ rmdir($key);
+ }
+ }
+ foreach my $dir (sort(keys(%is_dir))) {
+ if (($pathtocheck ne '') && ($dir ne '')) {
+ &cleanup_empty_dirs($prefix."$pathtocheck/$dir");
+ }
+ }
+ if ($result ne '') {
+ $output .= ''."\n".
+ $result."\n".
+ ' ';
+ }
+ unless ($ishome) {
+ my $replicationfail;
+ foreach my $item (keys(%prompttofetch)) {
+ my $fetchresult= &Apache::lonnet::reply('fetchuserfile:'.$item,$docuhome);
+ unless ($fetchresult eq 'ok') {
+ $replicationfail .= ''.$item.''."\n";
+ }
+ }
+ if ($replicationfail) {
+ $output .= ''.
+ &mt('Course home server failed to retrieve:').' '.
+ $replicationfail.
+ ' ';
+ }
+ }
+ } else {
+ $warning = &mt('No items found in archive.');
+ }
+ if ($error) {
+ $output .= ''.&mt('Not extracted.').' '.
+ $error.' '."\n";
+ }
+ if ($warning) {
+ $output .= ''.$warning.' '."\n";
+ }
+ return $output;
+}
+
+sub cleanup_empty_dirs {
+ my ($path) = @_;
+ if (($path ne '') && (-d $path)) {
+ if (opendir(my $dirh,$path)) {
+ my @dircontents = grep(!/^\./,readdir($dirh));
+ my $numitems = 0;
+ foreach my $item (@dircontents) {
+ if (-d "$path/$item") {
+ &recurse_dirs("$path/$item");
+ if (-e "$path/$item") {
+ $numitems ++;
+ }
+ } else {
+ $numitems ++;
+ }
+ }
+ if ($numitems == 0) {
+ rmdir($path);
+ }
+ closedir($dirh);
+ }
+ }
+ return;
+}
+
+=pod
+
+=item &get_folder_hierarchy()
+
+Provides hierarchy of names of folders/sub-folders containing the current
+item,
+
+Inputs: 3
+ - $navmap - navmaps object
+
+ - $map - url for map (either the trigger itself, or map containing
+ the resource, which is the trigger).
+
+ - $showitem - 1 => show title for map itself; 0 => do not show.
+
+Outputs: 1 @pathitems - array of folder/subfolder names.
+
+=cut
+
+sub get_folder_hierarchy {
+ my ($navmap,$map,$showitem) = @_;
+ my @pathitems;
+ if (ref($navmap)) {
+ my $mapres = $navmap->getResourceByUrl($map);
+ if (ref($mapres)) {
+ my $pcslist = $mapres->map_hierarchy();
+ if ($pcslist ne '') {
+ my @pcs = split(/,/,$pcslist);
+ foreach my $pc (@pcs) {
+ if ($pc == 1) {
+ push(@pathitems,&mt('Main Course Documents'));
+ } else {
+ my $res = $navmap->getByMapPc($pc);
+ if (ref($res)) {
+ my $title = $res->compTitle();
+ $title =~ s/\W+/_/g;
+ if ($title ne '') {
+ push(@pathitems,$title);
+ }
+ }
+ }
+ }
+ }
+ if ($showitem) {
+ if ($mapres->{ID} eq '0.0') {
+ push(@pathitems,&mt('Main Course Documents'));
+ } else {
+ my $maptitle = $mapres->compTitle();
+ $maptitle =~ s/\W+/_/g;
+ if ($maptitle ne '') {
+ push(@pathitems,$maptitle);
+ }
+ }
+ }
+ }
+ }
+ return @pathitems;
+}
+
=pod
=item * &get_turnedin_filepath()
@@ -11854,7 +13571,7 @@ sub init_user_environment {
# See if old ID present, if so, remove
- my ($filename,$cookie,$userroles);
+ my ($filename,$cookie,$userroles,$firstaccenv,$timerintenv);
my $now=time;
if ($public) {
@@ -11892,7 +13609,8 @@ sub init_user_environment {
# Initialize roles
- $userroles=&Apache::lonnet::rolesinit($domain,$username,$authhost);
+ ($userroles,$firstaccenv,$timerintenv) =
+ &Apache::lonnet::rolesinit($domain,$username,$authhost);
}
# ------------------------------------ Check browser type and MathML capability
@@ -11967,12 +13685,18 @@ sub init_user_environment {
}
$env{'user.environment'} = "$lonids/$cookie.id";
-
+
if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id",
&GDBM_WRCREAT(),0640)) {
&_add_to_env(\%disk_env,\%initial_env);
&_add_to_env(\%disk_env,\%userenv,'environment.');
&_add_to_env(\%disk_env,$userroles);
+ if (ref($firstaccenv) eq 'HASH') {
+ &_add_to_env(\%disk_env,$firstaccenv);
+ }
+ if (ref($timerintenv) eq 'HASH') {
+ &_add_to_env(\%disk_env,$timerintenv);
+ }
if (ref($args->{'extra_env'})) {
&_add_to_env(\%disk_env,$args->{'extra_env'});
}
@@ -12008,7 +13732,9 @@ sub get_symb {
my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url)));
if ($symb eq '') {
if (!$silent) {
- $request->print("Unable to handle ambiguous references:$url:.");
+ if (ref($request)) {
+ $request->print("Unable to handle ambiguous references:$url:.");
+ }
return ();
}
}
|