--- loncom/interface/loncommon.pm 2011/01/12 04:58:54 1.948.2.24
+++ loncom/interface/loncommon.pm 2012/04/11 15:53:22 1.1070
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.948.2.24 2011/01/12 04:58:54 raeburn Exp $
+# $Id: loncommon.pm,v 1.1070 2012/04/11 15:53:22 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -154,6 +154,8 @@ sub ssi_with_retries {
# ----------------------------------------------- Filetypes/Languages/Copyright
my %language;
my %supported_language;
+my %latex_language; # For choosing hyphenation in
+my %latex_language_bykey; # for choosing hyphenation from metadata
my %cprtag;
my %scprtag;
my %fe; my %fd; my %fm;
@@ -186,11 +188,15 @@ BEGIN {
while (my $line = <$fh>) {
next if ($line=~/^\#/);
chomp($line);
- my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$line));
+ my ($key,$two,$country,$three,$enc,$val,$sup,$latex)=(split(/\t/,$line));
$language{$key}=$val.' - '.$enc;
if ($sup) {
$supported_language{$key}=$sup;
}
+ if ($latex) {
+ $latex_language_bykey{$key} = $latex;
+ $latex_language{$two} = $latex;
+ }
}
close($fh);
}
@@ -409,7 +415,7 @@ sub studentbrowser_javascript {
+ENDRESBRW
+}
+
sub selectstudent_link {
- my ($form,$unameele,$udomele,$courseadvonly)=@_;
- my $callargs = "'".$form."','".$unameele."','".$udomele."'";
+ my ($form,$unameele,$udomele,$courseadvonly,$clickerid)=@_;
+ my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','".
+ &Apache::lonhtmlcommon::entity_encode($unameele)."','".
+ &Apache::lonhtmlcommon::entity_encode($udomele)."'";
if ($env{'request.course.id'}) {
if (!&Apache::lonnet::allowed('srm',$env{'request.course.id'})
&& !&Apache::lonnet::allowed('srm',$env{'request.course.id'}.
'/'.$env{'request.course.sec'})) {
return '';
}
+ $callargs.=",'".&Apache::lonhtmlcommon::entity_encode($clickerid)."'";
if ($courseadvonly) {
$callargs .= ",'',1,1";
}
@@ -452,7 +481,7 @@ sub selectstudent_link {
&mt('Select User').'';
}
if ($env{'request.role'}=~/^(au|dc|su)/) {
- $callargs .= ",1";
+ $callargs .= ",'',1";
return ''.
''.
&mt('Select User').'';
@@ -460,6 +489,19 @@ sub selectstudent_link {
return '';
}
+sub selectresource_link {
+ my ($form,$reslink,$arg)=@_;
+
+ my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','".
+ &Apache::lonhtmlcommon::entity_encode($reslink)."'";
+ unless ($env{'request.course.id'}) { return $arg; }
+ return ''.
+ ''.
+ $arg.'';
+}
+
+
+
sub authorbrowser_javascript {
return <<"ENDAUTHORBRW";
+
+ENDJS
+
+}
+
sub userbrowser_javascript {
my $id_functions = &javascript_index_functions();
return <<"ENDUSERBRW";
@@ -766,6 +853,9 @@ sub selectcourse_link {
} elsif ($selecttype eq 'Course/Community') {
$linktext = &mt('Select Course/Community');
$type = '';
+ } elsif ($selecttype eq 'Select') {
+ $linktext = &mt('Select');
+ $type = '';
}
return ''
."'
.'';
- if ($text ne "") {
+ if ($text ne "") {
$template.='';
}
return $template;
@@ -1142,27 +1238,22 @@ sub help_open_topic {
# This is a quicky function for Latex cheatsheet editing, since it
# appears in at least four places
sub helpLatexCheatsheet {
- my ($topic,$text,$not_author) = @_;
+ my ($topic,$text,$not_author,$stayOnPage) = @_;
my $out;
my $addOther = '';
if ($topic) {
- $addOther = ''.&Apache::loncommon::help_open_topic($topic,&mt($text),
- undef, undef, 600).
- ' ';
+ $addOther = ''.&help_open_topic($topic,&mt($text),$stayOnPage, undef, 600).' ';
}
$out = '' # Start cheatsheet
.$addOther
.''
- .&Apache::loncommon::help_open_topic('Greek_Symbols',&mt('Greek Symbols'),
- undef,undef,600)
+ .&help_open_topic('Greek_Symbols',&mt('Greek Symbols'),$stayOnPage,undef,600)
.' '
- .&Apache::loncommon::help_open_topic('Other_Symbols',&mt('Other Symbols'),
- undef,undef,600)
+ .&help_open_topic('Other_Symbols',&mt('Other Symbols'),$stayOnPage,undef,600)
.'';
unless ($not_author) {
$out .= ' '
- .&Apache::loncommon::help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),
- undef,undef,600)
+ .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600)
.'';
}
$out .= ''; # End cheatsheet
@@ -1205,12 +1296,7 @@ ENDOUTPUT
sub help_open_menu {
my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text)
= @_;
- $stayOnPage = 0 if (not defined $stayOnPage);
- # only use pop-up help (stayOnPage == 0)
- # if environment.remote is on (using remote control UI)
- if ($env{'environment.remote'} eq 'off' ) {
- $stayOnPage=1;
- }
+ $stayOnPage = 1;
my $output;
if ($component_help) {
if (!$text) {
@@ -1231,8 +1317,8 @@ sub help_open_menu {
sub top_nav_help {
my ($text) = @_;
$text = &mt($text);
- my $stay_on_page =
- ($env{'environment.remote'} eq 'off' );
+ my $stay_on_page = 1;
+
my $link = ($stay_on_page) ? "javascript:helpMenu('display')"
: "javascript:helpMenu('open')";
my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);
@@ -1247,10 +1333,7 @@ END
sub help_menu_js {
my ($text) = @_;
-
- my $stayOnPage =
- ($env{'environment.remote'} eq 'off' );
-
+ my $stayOnPage = 1;
my $width = 620;
my $height = 600;
my $helptopic=&general_help();
@@ -1307,10 +1390,7 @@ sub help_open_bug {
unless ($env{'user.adv'}) { return ''; }
unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; }
$text = "" if (not defined $text);
- $stayOnPage = 0 if (not defined $stayOnPage);
- if ($env{'environment.remote'} eq 'off' ) {
$stayOnPage=1;
- }
$width = 600 if (not defined $width);
$height = 600 if (not defined $height);
@@ -1351,10 +1431,7 @@ sub help_open_faq {
unless ($env{'user.adv'}) { return ''; }
unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; }
$text = "" if (not defined $text);
- $stayOnPage = 0 if (not defined $stayOnPage);
- if ($env{'environment.remote'} eq 'off' ) {
$stayOnPage=1;
- }
$width = 350 if (not defined $width);
$height = 400 if (not defined $height);
@@ -1671,6 +1748,7 @@ Inputs: $workbook
Returns: $format, a hash reference.
+
=cut
###############################################################
@@ -1732,7 +1810,7 @@ sub create_workbook {
return (undef);
}
#
- $workbook->set_tempdir('/home/httpd/perl/tmp');
+ $workbook->set_tempdir(LONCAPA::tempdir());
#
my $format = &Apache::loncommon::define_excel_formats($workbook);
return ($workbook,$filename,$format);
@@ -1870,7 +1948,7 @@ sub multiple_select_form {
Returns a string containing a
+ENDPROGBAR
+ &r_print($r,$content.&LCprogressbar_script($LCcurrentid));
+}
+
+sub LCprogressbarUpdate {
+ my ($r,$val,$text)=@_;
+ unless ($val) {
+ if ($LClastpercent) {
+ $val=$LClastpercent;
+ } else {
+ $val=0;
+ }
+ }
+ if ($val<0) { $val=0; }
+ if ($val>100) { $val=0; }
+ $LClastpercent=$val;
+ unless ($text) { $text=$val.'%'; }
+ $text=&js_ready($text);
+ &r_print($r,<
+//
+
+ENDUPDATE
+}
+
+sub LCprogressbarClose {
+ my ($r)=@_;
+ $LClastpercent=0;
+ &r_print($r,<
+//
+
+ENDCLOSE
+}
+
+sub r_print {
+ my ($r,$to_print)=@_;
+ if ($r) {
+ $r->print($to_print);
+ $r->rflush();
+ } else {
+ print($to_print);
+ }
+}
+
sub html_encode {
my ($result) = @_;
@@ -6993,6 +7519,7 @@ sub html_encode {
return $result;
}
+
sub js_ready {
my ($result) = @_;
@@ -7029,6 +7556,24 @@ sub validate_page {
}
}
+
+sub start_scrollbox {
+ my ($outerwidth,$width,$height,$id)=@_;
+ unless ($outerwidth) { $outerwidth='520px'; }
+ unless ($width) { $width='500px'; }
+ unless ($height) { $height='200px'; }
+ my ($table_id,$div_id);
+ if ($id ne '') {
+ $table_id = " id='table_$id'";
+ $div_id = " id='div_$id'";
+ }
+ return "";
+}
+
+sub end_scrollbox {
+ return ' |
';
+}
+
sub simple_error_page {
my ($r,$title,$msg) = @_;
my $page =
@@ -7056,30 +7601,36 @@ sub simple_error_page {
}
sub start_data_table {
- my ($add_class) = @_;
+ my ($add_class,$id) = @_;
my $css_class = (join(' ','LC_data_table',$add_class));
- &start_data_table_count();
- return ''."\n";
+ my $table_id;
+ if (defined($id)) {
+ $table_id = ' id="'.$id.'"';
+ }
+ &start_data_table_count();
+ return ''."\n";
}
sub end_data_table {
- &end_data_table_count();
+ &end_data_table_count();
return '
'."\n";;
}
sub start_data_table_row {
- my ($add_class) = @_;
+ my ($add_class, $id) = @_;
$row_count[0]++;
my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
- return ''."\n";;
+ $id = (' id="'.$id.'"') unless ($id eq '');
+ return '
'."\n";
}
sub continue_data_table_row {
- my ($add_class) = @_;
+ my ($add_class, $id) = @_;
my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
- $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');;
- return '
'."\n";;
+ $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+ $id = (' id="'.$id.'"') unless ($id eq '');
+ return '
'."\n";
}
sub end_data_table_row {
@@ -7184,7 +7735,7 @@ sub get_users_function {
$function='admin';
}
if (($env{'request.role'}=~/^(au|ca|aa)/) ||
- ($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {
+ ($ENV{'REQUEST_URI'}=~ m{/^(/priv)})) {
$function='author';
}
return $function;
@@ -7919,7 +8470,7 @@ sub user_picker {
my ($newuserscript,$new_user_create);
my $context_dom = $env{'request.role.domain'};
if ($context eq 'requestcrs') {
- if ($env{'form.coursedom'} ne '') {
+ if ($env{'form.coursedom'} ne '') {
$context_dom = $env{'form.coursedom'};
}
}
@@ -8299,7 +8850,8 @@ sub get_standard_codeitems {
=item * sorted_slots()
-Sorts an array of slot names in order of slot start time (earliest first).
+Sorts an array of slot names in order of an optional sort key,
+default sort is by slot start time (earliest first).
Inputs:
@@ -8309,15 +8861,16 @@ slotsarr - Reference to array of unsort
slots - Reference to hash of hash, where outer hash keys are slot names.
+sortkey - Name of key in inner hash to be sorted on (e.g., starttime).
+
=back
Returns:
=over 4
-sorted - An array of slot names sorted by the start time of the slot.
-
-=back
+sorted - An array of slot names sorted by a specified sort key
+ (default sort key is start time of the slot).
=back
@@ -8325,13 +8878,16 @@ sorted - An array of slot names sorted
sub sorted_slots {
- my ($slotsarr,$slots) = @_;
+ my ($slotsarr,$slots,$sortkey) = @_;
+ if ($sortkey eq '') {
+ $sortkey = 'starttime';
+ }
my @sorted;
if ((ref($slotsarr) eq 'ARRAY') && (ref($slots) eq 'HASH')) {
@sorted =
sort {
if (ref($slots->{$a}) && ref($slots->{$b})) {
- return $slots->{$a}{'starttime'} <=> $slots->{$b}{'starttime'}
+ return $slots->{$a}{$sortkey} <=> $slots->{$b}{$sortkey}
}
if (ref($slots->{$a})) { return -1;}
if (ref($slots->{$b})) { return 1;}
@@ -8341,9 +8897,136 @@ sub sorted_slots {
return @sorted;
}
+=pod
+
+=item * get_future_slots()
+
+Inputs:
+
+=over 4
+
+cnum - course number
+
+cdom - course domain
+
+now - current UNIX time
+
+symb - optional symb
+
+=back
+
+Returns:
+
+=over 4
+
+sorted_reservable - ref to array of student_schedulable slots currently
+ reservable, ordered by end date of reservation period.
+
+reservable_now - ref to hash of student_schedulable slots currently
+ reservable.
+
+ Keys in inner hash are:
+ (a) symb: either blank or symb to which slot use is restricted.
+ (b) endreserve: end date of reservation period.
+
+sorted_future - ref to array of student_schedulable slots reservable in
+ the future, ordered by start date of reservation period.
+
+future_reservable - ref to hash of student_schedulable slots reservable
+ in the future.
+
+ Keys in inner hash are:
+ (a) symb: either blank or symb to which slot use is restricted.
+ (b) startreserve: start date of reservation period.
+
+=back
+
+=cut
+
+sub get_future_slots {
+ my ($cnum,$cdom,$now,$symb) = @_;
+ my (%reservable_now,%future_reservable,@sorted_reservable,@sorted_future);
+ my %slots = &Apache::lonnet::get_course_slots($cnum,$cdom);
+ foreach my $slot (keys(%slots)) {
+ next unless($slots{$slot}->{'type'} eq 'schedulable_student');
+ if ($symb) {
+ next if (($slots{$slot}->{'symb'} ne '') &&
+ ($slots{$slot}->{'symb'} ne $symb));
+ }
+ if (($slots{$slot}->{'starttime'} > $now) &&
+ ($slots{$slot}->{'endtime'} > $now)) {
+ if (($slots{$slot}->{'allowedsections'}) || ($slots{$slot}->{'allowedusers'})) {
+ my $userallowed = 0;
+ if ($slots{$slot}->{'allowedsections'}) {
+ my @allowed_sec = split(',',$slots{$slot}->{'allowedsections'});
+ if (!defined($env{'request.role.sec'})
+ && grep(/^No section assigned$/,@allowed_sec)) {
+ $userallowed=1;
+ } else {
+ if (grep(/^\Q$env{'request.role.sec'}\E$/,@allowed_sec)) {
+ $userallowed=1;
+ }
+ }
+ unless ($userallowed) {
+ if (defined($env{'request.course.groups'})) {
+ my @groups = split(/:/,$env{'request.course.groups'});
+ foreach my $group (@groups) {
+ if (grep(/^\Q$group\E$/,@allowed_sec)) {
+ $userallowed=1;
+ last;
+ }
+ }
+ }
+ }
+ }
+ if ($slots{$slot}->{'allowedusers'}) {
+ my @allowed_users = split(',',$slots{$slot}->{'allowedusers'});
+ my $user = $env{'user.name'}.':'.$env{'user.domain'};
+ if (grep(/^\Q$user\E$/,@allowed_users)) {
+ $userallowed = 1;
+ }
+ }
+ next unless($userallowed);
+ }
+ my $startreserve = $slots{$slot}->{'startreserve'};
+ my $endreserve = $slots{$slot}->{'endreserve'};
+ my $symb = $slots{$slot}->{'symb'};
+ if (($startreserve < $now) &&
+ (!$endreserve || $endreserve > $now)) {
+ my $lastres = $endreserve;
+ if (!$lastres) {
+ $lastres = $slots{$slot}->{'starttime'};
+ }
+ $reservable_now{$slot} = {
+ symb => $symb,
+ endreserve => $lastres
+ };
+ } elsif (($startreserve > $now) &&
+ (!$endreserve || $endreserve > $startreserve)) {
+ $future_reservable{$slot} = {
+ symb => $symb,
+ startreserve => $startreserve
+ };
+ }
+ }
+ }
+ my @unsorted_reservable = keys(%reservable_now);
+ if (@unsorted_reservable > 0) {
+ @sorted_reservable =
+ &sorted_slots(\@unsorted_reservable,\%reservable_now,'endreserve');
+ }
+ my @unsorted_future = keys(%future_reservable);
+ if (@unsorted_future > 0) {
+ @sorted_future =
+ &sorted_slots(\@unsorted_future,\%future_reservable,'startreserve');
+ }
+ return (\@sorted_reservable,\%reservable_now,\@sorted_future,\%future_reservable);
+}
=pod
+=back
+
=head1 HTTP Helpers
=over 4
@@ -8507,9 +9190,9 @@ sub ask_for_embedded_content {
$url .= $current_path;
$getpropath = 1;
} elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') ||
- ($actionurl eq '/adm/imsimport')) {
- ($uname,my $rest) = ($args->{'current_path'} =~ m{/priv/($match_username)/?(.*)$});
- $url = '/home/'.$uname.'/public_html/';
+ ($actionurl eq '/adm/imsimport')) {
+ my ($udom,$uname,$rest) = ($args->{'current_path'} =~ m{/priv/($match_domain)/($match_username)/?(.*)$});
+ $url = $Apache::lonnet::perlvar{'lonDocRoot'}."/priv/$udom/$uname/";
$toplevel = $url;
if ($rest ne '') {
$url .= $rest;
@@ -8558,11 +9241,14 @@ sub ask_for_embedded_content {
}
foreach my $path (keys(%subdependencies)) {
my %currsubfile;
- if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
- my @subdir_list = &Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);
- foreach my $line (@subdir_list) {
- my ($file_name,$rest) = split(/\&/,$line,2);
- $currsubfile{$file_name} = 1;
+ 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;
+ }
}
} elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
if (opendir(my $dir,$url.'/'.$path)) {
@@ -8585,10 +9271,13 @@ sub ask_for_embedded_content {
}
my %currfile;
if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
- my @dir_list = &Apache::lonnet::dirlist($url,$udom,$uname,$getpropath);
- foreach my $line (@dir_list) {
- my ($file_name,$rest) = split(/\&/,$line,2);
- $currfile{$file_name} = 1;
+ my ($dirlistref,$listerror) =
+ &Apache::lonnet::dirlist($url,$udom,$uname,$getpropath);
+ if (ref($dirlistref) eq 'ARRAY') {
+ foreach my $line (@{$dirlistref}) {
+ my ($file_name,$rest) = split(/\&/,$line,2);
+ $currfile{$file_name} = 1;
+ }
}
} elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
if (opendir(my $dir,$url)) {
@@ -8666,7 +9355,7 @@ sub ask_for_embedded_content {
} elsif ($applies) {
$output = ''.&mt('Referenced files').':
';
if ($applies > 1) {
- $output .=
+ $output .=
&mt('No files need to be uploaded, as one of the following applies to each reference:').'';
if ($numremref) {
$output .= '- '.&mt('reference is to a URL which points to another server').'
'."\n";
@@ -8696,7 +9385,7 @@ sub ask_for_embedded_content {
$embed_file,\%mapping,
$allfiles,$codebase);
} else {
- $pathchange_output .=
+ $pathchange_output .=
&start_data_table_row().
' | '.
@@ -8715,7 +9404,7 @@ sub ask_for_embedded_content {
$output .= ''."\n";
}
- if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') ||
+ if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') ||
($actionurl eq '/adm/imsimport')) {
$output .= ''."\n";
} elsif ($actionurl eq '/adm/portfolio' || $actionurl eq '/adm/coursegrp_portfolio') {
@@ -8727,8 +9416,8 @@ sub ask_for_embedded_content {
my %pathchange = ();
$output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);
if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
- $output .= ''.&mt('or').'
';
- }
+ $output .= ''.&mt('or').'
';
+ }
}
return ($output,$num,$numpathchg);
}
@@ -8743,7 +9432,7 @@ sub embedded_file_element {
}
$output .= '';
- unless (($context eq 'upload_embedded') &&
+ unless (($context eq 'upload_embedded') &&
($mapping->{$embed_file} eq $embed_file)) {
$output .='
';
@@ -8844,7 +9533,7 @@ sub upload_embedded {
next;
} else {
$output .= &mt('Uploaded [_1]',''.
- $path.$fname.'').'
';
+ $path.$fname.'').'
';
}
}
} elsif ($context eq 'coursedoc') {
@@ -8867,12 +9556,12 @@ sub upload_embedded {
my $fullpath = $dir_root.$dirpath.'/'.$path;
my $dest = $fullpath.$fname;
my $url = $url_root.$dirpath.'/'.$path.$fname;
- my @parts=split(/\//,$fullpath);
+ my @parts=split(/\//,"$dirpath/$path");
my $count;
my $filepath = $dir_root;
- for ($count=4;$count<=$#parts;$count++) {
- $filepath .= "/$parts[$count]";
- if ((-e $filepath)!=1) {
+ foreach my $subdir (@parts) {
+ $filepath .= "/$subdir";
+ if (!-e $filepath) {
mkdir($filepath,0770);
}
}
@@ -8951,7 +9640,7 @@ sub modify_html_form {
''.
&end_data_table_row();
- }
+ }
}
} else {
$modifyform = $pathchgtable;
@@ -8991,8 +9680,7 @@ sub modify_html_refs {
} elsif ($context eq 'coursedoc') {
$container = $env{'form.primaryurl'};
} else {
- $container = $env{'form.filename'};
- $container =~ s{^/priv/(\Q$uname\E)/(.*)}{/home/$1/public_html/$2};
+ $container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'};
}
my (%allfiles,%codebase,$output,$content);
my @changes = &get_env_multiple('form.namechange');
@@ -9002,7 +9690,7 @@ sub modify_html_refs {
$content = &Apache::lonnet::getfile($container);
return if ($content eq '-1');
} else {
- return unless ($container =~ /^\Q$dir_root\E/);
+ return unless ($container =~ /^\Q$dir_root\E/);
if (open(my $fh,"<$container")) {
$content = join('', <$fh>);
close($fh);
@@ -9014,7 +9702,7 @@ sub modify_html_refs {
my $mm = new File::MMagic;
my $mime_type = $mm->checktype_contents($content);
if ($mime_type eq 'text/html') {
- my $parse_result =
+ my $parse_result =
&Apache::lonnet::extract_embedded_items($container,\%allfiles,
\%codebase,\$content);
if ($parse_result eq 'ok') {
@@ -9024,7 +9712,7 @@ sub modify_html_refs {
if ($allfiles{$ref}) {
my $newname = $orig;
my ($attrib_regexp,$codebase);
- my $attrib_regexp = &unescape($env{'form.embedded_attrib_'.$i});
+ $attrib_regexp = &unescape($env{'form.embedded_attrib_'.$i});
if ($attrib_regexp =~ /:/) {
$attrib_regexp =~ s/\:/|/g;
}
@@ -9033,7 +9721,7 @@ sub modify_html_refs {
$count += $numchg;
}
if ($env{'form.embedded_codebase_'.$i} ne '') {
- my $codebase = &unescape($env{'form.embedded_codebase_'.$i});
+ $codebase = &unescape($env{'form.embedded_codebase_'.$i});
my $numchg = ($content =~ s/(codebase\s*=\s*["']?)\Q$codebase\E(["']?)/$1.$2/i); #' stupid emacs
$codebasecount ++;
}
@@ -9047,7 +9735,7 @@ sub modify_html_refs {
my ($fname) = ($container =~ m{/([^/]+)$});
$output = ''.&mt('Updated [quant,_1,reference] in [_2].',
$count,''.
- $fname.'').'
';
+ $fname.'').'';
} else {
$output = ''.
&mt('Error: update failed for: [_1].',
@@ -9099,17 +9787,17 @@ sub check_for_upload {
my $filesize = length($env{'form.'.$element});
if (!$filesize) {
my $msg = ''.
- &mt('Unable to upload [_1]. (size = [_2] bytes)',
+ &mt('Unable to upload [_1]. (size = [_2] bytes)',
''.$fname.'',
$filesize).'
'.
- &mt('Either the file you attempted to upload was empty, or your web browser was unable to read its contents.').'
';
+ &mt('Either the file you attempted to upload was empty, or your web browser was unable to read its contents.').'
'.
'';
return ('zero_bytes',$msg);
}
$filesize = $filesize/1000; #express in k (1024?)
my $getpropath = 1;
- my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,
- $getpropath);
+ my ($dirlistref,$listerror) =
+ &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,$getpropath);
my $found_file = 0;
my $locked_file = 0;
my @lockers;
@@ -9117,48 +9805,50 @@ sub check_for_upload {
if ($env{'request.course.id'}) {
$navmap = Apache::lonnavmaps::navmap->new();
}
- foreach my $line (@dir_list) {
- my ($file_name,$rest)=split(/\&/,$line,2);
- if ($file_name eq $fname){
- $file_name = $path.$file_name;
- if ($group ne '') {
- $file_name = $group.$file_name;
- }
- $found_file = 1;
- if (&Apache::lonnet::is_locked($file_name,$udom,$uname,\@lockers) eq 'true') {
- foreach my $lock (@lockers) {
- if (ref($lock) eq 'ARRAY') {
- my ($symb,$crsid) = @{$lock};
- if ($crsid eq $env{'request.course.id'}) {
- if (ref($navmap)) {
- my $res = $navmap->getBySymb($symb);
- foreach my $part (@{$res->parts()}) {
- my ($slot_status,$slot_time,$slot_name)=$res->check_for_slot($part);
- unless (($slot_status == $res->RESERVED) ||
- ($slot_status == $res->RESERVED_LOCATION)) {
- $locked_file = 1;
+ if (ref($dirlistref) eq 'ARRAY') {
+ foreach my $line (@{$dirlistref}) {
+ my ($file_name,$rest)=split(/\&/,$line,2);
+ if ($file_name eq $fname){
+ $file_name = $path.$file_name;
+ if ($group ne '') {
+ $file_name = $group.$file_name;
+ }
+ $found_file = 1;
+ if (&Apache::lonnet::is_locked($file_name,$udom,$uname,\@lockers) eq 'true') {
+ foreach my $lock (@lockers) {
+ if (ref($lock) eq 'ARRAY') {
+ my ($symb,$crsid) = @{$lock};
+ if ($crsid eq $env{'request.course.id'}) {
+ if (ref($navmap)) {
+ my $res = $navmap->getBySymb($symb);
+ foreach my $part (@{$res->parts()}) {
+ my ($slot_status,$slot_time,$slot_name)=$res->check_for_slot($part);
+ unless (($slot_status == $res->RESERVED) ||
+ ($slot_status == $res->RESERVED_LOCATION)) {
+ $locked_file = 1;
+ }
}
+ } else {
+ $locked_file = 1;
}
} else {
$locked_file = 1;
}
- } else {
- $locked_file = 1;
}
- }
- }
- } else {
- my @info = split(/\&/,$rest);
- my $currsize = $info[6]/1000;
- if ($currsize < $filesize) {
- my $extra = $filesize - $currsize;
- if (($current_disk_usage + $extra) > $disk_quota) {
- my $msg = ''.
- &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',
- ''.$fname.'',$filesize,$currsize).''.
- '
'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
- $disk_quota,$current_disk_usage);
- return ('will_exceed_quota',$msg);
+ }
+ } else {
+ my @info = split(/\&/,$rest);
+ my $currsize = $info[6]/1000;
+ if ($currsize < $filesize) {
+ my $extra = $filesize - $currsize;
+ if (($current_disk_usage + $extra) > $disk_quota) {
+ my $msg = ''.
+ &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',
+ ''.$fname.'',$filesize,$currsize).''.
+ '
'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
+ $disk_quota,$current_disk_usage);
+ return ('will_exceed_quota',$msg);
+ }
}
}
}
@@ -9228,6 +9918,1269 @@ 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".
+ ''."\n".
+ ''."\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()
+
+Determines path in a user's portfolio file for storage of files uploaded
+to a specific essayresponse or dropbox item.
+
+Inputs: 3 required + 1 optional.
+$symb is symb for resource, $uname and $udom are for current user (required).
+$caller is optional (can be "submission", if routine is called when storing
+an upoaded file when "Submit Answer" button was pressed).
+
+Returns array containing $path and $multiresp.
+$path is path in portfolio. $multiresp is 1 if this resource contains more
+than one file upload item. Callers of routine should append partid as a
+subdirectory to $path in cases where $multiresp is 1.
+
+Called by: homework/essayresponse.pm and homework/structuretags.pm
+
+=cut
+
+sub get_turnedin_filepath {
+ my ($symb,$uname,$udom,$caller) = @_;
+ my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb);
+ my $turnindir;
+ my %userhash = &Apache::lonnet::userenvironment($udom,$uname,'turnindir');
+ $turnindir = $userhash{'turnindir'};
+ my ($path,$multiresp);
+ if ($turnindir eq '') {
+ if ($caller eq 'submission') {
+ $turnindir = &mt('turned in');
+ $turnindir =~ s/\W+/_/g;
+ my %newhash = (
+ 'turnindir' => $turnindir,
+ );
+ &Apache::lonnet::put('environment',\%newhash,$udom,$uname);
+ }
+ }
+ if ($turnindir ne '') {
+ $path = '/'.$turnindir.'/';
+ my ($multipart,$turnin,@pathitems);
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (defined($navmap)) {
+ my $mapres = $navmap->getResourceByUrl($map);
+ if (ref($mapres)) {
+ my $pcslist = $mapres->map_hierarchy();
+ if ($pcslist ne '') {
+ foreach my $pc (split(/,/,$pcslist)) {
+ my $res = $navmap->getByMapPc($pc);
+ if (ref($res)) {
+ my $title = $res->compTitle();
+ $title =~ s/\W+/_/g;
+ if ($title ne '') {
+ push(@pathitems,$title);
+ }
+ }
+ }
+ }
+ my $maptitle = $mapres->compTitle();
+ $maptitle =~ s/\W+/_/g;
+ if ($maptitle ne '') {
+ push(@pathitems,$maptitle);
+ }
+ unless ($env{'request.state'} eq 'construct') {
+ my $res = $navmap->getBySymb($symb);
+ if (ref($res)) {
+ my $partlist = $res->parts();
+ my $totaluploads = 0;
+ if (ref($partlist) eq 'ARRAY') {
+ foreach my $part (@{$partlist}) {
+ my @types = $res->responseType($part);
+ my @ids = $res->responseIds($part);
+ for (my $i=0; $i < scalar(@ids); $i++) {
+ if ($types[$i] eq 'essay') {
+ my $partid = $part.'_'.$ids[$i];
+ if (&Apache::lonnet::EXT("resource.$partid.uploadedfiletypes") ne '') {
+ $totaluploads ++;
+ }
+ }
+ }
+ }
+ if ($totaluploads > 1) {
+ $multiresp = 1;
+ }
+ }
+ }
+ }
+ } else {
+ return;
+ }
+ } else {
+ return;
+ }
+ my $restitle=&Apache::lonnet::gettitle($symb);
+ $restitle =~ s/\W+/_/g;
+ if ($restitle eq '') {
+ $restitle = ($resurl =~ m{/[^/]+$});
+ if ($restitle eq '') {
+ $restitle = time;
+ }
+ }
+ push(@pathitems,$restitle);
+ $path .= join('/',@pathitems);
+ }
+ return ($path,$multiresp);
+}
+
=pod
=back
@@ -11149,6 +13102,8 @@ sub construct_course {
############################################################
############################################################
+#SD
+# only Community and Course, or anything else?
sub course_type {
my ($cid) = @_;
if (!defined($cid)) {
@@ -11264,7 +13219,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) {
@@ -11302,7 +13257,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
@@ -11314,15 +13270,12 @@ sub init_user_environment {
my %userenv = &Apache::lonnet::dump('environment',$domain,$username);
my ($tmp) = keys(%userenv);
if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
- # default remote control to off
- if ($userenv{'remote'} ne 'on') { $userenv{'remote'} = 'off'; }
} else {
undef(%userenv);
}
if (($userenv{'interface'}) && (!$form->{'interface'})) {
$form->{'interface'}=$userenv{'interface'};
}
- $env{'environment.remote'}=$userenv{'remote'};
if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; }
# --------------- Do not trust query string to be put directly into environment
@@ -11354,16 +13307,17 @@ sub init_user_environment {
$initial_env{"browser.localres"} = $form->{'localres'};
}
- if ($public) {
- $initial_env{"environment.remote"} = "off";
- }
if ($form->{'interface'}) {
$form->{'interface'}=~s/\W//gs;
$initial_env{"browser.interface"} = $form->{'interface'};
$env{'browser.interface'}=$form->{'interface'};
}
+
my %is_adv = ( is_adv => $env{'user.adv'} );
- my %domdef = &Apache::lonnet::get_domain_defaults($domain);
+ my %domdef;
+ unless ($domain eq 'public') {
+ %domdef = &Apache::lonnet::get_domain_defaults($domain);
+ }
foreach my $tool ('aboutme','blog','portfolio') {
$userenv{'availabletools.'.$tool} =
@@ -11379,12 +13333,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'});
}