Diff for /loncom/interface/loncommon.pm between versions 1.1053 and 1.1075.2.14

version 1.1053, 2012/01/16 18:00:24 version 1.1075.2.14, 2012/09/01 09:49:08
Line 70  use Apache::lonclonecourse(); Line 70  use Apache::lonclonecourse();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale::Catalog;  use DateTime::Locale::Catalog;
   use Authen::Captcha;
   use Captcha::reCAPTCHA;
   
 # ---------------------------------------------- Designs  # ---------------------------------------------- Designs
 use vars qw(%defaultdesign);  use vars qw(%defaultdesign);
Line 885  sub check_uncheck_jscript { Line 887  sub check_uncheck_jscript {
 function checkAll(field) {  function checkAll(field) {
     if (field.length > 0) {      if (field.length > 0) {
         for (i = 0; i < field.length; i++) {          for (i = 0; i < field.length; i++) {
             field[i].checked = true ;              if (!field[i].disabled) {
                   field[i].checked = true;
               }
         }          }
     } else {      } else {
         field.checked = true          if (!field.disabled) {
               field.checked = true;
           }
     }      }
 }  }
     
Line 1374  function helpMenu(target) { Line 1380  function helpMenu(target) {
     return;      return;
 }  }
 function writeHelp(caller) {  function writeHelp(caller) {
     caller.document.writeln('$start_page<frame name="bannerframe"  src="'+banner_link+'" /><frame name="bodyframe" src="$details_link" /> $end_page')      caller.document.writeln('$start_page\\n<frame name="bannerframe" src="'+banner_link+'" />\\n<frame name="bodyframe" src="$details_link" />\\n$end_page')
     caller.document.close()      caller.document.close()
     caller.focus()      caller.focus()
 }  }
Line 1748  Inputs: $workbook Line 1754  Inputs: $workbook
   
 Returns: $format, a hash reference.  Returns: $format, a hash reference.
   
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 1980  sub select_form { Line 1987  sub select_form {
 # For display filters  # For display filters
   
 sub display_filter {  sub display_filter {
       my ($context) = @_;
     if (!$env{'form.show'}) { $env{'form.show'}=10; }      if (!$env{'form.show'}) { $env{'form.show'}=10; }
     if (!$env{'form.displayfilter'}) { $env{'form.displayfilter'}='currentfolder'; }      if (!$env{'form.displayfilter'}) { $env{'form.displayfilter'}='currentfolder'; }
     return '<span class="LC_nobreak"><label>'.&mt('Records [_1]',      my $phraseinput = 'hidden';
       my $includeinput = 'hidden';
       my ($checked,$includetypestext);
       if ($env{'form.displayfilter'} eq 'containing') {
           $phraseinput = 'text'; 
           if ($context eq 'parmslog') {
               $includeinput = 'checkbox';
               if ($env{'form.includetypes'}) {
                   $checked = ' checked="checked"';
               }
               $includetypestext = &mt('Include parameter types');
           }
       } else {
           $includetypestext = '&nbsp;';
       }
       my ($additional,$secondid,$thirdid);
       if ($context eq 'parmslog') {
           $additional = 
               '<label><input type="'.$includeinput.'" name="includetypes"'. 
               $checked.' name="includetypes" value="1" id="includetypes" />'.
               '&nbsp;<span id="includetypestext">'.$includetypestext.'</span>'.
               '</label>';
           $secondid = 'includetypes';
           $thirdid = 'includetypestext';
       }
       my $onchange = "javascript:toggleHistoryOptions(this,'containingphrase','$context',
                                                       '$secondid','$thirdid')";
       return '<span class="LC_nobreak"><label>'.&mt('Records: [_1]',
        &Apache::lonmeta::selectbox('show',$env{'form.show'},undef,         &Apache::lonmeta::selectbox('show',$env{'form.show'},undef,
    (&mt('all'),10,20,50,100,1000,10000))).     (&mt('all'),10,20,50,100,1000,10000))).
    '</label></span> <span class="LC_nobreak">'.     '</label></span> <span class="LC_nobreak">'.
            &mt('Filter [_1]',             &mt('Filter: [_1]',
    &select_form($env{'form.displayfilter'},     &select_form($env{'form.displayfilter'},
  'displayfilter',   'displayfilter',
  {'currentfolder' => 'Current folder/page',   {'currentfolder' => 'Current folder/page',
  'containing' => 'Containing phrase',   'containing' => 'Containing phrase',
  'none' => 'None'})).   'none' => 'None'},$onchange)).'&nbsp;'.
  '<input type="text" name="containingphrase" size="30" value="'.&HTML::Entities::encode($env{'form.containingphrase'}).'" /></span>';   '<input type="'.$phraseinput.'" name="containingphrase" id="containingphrase" size="30" value="'.
                            &HTML::Entities::encode($env{'form.containingphrase'}).
                            '" />'.$additional;
   }
   
   sub display_filter_js {
       my $includetext = &mt('Include parameter types');
       return <<"ENDJS";
     
   function toggleHistoryOptions(setter,firstid,context,secondid,thirdid) {
       var firstType = 'hidden';
       if (setter.options[setter.selectedIndex].value == 'containing') {
           firstType = 'text';
       }
       firstObject = document.getElementById(firstid);
       if (typeof(firstObject) == 'object') {
           if (firstObject.type != firstType) {
               changeInputType(firstObject,firstType);
           }
       }
       if (context == 'parmslog') {
           var secondType = 'hidden';
           if (firstType == 'text') {
               secondType = 'checkbox';
           }
           secondObject = document.getElementById(secondid);  
           if (typeof(secondObject) == 'object') {
               if (secondObject.type != secondType) {
                   changeInputType(secondObject,secondType);
               }
           }
           var textItem = document.getElementById(thirdid);
           var currtext = textItem.innerHTML;
           var newtext;
           if (firstType == 'text') {
               newtext = '$includetext';
           } else {
               newtext = '&nbsp;';
           }
           if (currtext != newtext) {
               textItem.innerHTML = newtext;
           }
       }
       return;
   }
   
   function changeInputType(oldObject,newType) {
       var newObject = document.createElement('input');
       newObject.type = newType;
       if (oldObject.size) {
           newObject.size = oldObject.size;
       }
       if (oldObject.value) {
           newObject.value = oldObject.value;
       }
       if (oldObject.name) {
           newObject.name = oldObject.name;
       }
       if (oldObject.id) {
           newObject.id = oldObject.id;
       }
       oldObject.parentNode.replaceChild(newObject,oldObject);
       return;
   }
   
   ENDJS
 }  }
   
 sub gradeleveldescription {  sub gradeleveldescription {
Line 2856  database which holds them. Line 2956  database which holds them.
   
 Uses global $thesaurus_db_file.  Uses global $thesaurus_db_file.
   
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 3127  sub noteswrapper { Line 3228  sub noteswrapper {
 # ------------------------------------------------------------- Aboutme Wrapper  # ------------------------------------------------------------- Aboutme Wrapper
   
 sub aboutmewrapper {  sub aboutmewrapper {
     my ($link,$username,$domain,$target)=@_;      my ($link,$username,$domain,$target,$class)=@_;
     if (!defined($username)  && !defined($domain)) {      if (!defined($username)  && !defined($domain)) {
         return;          return;
     }      }
     return '<a href="/adm/'.$domain.'/'.$username.'/aboutme?forcestudent=1"'.      return '<a href="/adm/'.$domain.'/'.$username.'/aboutme?forcestudent=1"'.
  ($target?' target="$target"':'').' title="'.&mt("View this user's personal information page").'">'.$link.'</a>';   ($target?' target="'.$target.'"':'').($class?' class="'.$class.'"':'').' title="'.&mt("View this user's personal information page").'">'.$link.'</a>';
 }  }
   
 # ------------------------------------------------------------ Syllabus Wrapper  # ------------------------------------------------------------ Syllabus Wrapper
Line 3988  sub findallcourses { Line 4089  sub findallcourses {
         $udom = $env{'user.domain'};          $udom = $env{'user.domain'};
     }      }
     if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {      if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
         my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});          my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname);
         my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,  
                                               $extra);  
         if (!%roles) {          if (!%roles) {
             %roles = (              %roles = (
                        cc => 1,                         cc => 1,
Line 4015  sub findallcourses { Line 4114  sub findallcourses {
             if ($tstart) {              if ($tstart) {
                 next if ($tstart > $now);                  next if ($tstart > $now);
             }              }
             my ($cdom,$cnum,$sec,$cnumpart,$secpart,$role,$realsec);              my ($cdom,$cnum,$sec,$cnumpart,$secpart,$role);
             (undef,$cdom,$cnumpart,$secpart) = split(/\//,$entry);              (undef,$cdom,$cnumpart,$secpart) = split(/\//,$entry);
               my $value = $trole.'/'.$cdom.'/';
             if ($secpart eq '') {              if ($secpart eq '') {
                 ($cnum,$role) = split(/_/,$cnumpart);                   ($cnum,$role) = split(/_/,$cnumpart); 
                 $sec = 'none';                  $sec = 'none';
                 $realsec = '';                  $value .= $cnum.'/';
             } else {              } else {
                 $cnum = $cnumpart;                  $cnum = $cnumpart;
                 ($sec,$role) = split(/_/,$secpart);                  ($sec,$role) = split(/_/,$secpart);
                 $realsec = $sec;                  $value .= $cnum.'/'.$sec;
               }
               if (ref($courses{$cdom.'_'.$cnum}{$sec}) eq 'ARRAY') {
                   unless (grep(/^\Q$value\E$/,@{$courses{$cdom.'_'.$cnum}{$sec}})) {
                       push(@{$courses{$cdom.'_'.$cnum}{$sec}},$value);
                   }
               } else {
                   @{$courses{$cdom.'_'.$cnum}{$sec}} = ($value);
             }              }
             $courses{$cdom.'_'.$cnum}{$sec} = $trole.'/'.$cdom.'/'.$cnum.'/'.$realsec;  
         }          }
     } else {      } else {
         foreach my $key (keys(%env)) {          foreach my $key (keys(%env)) {
Line 4044  sub findallcourses { Line 4150  sub findallcourses {
                     if ($now>$endtime) { $active=0; }                      if ($now>$endtime) { $active=0; }
                 }                  }
                 if ($active) {                  if ($active) {
                       my $value = $role.'/'.$cdom.'/'.$cnum.'/';
                     if ($sec eq '') {                      if ($sec eq '') {
                         $sec = 'none';                          $sec = 'none';
                       } else {
                           $value .= $sec;
                       }
                       if (ref($courses{$cdom.'_'.$cnum}{$sec}) eq 'ARRAY') {
                           unless (grep(/^\Q$value\E$/,@{$courses{$cdom.'_'.$cnum}{$sec}})) {
                               push(@{$courses{$cdom.'_'.$cnum}{$sec}},$value);
                           }
                       } else {
                           @{$courses{$cdom.'_'.$cnum}{$sec}} = ($value);
                     }                      }
                     $courses{$cdom.'_'.$cnum}{$sec} =   
                                      $role.'/'.$cdom.'/'.$cnum.'/'.$sec;  
                 }                  }
             }              }
         }          }
Line 4059  sub findallcourses { Line 4173  sub findallcourses {
 ###############################################  ###############################################
   
 sub blockcheck {  sub blockcheck {
     my ($setters,$activity,$uname,$udom) = @_;      my ($setters,$activity,$uname,$udom,$url) = @_;
   
     if (!defined($udom)) {      if (!defined($udom)) {
         $udom = $env{'user.domain'};          $udom = $env{'user.domain'};
Line 4071  sub blockcheck { Line 4185  sub blockcheck {
     # If uname and udom are for a course, check for blocks in the course.      # If uname and udom are for a course, check for blocks in the course.
   
     if (&Apache::lonnet::is_course($udom,$uname)) {      if (&Apache::lonnet::is_course($udom,$uname)) {
         my %records = &Apache::lonnet::dump('comm_block',$udom,$uname);          my ($startblock,$endblock,$triggerblock) = 
         my ($startblock,$endblock)=&get_blocks($setters,$activity,$udom,$uname);              &get_blocks($setters,$activity,$udom,$uname,$url);
         return ($startblock,$endblock);          return ($startblock,$endblock,$triggerblock);
     }      }
   
     my $startblock = 0;      my $startblock = 0;
     my $endblock = 0;      my $endblock = 0;
       my $triggerblock = '';
     my %live_courses = &findallcourses(undef,$uname,$udom);      my %live_courses = &findallcourses(undef,$uname,$udom);
   
     # If uname is for a user, and activity is course-specific, i.e.,      # If uname is for a user, and activity is course-specific, i.e.,
Line 4141  sub blockcheck { Line 4256  sub blockcheck {
             if ($otheruser) {              if ($otheruser) {
                 # Resource belongs to user other than current user.                  # Resource belongs to user other than current user.
                 # Assemble privs for that user, and check for 'evb' priv.                  # Assemble privs for that user, and check for 'evb' priv.
                 my ($trole,$tdom,$tnum,$tsec);                  my (%allroles,%userroles);
                 my $entry = $live_courses{$course}{$sec};                  if (ref($live_courses{$course}{$sec}) eq 'ARRAY') {
                 if ($entry =~ /^cr/) {                      foreach my $entry (@{$live_courses{$course}{$sec}}) { 
                     ($trole,$tdom,$tnum,$tsec) =                           my ($trole,$tdom,$tnum,$tsec);
                       ($entry =~ m|^(cr/$match_domain/$match_username/\w+)\./($match_domain)/($match_username)/?(\w*)$|);                          if ($entry =~ /^cr/) {
                 } else {                              ($trole,$tdom,$tnum,$tsec) = 
                     ($trole,$tdom,$tnum,$tsec) = split(/\//,$entry);                                  ($entry =~ m|^(cr/$match_domain/$match_username/\w+)\./($match_domain)/($match_username)/?(\w*)$|);
                 }                          } else {
                 my ($spec,$area,$trest,%allroles,%userroles);                             ($trole,$tdom,$tnum,$tsec) = split(/\//,$entry);
                 $area = '/'.$tdom.'/'.$tnum;                          }
                 $trest = $tnum;                          my ($spec,$area,$trest);
                 if ($tsec ne '') {                          $area = '/'.$tdom.'/'.$tnum;
                     $area .= '/'.$tsec;                          $trest = $tnum;
                     $trest .= '/'.$tsec;                          if ($tsec ne '') {
                 }                              $area .= '/'.$tsec;
                 $spec = $trole.'.'.$area;                              $trest .= '/'.$tsec;
                 if ($trole =~ /^cr/) {                          }
                     &Apache::lonnet::custom_roleprivs(\%allroles,$trole,                          $spec = $trole.'.'.$area;
                                                       $tdom,$spec,$trest,$area);                          if ($trole =~ /^cr/) {
                 } else {                              &Apache::lonnet::custom_roleprivs(\%allroles,$trole,
                     &Apache::lonnet::standard_roleprivs(\%allroles,$trole,                                                                $tdom,$spec,$trest,$area);
                                                        $tdom,$spec,$trest,$area);                          } else {
                 }                              &Apache::lonnet::standard_roleprivs(\%allroles,$trole,
                 my ($author,$adv) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles);                                                                  $tdom,$spec,$trest,$area);
                 if ($userroles{'user.priv.'.$checkrole} =~ /evb\&([^\:]*)/) {                          }
                     if ($1) {                      }
                         $no_userblock = 1;                      my ($author,$adv) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles);
                         last;                      if ($userroles{'user.priv.'.$checkrole} =~ /evb\&([^\:]*)/) {
                           if ($1) {
                               $no_userblock = 1;
                               last;
                           }
                     }                      }
                 }                  }
             } else {              } else {
Line 4188  sub blockcheck { Line 4307  sub blockcheck {
         # Retrieve blocking times and identity of locker for course          # Retrieve blocking times and identity of locker for course
         # of specified user, unless user has 'evb' privilege.          # of specified user, unless user has 'evb' privilege.
                   
         my ($start,$end)=&get_blocks($setters,$activity,$cdom,$cnum);          my ($start,$end,$trigger) = 
               &get_blocks($setters,$activity,$cdom,$cnum,$url);
         if (($start != 0) &&           if (($start != 0) && 
             (($startblock == 0) || ($startblock > $start))) {              (($startblock == 0) || ($startblock > $start))) {
             $startblock = $start;              $startblock = $start;
               if ($trigger ne '') {
                   $triggerblock = $trigger;
               }
         }          }
         if (($end != 0)  &&          if (($end != 0)  &&
             (($endblock == 0) || ($endblock < $end))) {              (($endblock == 0) || ($endblock < $end))) {
             $endblock = $end;              $endblock = $end;
               if ($trigger ne '') {
                   $triggerblock = $trigger;
               }
         }          }
     }      }
     return ($startblock,$endblock);      return ($startblock,$endblock,$triggerblock);
 }  }
   
 sub get_blocks {  sub get_blocks {
     my ($setters,$activity,$cdom,$cnum) = @_;      my ($setters,$activity,$cdom,$cnum,$url) = @_;
     my $startblock = 0;      my $startblock = 0;
     my $endblock = 0;      my $endblock = 0;
       my $triggerblock = '';
     my $course = $cdom.'_'.$cnum;      my $course = $cdom.'_'.$cnum;
     $setters->{$course} = {};      $setters->{$course} = {};
     $setters->{$course}{'staff'} = [];      $setters->{$course}{'staff'} = [];
     $setters->{$course}{'times'} = [];      $setters->{$course}{'times'} = [];
     my %records = &Apache::lonnet::dump('comm_block',$cdom,$cnum);      $setters->{$course}{'triggers'} = [];
     foreach my $record (keys(%records)) {      my (@blockers,%triggered);
         my ($start,$end) = ($record =~ m/^(\d+)____(\d+)$/);      my $now = time;
         if ($start <= time && $end >= time) {      my %commblocks = &Apache::lonnet::get_comm_blocks($cdom,$cnum);
             my ($staff_name,$staff_dom,$title,$blocks) =      if ($activity eq 'docs') {
                 &parse_block_record($records{$record});          @blockers = &Apache::lonnet::has_comm_blocking('bre',undef,$url,\%commblocks);
             if ($blocks->{$activity} eq 'on') {          foreach my $block (@blockers) {
                 push(@{$$setters{$course}{'staff'}},[$staff_name,$staff_dom]);              if ($block =~ /^firstaccess____(.+)$/) {
                 push(@{$$setters{$course}{'times'}}, [$start,$end]);                  my $item = $1;
                 if ( ($startblock == 0) || ($startblock > $start) ) {                  my $type = 'map';
                     $startblock = $start;                  my $timersymb = $item;
                   if ($item eq 'course') {
                       $type = 'course';
                   } elsif ($item =~ /___\d+___/) {
                       $type = 'resource';
                   } else {
                       $timersymb = &Apache::lonnet::symbread($item);
                   }
                   my $start = $env{'course.'.$cdom.'_'.$cnum.'.firstaccess.'.$timersymb};
                   my $end = $start + $env{'course.'.$cdom.'_'.$cnum.'.timerinterval.'.$timersymb};
                   $triggered{$block} = {
                                          start => $start,
                                          end   => $end,
                                          type  => $type,
                                        };
               }
           }
       } else {
           foreach my $block (keys(%commblocks)) {
               if ($block =~ m/^(\d+)____(\d+)$/) { 
                   my ($start,$end) = ($1,$2);
                   if ($start <= time && $end >= time) {
                       if (ref($commblocks{$block}) eq 'HASH') {
                           if (ref($commblocks{$block}{'blocks'}) eq 'HASH') {
                               if ($commblocks{$block}{'blocks'}{$activity} eq 'on') {
                                   unless(grep(/^\Q$block\E$/,@blockers)) {
                                       push(@blockers,$block);
                                   }
                               }
                           }
                       }
                   }
               } elsif ($block =~ /^firstaccess____(.+)$/) {
                   my $item = $1;
                   my $timersymb = $item; 
                   my $type = 'map';
                   if ($item eq 'course') {
                       $type = 'course';
                   } elsif ($item =~ /___\d+___/) {
                       $type = 'resource';
                   } else {
                       $timersymb = &Apache::lonnet::symbread($item);
                 }                  }
                 if ( ($endblock == 0) || ($endblock < $end) ) {                  my $start = $env{'course.'.$cdom.'_'.$cnum.'.firstaccess.'.$timersymb};
                     $endblock = $end;                  my $end = $start + $env{'course.'.$cdom.'_'.$cnum.'.timerinterval.'.$timersymb}; 
                   if ($start && $end) {
                       if (($start <= time) && ($end >= time)) {
                           unless (grep(/^\Q$block\E$/,@blockers)) {
                               push(@blockers,$block);
                               $triggered{$block} = {
                                                      start => $start,
                                                      end   => $end,
                                                      type  => $type,
                                                    };
                           }
                       }
                   }
               }
           }
       }
       foreach my $blocker (@blockers) {
           my ($staff_name,$staff_dom,$title,$blocks) =
               &parse_block_record($commblocks{$blocker});
           push(@{$$setters{$course}{'staff'}},[$staff_name,$staff_dom]);
           my ($start,$end,$triggertype);
           if ($blocker =~ m/^(\d+)____(\d+)$/) {
               ($start,$end) = ($1,$2);
           } elsif (ref($triggered{$blocker}) eq 'HASH') {
               $start = $triggered{$blocker}{'start'};
               $end = $triggered{$blocker}{'end'};
               $triggertype = $triggered{$blocker}{'type'};
           }
           if ($start) {
               push(@{$$setters{$course}{'times'}}, [$start,$end]);
               if ($triggertype) {
                   push(@{$$setters{$course}{'triggers'}},$triggertype);
               } else {
                   push(@{$$setters{$course}{'triggers'}},0);
               }
               if ( ($startblock == 0) || ($startblock > $start) ) {
                   $startblock = $start;
                   if ($triggertype) {
                       $triggerblock = $blocker;
                 }                  }
             }              }
               if ( ($endblock == 0) || ($endblock < $end) ) {
                  $endblock = $end;
                  if ($triggertype) {
                      $triggerblock = $blocker;
                  }
               }
         }          }
     }      }
     return ($startblock,$endblock);      return ($startblock,$endblock,$triggerblock);
 }  }
   
 sub parse_block_record {  sub parse_block_record {
Line 4251  sub parse_block_record { Line 4463  sub parse_block_record {
 }  }
   
 sub blocking_status {  sub blocking_status {
   my ($activity,$uname,$udom) = @_;      my ($activity,$uname,$udom,$url) = @_;
   my %setters;      my %setters;
   
   # check for active blocking  
   my ($startblock,$endblock)=&blockcheck(\%setters,$activity,$uname,$udom);  
   
   my $blocked = $startblock && $endblock ? 1 : 0;  
   
   # caller just wants to know whether a block is active  # check for active blocking
   if (!wantarray) { return $blocked; }      my ($startblock,$endblock,$triggerblock) = 
           &blockcheck(\%setters,$activity,$uname,$udom,$url);
   # build a link to a popup window containing the details      my $blocked = 0;
   my $querystring  = "?activity=$activity";      if ($startblock && $endblock) {
   # $uname and $udom decide whose portfolio the user is trying to look at          $blocked = 1;
      $querystring .= "&amp;udom=$udom"      if $udom;      }
      $querystring .= "&amp;uname=$uname"    if $uname;  
   # caller just wants to know whether a block is active
   my $output .= <<'END_MYBLOCK';      if (!wantarray) { return $blocked; }
     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {  
         var options = "width=" + w + ",height=" + h + ",";  # build a link to a popup window containing the details
         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";      my $querystring  = "?activity=$activity";
         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";  # $uname and $udom decide whose portfolio the user is trying to look at
         var newWin = window.open(url, wdwName, options);      if ($activity eq 'port') {
         newWin.focus();          $querystring .= "&amp;udom=$udom"      if $udom;
     }          $querystring .= "&amp;uname=$uname"    if $uname;
       } elsif ($activity eq 'docs') {
           $querystring .= '&amp;url='.&HTML::Entities::encode($url,'&"');
       }
   
       my $output .= <<'END_MYBLOCK';
   function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
       var options = "width=" + w + ",height=" + h + ",";
       options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
       options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
       var newWin = window.open(url, wdwName, options);
       newWin.focus();
   }
 END_MYBLOCK  END_MYBLOCK
   
   $output = Apache::lonhtmlcommon::scripttag($output);      $output = Apache::lonhtmlcommon::scripttag($output);
       
   my $popupUrl = "/adm/blockingstatus/$querystring";      my $popupUrl = "/adm/blockingstatus/$querystring";
   my $text = mt('Communication Blocked');      my $text = &mt('Communication Blocked');
       if ($activity eq 'docs') {
   $output .= <<"END_BLOCK";          $text = &mt('Content Access Blocked');
       } elsif ($activity eq 'printout') {
           $text = &mt('Printing Blocked');
       }
       $output .= <<"END_BLOCK";
 <div class='LC_comblock'>  <div class='LC_comblock'>
   <a onclick='openWindow("$popupUrl","Blocking Table",600,300,"no","no");return false;' href='/adm/blockingstatus/$querystring'    <a onclick='openWindow("$popupUrl","Blocking Table",600,300,"no","no");return false;' href='/adm/blockingstatus/$querystring'
   title='$text'>    title='$text'>
Line 4294  END_MYBLOCK Line 4517  END_MYBLOCK
   
 END_BLOCK  END_BLOCK
   
   return ($blocked, $output);      return ($blocked, $output);
 }  }
   
 ###############################################  ###############################################
Line 4737  Inputs: Line 4960  Inputs:
   
 =item * $bgcolor, used to override the bgcolor on a webpage to a specific value  =item * $bgcolor, used to override the bgcolor on a webpage to a specific value
   
   =item * $no_inline_link, if true and in remote mode, don't show the
            'Switch To Inline Menu' link
   
 =item * $args, optional argument valid values are  =item * $args, optional argument valid values are
             no_auto_mt_title -> prevents &mt()ing the title arg              no_auto_mt_title -> prevents &mt()ing the title arg
             inherit_jsmath -> when creating popup window in a page,              inherit_jsmath -> when creating popup window in a page,
Line 4754  other decorations will be returned. Line 4980  other decorations will be returned.
   
 sub bodytag {  sub bodytag {
     my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,      my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,
         $no_nav_bar,$bgcolor,$args)=@_;          $no_nav_bar,$bgcolor,$no_inline_link,$args)=@_;
   
     my $public;      my $public;
     if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))      if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
Line 4796  sub bodytag { Line 5022  sub bodytag {
     }      }
   
     if (!$realm) { $realm='&nbsp;'; }      if (!$realm) { $realm='&nbsp;'; }
   # Set messages
       my $messages=&domainlogo($domain);
   
     my $extra_body_attr = &make_attr_string($forcereg,\%design);      my $extra_body_attr = &make_attr_string($forcereg,\%design);
   
Line 4811  sub bodytag { Line 5039  sub bodytag {
     if ($public) {      if ($public) {
  undef($role);   undef($role);
     } else {      } else {
  $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});   $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'},
                                   undef,'LC_menubuttons_link');
     }      }
           
     my $titleinfo = '<h1>'.$title.'</h1>';      my $titleinfo = '<h1>'.$title.'</h1>';
Line 4829  sub bodytag { Line 5058  sub bodytag {
     $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;      $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;
     &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);      &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
   
         if ($no_nav_bar || $env{'form.inhibitmenu'} eq 'yes') {       if ($no_nav_bar || $env{'form.inhibitmenu'} eq 'yes') { 
             return $bodytag;           return $bodytag; 
         }       }
   
         if ($env{'request.state'} eq 'construct') { $forcereg=1; }      if ($env{'request.state'} eq 'construct') { $forcereg=1; }
   
       unless ($env{'environment.remote'} eq 'on') {
   
         #    if ($env{'request.state'} eq 'construct') {          #    if ($env{'request.state'} eq 'construct') {
         #        $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls          #        $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls
Line 4842  sub bodytag { Line 5073  sub bodytag {
   
   
         if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {          if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
              if ($dc_info) {              unless ($env{'request.noversionuri'} =~ m{/res/adm/pages/bookmarkmenu/}) {
                  $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;                  if ($dc_info) {
              }                       $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;
              $bodytag .= qq|<div id="LC_nav_bar">$name $role<br />                  }
                 <em>$realm</em> $dc_info</div>|;                  $bodytag .= qq|<div id="LC_nav_bar">$name $role<br />
                                  <em>$realm</em> $dc_info</div>|;
               }
             return $bodytag;              return $bodytag;
         }          }
   
Line 4883  sub bodytag { Line 5116  sub bodytag {
         }          }
   
         return $bodytag;          return $bodytag;
       }
   
   #
   # Top frame rendering, Remote is up
   #
   
       my $imgsrc = $img;
       if ($img =~ /^\/adm/) {
           $imgsrc = &lonhttpdurl($img);
       }
       my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />';
   
       # Explicit link to get inline menu
       my $menu= ($no_inline_link?''
                  :'<a href="/adm/remote?action=collapse" target="_top">'.&mt('Switch to Inline Menu Mode').'</a>');
   
       if ($dc_info) {
           $dc_info = qq|<span class="LC_cusr_subheading">($dc_info)</span>|;
       }
   
       unless ($env{'form.inhibitmenu'}) {
           $bodytag .= qq|<div id="LC_nav_bar">$name $role</div>
                          <ol class="LC_primary_menu LC_right">
                          <li>$menu</li>
                          </ol><div id="LC_realm"> $realm $dc_info</div>|;
       }
       my $funclist;
       if ($env{'request.state'} eq 'construct') {
           if (!$public){
               if ($env{'request.state'} eq 'construct') {
                   $funclist = &Apache::lonhtmlcommon::scripttag(
                                   &Apache::lonmenu::utilityfunctions(), 'start').
                               &Apache::lonhtmlcommon::scripttag('','end').
                               &Apache::lonmenu::innerregister($forcereg,
                                                               $args->{'bread_crumbs'});
               }
           }
       }
       return(<<ENDBODY);
   $bodytag
   <table id="LC_title_bar" class="LC_with_remote">
   <tr><td>$upperleft</td>
       <td>$messages&nbsp;</td>
   </tr>
   <tr><td>$titleinfo $dc_info $menu</td>
   </tr>
   </table>
   $funclist
   ENDBODY
 }  }
   
 sub dc_courseid_toggle {  sub dc_courseid_toggle {
     my ($dc_info) = @_;      my ($dc_info) = @_;
     return ' <span id="dccidtext" class="LC_cusr_subheading LC_nobreak">'.      return ' <span id="dccidtext" class="LC_cusr_subheading LC_nobreak">'.
            '<a href="javascript:showCourseID();">'.             '<a href="javascript:showCourseID();" class="LC_menubuttons_link">'.
            &mt('(More ...)').'</a></span>'.             &mt('(More ...)').'</a></span>'.
            '<div id="dccid" class="LC_dccid">'.$dc_info.'</div>';             '<div id="dccid" class="LC_dccid">'.$dc_info.'</div>';
 }  }
Line 4914  sub make_attr_string { Line 5196  sub make_attr_string {
  delete($attr_ref->{$key});   delete($attr_ref->{$key});
     }      }
  }   }
  $attr_ref->{'onload'}  = $on_load;          if ($env{'environment.remote'} eq 'on') {
  $attr_ref->{'onunload'}= $on_unload;              $attr_ref->{'onload'}  =
                   &Apache::lonmenu::loadevents().  $on_load;
               $attr_ref->{'onunload'}=
                   &Apache::lonmenu::unloadevents().$on_unload;
           } else {  
       $attr_ref->{'onload'}  = $on_load;
       $attr_ref->{'onunload'}= $on_unload;
           }
     }      }
   
     my $attr_string;      my $attr_string;
Line 4945  i.e., $env{'internal.head.redirect'} exi Line 5234  i.e., $env{'internal.head.redirect'} exi
   
 sub endbodytag {  sub endbodytag {
     my ($args) = @_;      my ($args) = @_;
     my $endbodytag='</body>';      my $endbodytag;
       unless ((ref($args) eq 'HASH') && ($args->{'notbody'})) {
           $endbodytag='</body>';
       }
     $endbodytag=&Apache::lontexconvert::jsMath_process()."\n".$endbodytag;      $endbodytag=&Apache::lontexconvert::jsMath_process()."\n".$endbodytag;
     if ( exists( $env{'internal.head.redirect'} ) ) {      if ( exists( $env{'internal.head.redirect'} ) ) {
         if (!(ref($args) eq 'HASH' && $args->{'noredirectlink'})) {          if (!(ref($args) eq 'HASH' && $args->{'noredirectlink'})) {
Line 4993  sub standard_css { Line 5285  sub standard_css {
     my $mono                 = 'monospace';      my $mono                 = 'monospace';
     my $data_table_head      = $sidebg;      my $data_table_head      = $sidebg;
     my $data_table_light     = '#FAFAFA';      my $data_table_light     = '#FAFAFA';
     my $data_table_dark      = '#F0F0F0';      my $data_table_dark      = '#E0E0E0';
     my $data_table_darker    = '#CCCCCC';      my $data_table_darker    = '#CCCCCC';
     my $data_table_highlight = '#FFFF00';      my $data_table_highlight = '#FFFF00';
     my $mail_new             = '#FFBB77';      my $mail_new             = '#FFBB77';
Line 6080  div.LC_edit_problem_footer { Line 6372  div.LC_edit_problem_footer {
   font-weight: normal;    font-weight: normal;
   font-size:  medium;    font-size:  medium;
   margin: 2px;    margin: 2px;
     background-color: $sidebg;
 }  }
   
 div.LC_edit_problem_header,  div.LC_edit_problem_header,
Line 6096  div.LC_edit_problem_header_title { Line 6389  div.LC_edit_problem_header_title {
   font-size: larger;    font-size: larger;
   background: $tabbg;    background: $tabbg;
   padding: 3px;    padding: 3px;
     margin: 0 0 5px 0;
 }  }
   
 table.LC_edit_problem_header_title {  table.LC_edit_problem_header_title {
Line 6226  fieldset > legend { Line 6520  fieldset > legend {
 ol.LC_primary_menu {  ol.LC_primary_menu {
   float: right;    float: right;
   margin: 0;    margin: 0;
     padding: 0;
   background-color: $pgbg_or_bgcolor;    background-color: $pgbg_or_bgcolor;
 }  }
   
Line 6234  ol#LC_PathBreadcrumbs { Line 6529  ol#LC_PathBreadcrumbs {
 }  }
   
 ol.LC_primary_menu li {  ol.LC_primary_menu li {
   display: inline;    color: RGB(80, 80, 80);
   padding: 5px 5px 0 10px;    vertical-align: middle;
     text-align: left;
     list-style: none;
     float: left;
   }
   
   ol.LC_primary_menu li a {
     display: block;
     margin: 0;
     padding: 0 5px 0 10px;
     text-decoration: none;
   }
   
   ol.LC_primary_menu li ul {
     display: none;
     width: 10em;
     background-color: $data_table_light;
   }
   
   ol.LC_primary_menu li:hover ul, ol.LC_primary_menu li.hover ul {
     display: block;
     position: absolute;
     margin: 0;
     padding: 0;
     z-index: 2;
   }
   
   ol.LC_primary_menu li:hover li, ol.LC_primary_menu li.hover li {
     font-size: 90%;
   vertical-align: top;    vertical-align: top;
     float: none;
     border-left: 1px solid black;
     border-right: 1px solid black;
   }
   
   ol.LC_primary_menu li:hover li a, ol.LC_primary_menu li.hover li a {
     background-color:$data_table_light;
   }
   
   ol.LC_primary_menu li li a:hover {
      color:$button_hover;
      background-color:$data_table_dark;
 }  }
   
 ol.LC_primary_menu li img {  ol.LC_primary_menu li img {
   vertical-align: bottom;    vertical-align: bottom;
   height: 1.1em;    height: 1.1em;
     margin: 0.2em 0 0 0;
 }  }
   
 ol.LC_primary_menu a {  ol.LC_primary_menu a {
Line 6287  ul#LC_secondary_menu { Line 6623  ul#LC_secondary_menu {
   margin: 0;    margin: 0;
   width: 100%;    width: 100%;
   text-align: left;    text-align: left;
     float: left;
 }  }
   
 ul#LC_secondary_menu li {  ul#LC_secondary_menu li {
   font-weight: bold;    font-weight: bold;
   line-height: 1.8em;    line-height: 1.8em;
   padding: 0 0.8em;  
   border-right: 1px solid black;    border-right: 1px solid black;
   display: inline;  
   vertical-align: middle;    vertical-align: middle;
     float: left;
   }
   
   ul#LC_secondary_menu li.LC_hoverable:hover, ul#LC_secondary_menu li.hover {
     background-color: $data_table_light;
   }
   
   ul#LC_secondary_menu li a {
     padding: 0 0.8em;
   }
   
   ul#LC_secondary_menu li ul {
     display: none;
   }
   
   ul#LC_secondary_menu li:hover ul, ul#LC_secondary_menu li.hover ul {
     display: block;
     position: absolute;
     margin: 0;
     padding: 0;
     list-style:none;
     float: none;
     background-color: $data_table_light;
     z-index: 2;
     margin-left: -1px;
   }
   
   ul#LC_secondary_menu li ul li {
     font-size: 90%;
     vertical-align: top;
     border-left: 1px solid black;
     border-right: 1px solid black;
     background-color: $data_table_light
     list-style:none;
     float: none;
   }
   
   ul#LC_secondary_menu li ul li:hover, ul#LC_secondary_menu li ul li.hover {
     background-color: $data_table_dark;
 }  }
   
 ul.LC_TabContent {  ul.LC_TabContent {
Line 6635  ul#LC_toolbar { Line 7009  ul#LC_toolbar {
   list-style:none;    list-style:none;
   position:relative;    position:relative;
   background-color:white;    background-color:white;
     overflow: auto;
 }  }
   
 ul#LC_toolbar li {  ul#LC_toolbar li {
Line 6644  ul#LC_toolbar li { Line 7019  ul#LC_toolbar li {
   float: left;    float: left;
   display:inline;    display:inline;
   vertical-align:middle;    vertical-align:middle;
     white-space: nowrap;
 }  }
   
   
Line 6788  sub headtag { Line 7164  sub headtag {
  '<head>'.   '<head>'.
  &font_settings();   &font_settings();
   
       my $inhibitprint = &print_suppression();
   
     if (!$args->{'frameset'}) {      if (!$args->{'frameset'}) {
  $result .= &Apache::lonhtmlcommon::htmlareaheaders();   $result .= &Apache::lonhtmlcommon::htmlareaheaders();
     }      }
     if ($args->{'force_register'} && $env{'request.noversionuri'} !~ m{^/res/adm/pages/}) {      if ($args->{'force_register'}) {
         $result .= Apache::lonxml::display_title();          $result .= &Apache::lonmenu::registerurl(1);
     }      }
     if (!$args->{'no_nav_bar'}       if (!$args->{'no_nav_bar'} 
  && !$args->{'only_body'}   && !$args->{'only_body'}
Line 6833  ADDMETA Line 7211  ADDMETA
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }      if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
     $result .= '<title> LON-CAPA '.$title.'</title>'      $result .= '<title> LON-CAPA '.$title.'</title>'
  .'<link rel="stylesheet" type="text/css" href="'.$url.'" />'   .'<link rel="stylesheet" type="text/css" href="'.$url.'" />'
           .$inhibitprint
  .$head_extra;   .$head_extra;
     return $result.'</head>';      return $result.'</head>';
 }  }
Line 6858  sub font_settings { Line 7237  sub font_settings {
   
 =pod  =pod
   
   =item * &print_suppression()
   
   In course context returns css which causes the body to be blank when media="print",
   if printout generation is unavailable for the current resource.
   
   This could be because:
   
   (a) printstartdate is in the future
   
   (b) printenddate is in the past
   
   (c) there is an active exam block with "printout"
   functionality blocked
   
   Users with pav, pfo or evb privileges are exempt.
   
   Inputs: none
   
   =cut
   
   
   sub print_suppression {
       my $noprint;
       if ($env{'request.course.id'}) {
           my $scope = $env{'request.course.id'};
           if ((&Apache::lonnet::allowed('pav',$scope)) ||
               (&Apache::lonnet::allowed('pfo',$scope))) {
               return;
           }
           if ($env{'request.course.sec'} ne '') {
               $scope .= "/$env{'request.course.sec'}";
               if ((&Apache::lonnet::allowed('pav',$scope)) ||
                   (&Apache::lonnet::allowed('pfo',$scope))) {
                   return;
               }
           }
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           my $blocked = &blocking_status('printout',$cnum,$cdom);
           if ($blocked) {
               my $checkrole = "cm./$cdom/$cnum";
               if ($env{'request.course.sec'} ne '') {
                   $checkrole .= "/$env{'request.course.sec'}";
               }
               unless ((&Apache::lonnet::allowed('evb',undef,undef,$checkrole)) &&
                       ($env{'request.role'} !~ m{^st\./$cdom/$cnum})) {
                   $noprint = 1;
               }
           }
           unless ($noprint) {
               my $symb = &Apache::lonnet::symbread();
               if ($symb ne '') {
                   my $navmap = Apache::lonnavmaps::navmap->new();
                   if (ref($navmap)) {
                       my $res = $navmap->getBySymb($symb);
                       if (ref($res)) {
                           if (!$res->resprintable()) {
                               $noprint = 1;
                           }
                       }
                   }
               }
           }
           if ($noprint) {
               return <<"ENDSTYLE";
   <style type="text/css" media="print">
       body { display:none }
   </style>
   ENDSTYLE
           }
       }
       return;
   }
   
   =pod
   
 =item * &xml_begin()  =item * &xml_begin()
   
 Returns the needed doctype and <html>  Returns the needed doctype and <html>
Line 6924  $args - additional optional args support Line 7379  $args - additional optional args support
              skip_phases    -> hash ref of                skip_phases    -> hash ref of 
                                     head -> skip the <html><head> generation                                      head -> skip the <html><head> generation
                                     body -> skip all <body> generation                                      body -> skip all <body> generation
                no_inline_link -> if true and in remote mode, don't show the
                                       'Switch To Inline Menu' link
              no_auto_mt_title -> prevent &mt()ing the title arg               no_auto_mt_title -> prevent &mt()ing the title arg
              inherit_jsmath -> when creating popup window in a page,               inherit_jsmath -> when creating popup window in a page,
                                     should it have jsmath forced on by the                                      should it have jsmath forced on by the
Line 6959  sub start_page { Line 7416  sub start_page {
                          $args->{'function'},       $args->{'add_entries'},                           $args->{'function'},       $args->{'add_entries'},
                          $args->{'only_body'},      $args->{'domain'},                           $args->{'only_body'},      $args->{'domain'},
                          $args->{'force_register'}, $args->{'no_nav_bar'},                           $args->{'force_register'}, $args->{'no_nav_bar'},
                          $args->{'bgcolor'},        $args);                           $args->{'bgcolor'},        $args->{'no_inline_link'},
                            $args);
         }          }
     }      }
   
Line 7016  sub end_page { Line 7474  sub end_page {
     } else {      } else {
  $result .= &endbodytag($args);   $result .= &endbodytag($args);
     }      }
     $result .= "\n</html>";      unless ($args->{'notbody'}) {
           $result .= "\n</html>";
       }
   
     if ($args->{'js_ready'}) {      if ($args->{'js_ready'}) {
  $result = &js_ready($result);   $result = &js_ready($result);
Line 7101  sub modal_link { Line 7561  sub modal_link {
     unless ($width) { $width=480; }      unless ($width) { $width=480; }
     unless ($height) { $height=400; }      unless ($height) { $height=400; }
     unless ($scrolling) { $scrolling='yes'; }      unless ($scrolling) { $scrolling='yes'; }
     return '<a href="'.$link.'" target="'.$target.'" title="'.$title.'" onclick="openMyModal(\''.$link.'\','.$width.','.$height.',\''.$scrolling.'\'); return false;">'.      my $target_attr;
            $linktext.'</a>';      if (defined($target)) {
           $target_attr = 'target="'.$target.'"';
       }
       return <<"ENDLINK";
   <a href="$link" $target_attr title="$title" onclick="javascript:openMyModal('$link',$width,$height,'$scrolling'); return false;">
              $linktext</a>
   ENDLINK
 }  }
   
 sub modal_adhoc_script {  sub modal_adhoc_script {
Line 7350  sub validate_page { Line 7816  sub validate_page {
   
   
 sub start_scrollbox {  sub start_scrollbox {
     my ($outerwidth,$width,$height,$id)=@_;      my ($outerwidth,$width,$height,$id,$bgcolor)=@_;
     unless ($outerwidth) { $outerwidth='520px'; }      unless ($outerwidth) { $outerwidth='520px'; }
     unless ($width) { $width='500px'; }      unless ($width) { $width='500px'; }
     unless ($height) { $height='200px'; }      unless ($height) { $height='200px'; }
     my ($table_id,$div_id);      my ($table_id,$div_id,$tdcol);
     if ($id ne '') {      if ($id ne '') {
         $table_id = " id='table_$id'";          $table_id = " id='table_$id'";
         $div_id = " id='div_$id'";          $div_id = " id='div_$id'";
     }      }
     return "<table style='width: $outerwidth; border: 1px solid none;'$table_id><tr><td style='width: $width;' bgcolor='#FFFFFF'><div style='overflow:auto; width:$width; height: $height;'$div_id>";      if ($bgcolor ne '') {
           $tdcol = "background-color: $bgcolor;";
       }
       return <<"END";
   <table style="width: $outerwidth; border: 1px solid none;"$table_id><tr><td style="width: $width;$tdcol"><div style="overflow:auto; width:$width; height: $height;"$div_id>
   END
 }  }
   
 sub end_scrollbox {  sub end_scrollbox {
Line 7585  role status: active, previous or future. Line 8056  role status: active, previous or future.
   
 sub check_user_status {  sub check_user_status {
     my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;      my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
     my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});      my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
     my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,$extra);  
     my @uroles = keys %userinfo;      my @uroles = keys %userinfo;
     my $srchstr;      my $srchstr;
     my $active_chk = 'none';      my $active_chk = 'none';
Line 8817  sub get_future_slots { Line 9287  sub get_future_slots {
   
 =pod  =pod
   
   =back
   
 =head1 HTTP Helpers  =head1 HTTP Helpers
   
 =over 4  =over 4
Line 8955  sub get_env_multiple { Line 9427  sub get_env_multiple {
   
 sub ask_for_embedded_content {  sub ask_for_embedded_content {
     my ($actionurl,$state,$allfiles,$codebase,$args)=@_;      my ($actionurl,$state,$allfiles,$codebase,$args)=@_;
     my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges);      my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges,
     my $num = 0;          %currsubfile,%unused,$rem);
       my $counter = 0;
       my $numnew = 0;
     my $numremref = 0;      my $numremref = 0;
     my $numinvalid = 0;      my $numinvalid = 0;
     my $numpathchg = 0;      my $numpathchg = 0;
     my $numexisting = 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');
   
       my $navmap;
       if ($env{'request.course.id'}) {
           $navmap = Apache::lonnavmaps::navmap->new();
       }
     if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {      if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
         my $current_path='/';          my $current_path='/';
         if ($env{'form.currentpath'}) {          if ($env{'form.currentpath'}) {
Line 8989  sub ask_for_embedded_content { Line 9472  sub ask_for_embedded_content {
         }          }
     } elsif ($actionurl eq '/adm/coursedocs') {      } elsif ($actionurl eq '/adm/coursedocs') {
         if (ref($args) eq 'HASH') {          if (ref($args) eq 'HASH') {
            $url = $args->{'docs_url'};              $url = $args->{'docs_url'};
            $toplevel = $url;              $toplevel = $url;
               if ($args->{'context'} eq 'paste') {
                   ($cdom,$cnum) = ($url =~ m{^\Q/uploaded/\E($match_domain)/($match_courseid)/});
                   ($path) =
                       ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});
                   $fileloc = &Apache::lonnet::filelocation('',$toplevel);
                   $fileloc =~ s{^/}{};
               }
           }
       } 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";
                   ($rem) = ($toplevel =~ m{^(.+/)[^/]+$});
                   ($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();      my $now = time();
Line 9029  sub ask_for_embedded_content { Line 9536  sub ask_for_embedded_content {
             }              }
         }          }
     }      }
       my $dirptr = 16384;
     foreach my $path (keys(%subdependencies)) {      foreach my $path (keys(%subdependencies)) {
         my %currsubfile;          $currsubfile{$path} = {};
         if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {           if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) { 
             my ($sublistref,$listerror) =              my ($sublistref,$listerror) =
                 &Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);                  &Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);
             if (ref($sublistref) eq 'ARRAY') {              if (ref($sublistref) eq 'ARRAY') {
                 foreach my $line (@{$sublistref}) {                  foreach my $line (@{$sublistref}) {
                     my ($file_name,$rest) = split(/\&/,$line,2);                      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')) {          } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
             if (opendir(my $dir,$url.'/'.$path)) {              if (opendir(my $dir,$url.'/'.$path)) {
                 my @subdir_list = grep(!/^\./,readdir($dir));                  my @subdir_list = grep(!/^\./,readdir($dir));
                 map {$currsubfile{$_} = 1;} @subdir_list;                  map {$currsubfile{$path}{$_} = 1;} @subdir_list;
               }
           } elsif (($actionurl eq '/adm/dependencies') ||
                    (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&
                     ($args->{'context'} eq 'paste'))) {
               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}})) {          foreach my $file (keys(%{$subdependencies{$path}})) {
             if ($currsubfile{$file}) {              if (exists($currsubfile{$path}{$file})) {
                 my $item = $path.'/'.$file;                  my $item = $path.'/'.$file;
                 unless ($mapping{$item} eq $item) {                  unless ($mapping{$item} eq $item) {
                     $pathchanges{$item} = 1;                      $pathchanges{$item} = 1;
Line 9058  sub ask_for_embedded_content { Line 9586  sub ask_for_embedded_content {
                 $newfiles{$path.'/'.$file} = 1;                  $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}) {
                                next if (($rem ne '') &&
                                         (($env{"httpref.$rem"."$path/$file"} ne '') ||
                                          (ref($navmap) &&
                                          (($navmap->getResourceByUrl($rem."$path/$file") ne '') ||
                                           (($file =~ /^(.*\.s?html?)\.bak$/i) &&
                                            ($navmap->getResourceByUrl($rem."$path/$1")))))));
                                $unused{$path.'/'.$file} = 1; 
                            }
                       }
                   }
               }
           }
     }      }
     my %currfile;      my %currfile;
     if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {      if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
Line 9074  sub ask_for_embedded_content { Line 9619  sub ask_for_embedded_content {
             my @dir_list = grep(!/^\./,readdir($dir));              my @dir_list = grep(!/^\./,readdir($dir));
             map {$currfile{$_} = 1;} @dir_list;              map {$currfile{$_} = 1;} @dir_list;
         }          }
       } elsif (($actionurl eq '/adm/dependencies') ||
                (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&
                 ($args->{'context'} eq 'paste'))) {
           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)) {      foreach my $file (keys(%dependencies)) {
         if ($currfile{$file}) {          if (exists($currfile{$file})) {
             unless ($mapping{$file} eq $file) {              unless ($mapping{$file} eq $file) {
                 $pathchanges{$file} = 1;                  $pathchanges{$file} = 1;
             }              }
Line 9086  sub ask_for_embedded_content { Line 9651  sub ask_for_embedded_content {
             $newfiles{$file} = 1;              $newfiles{$file} = 1;
         }          }
     }      }
       foreach my $file (keys(%currfile)) {
           unless (($file eq $filename) ||
                   ($file eq $filename.'.bak') ||
                   ($dependencies{$file})) {
               if ($actionurl eq '/adm/dependencies') {
                   next if (($rem ne '') &&
                            (($env{"httpref.$rem".$file} ne '') ||
                             (ref($navmap) &&
                             (($navmap->getResourceByUrl($rem.$file) ne '') ||
                              (($file =~ /^(.*\.s?html?)\.bak$/i) &&
                               ($navmap->getResourceByUrl($rem.$1)))))));
               }
               $unused{$file} = 1;
           }
       }
       if (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&
           ($args->{'context'} eq 'paste')) {
           $counter = scalar(keys(%existing));
           $numpathchg = scalar(keys(%pathchanges));
           return ($output,$counter,$numpathchg,\%existing);
       }
     foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) {      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().          $upload_output .= &start_data_table_row().
                           '<td><span class="LC_filename">'.$embed_file.'</span>';                            '<td><img src="'.&icon($embed_file).'" />&nbsp;'.
                             '<span class="LC_filename">'.$embed_file.'</span>';
         unless ($mapping{$embed_file} eq $embed_file) {          unless ($mapping{$embed_file} eq $embed_file) {
             $upload_output .= '<br /><span class="LC_info" style="font-size:smaller;">'.&mt('changed from: [_1]',$mapping{$embed_file}).'</span>';              $upload_output .= '<br /><span class="LC_info" style="font-size:smaller;">'.&mt('changed from: [_1]',$mapping{$embed_file}).'</span>';
         }          }
         $upload_output .= '</td><td>';          $upload_output .= '</td><td>';
         if ($args->{'ignore_remote_references'}          if ($args->{'ignore_remote_references'} && $embed_file =~ m{^\w+://}) { 
             && $embed_file =~ m{^\w+://}) {  
             $upload_output.='<span class="LC_warning">'.&mt("URL points to other server.").'</span>';              $upload_output.='<span class="LC_warning">'.&mt("URL points to other server.").'</span>';
             $numremref++;              $numremref++;
         } elsif ($args->{'error_on_invalid_names'}          } elsif ($args->{'error_on_invalid_names'}
             && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) {              && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) {
   
             $upload_output.='<span class="LC_warning">'.&mt('Invalid characters').'</span>';              $upload_output.='<span class="LC_warning">'.&mt('Invalid characters').'</span>';
             $numinvalid++;              $numinvalid++;
         } else {          } else {
             $upload_output .= &embedded_file_element('upload_embedded',$num,              $upload_output .= &embedded_file_element('upload_embedded',$counter,
                                                      $embed_file,\%mapping,                                                       $embed_file,\%mapping,
                                                      $allfiles,$codebase);                                                       $allfiles,$codebase,'upload');
             $num++;              $counter ++;
               $numnew ++;
         }          }
         $upload_output .= '</td>'.&Apache::loncommon::end_data_table_row()."\n";          $upload_output .= '</td>'.&Apache::loncommon::end_data_table_row()."\n";
     }      }
     foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%existing)) {      foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%existing)) {
         $upload_output .= &start_data_table_row().          if ($actionurl eq '/adm/dependencies') {
                           '<td><span class="LC_filename">'.$embed_file.'</span></td>'.              my ($size,$mtime) = &get_dependency_details(\%currfile,\%currsubfile,$embed_file);
                           '<td><span class="LC_warning">'.&mt('Already exists').'</span></td>'.              $modify_output .= &start_data_table_row().
                           &Apache::loncommon::end_data_table_row()."\n";                                '<td><a href="'.$path.'/'.$embed_file.'" style="text-decoration:none;">'.
                                 '<img src="'.&icon($embed_file).'" border="0" />'.
                                 '&nbsp;<span class="LC_filename">'.$embed_file.'</span></a></td>'.
                                 '<td>'.$size.'</td>'.
                                 '<td>'.$mtime.'</td>'.
                                 '<td><label><input type="checkbox" name="mod_upload_dep" '.
                                 'onclick="toggleBrowse('."'$counter'".')" id="mod_upload_dep_'.
                                 $counter.'" value="'.$counter.'" />'.&mt('Yes').'</label>'.
                                 '<div id="moduploaddep_'.$counter.'" style="display:none;">'.
                                 &embedded_file_element('upload_embedded',$counter,
                                                        $embed_file,\%mapping,
                                                        $allfiles,$codebase,'modify').
                                 '</div></td>'.
                                 &end_data_table_row()."\n";
               $counter ++;
           } else {
               $upload_output .= &start_data_table_row().
                                 '<td><span class="LC_filename">'.$embed_file.'</span></td>';
                                 '<td><span class="LC_warning">'.&mt('Already exists').'</span></td>'.
                                 &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().
                             '<td><img src="'.&icon($oldfile).'" />'.
                             '&nbsp;<span class="LC_filename">'.$oldfile.'</span></td>'.
                             '<td>'.$size.'</td>'.
                             '<td>'.$mtime.'</td>'.
                             '<td><label><input type="checkbox" name="del_upload_dep" '.
                             ' value="'.$delidx.'" />'.&mt('Yes').'</label>'.
                             &embedded_file_element('upload_embedded',$delidx,
                                                    $oldfile,\%mapping,$allfiles,
                                                    $codebase,'delete').'</td>'.
                             &end_data_table_row()."\n"; 
           $numunused ++;
           $delidx ++;
     }      }
     if ($upload_output) {      if ($upload_output) {
         $upload_output = &start_data_table().          $upload_output = &start_data_table().
                          $upload_output.                           $upload_output.
                          &end_data_table()."\n";                           &end_data_table()."\n";
     }      }
       if ($modify_output) {
           $modify_output = &start_data_table().
                            &start_data_table_header_row().
                            '<th>'.&mt('File').'</th>'.
                            '<th>'.&mt('Size (KB)').'</th>'.
                            '<th>'.&mt('Modified').'</th>'.
                            '<th>'.&mt('Upload replacement?').'</th>'.
                            &end_data_table_header_row().
                            $modify_output.
                            &end_data_table()."\n";
       }
       if ($delete_output) {
           $delete_output = &start_data_table().
                            &start_data_table_header_row().
                            '<th>'.&mt('File').'</th>'.
                            '<th>'.&mt('Size (KB)').'</th>'.
                            '<th>'.&mt('Modified').'</th>'.
                            '<th>'.&mt('Delete?').'</th>'.
                            &end_data_table_header_row().
                            $delete_output.
                            &end_data_table()."\n";
       }
     my $applies = 0;      my $applies = 0;
     if ($numremref) {      if ($numremref) {
         $applies ++;          $applies ++;
Line 9131  sub ask_for_embedded_content { Line 9779  sub ask_for_embedded_content {
     if ($numexisting) {      if ($numexisting) {
         $applies ++;          $applies ++;
     }      }
     if ($num) {      if ($counter || $numunused) {
         $output = '<form name="upload_embedded" action="'.$actionurl.'"'.          $output = '<form name="upload_embedded" action="'.$actionurl.'"'.
                   ' method="post" enctype="multipart/form-data">'."\n".                    ' method="post" enctype="multipart/form-data">'."\n".
                   $state.                    $state.'<h3>'.$heading.'</h3>'; 
                   '<h3>'.&mt('Upload embedded files').          if ($actionurl eq '/adm/dependencies') {
                   ':</h3>'.$upload_output.'<br />'."\n".              if ($numnew) {
                   '<input type ="hidden" name="number_embedded_items" value="'.                  $output .= '<h4>'.&mt('Missing dependencies').'</h4>'.
                   $num.'" />'."\n";                             '<p>'.&mt('The following files need to be uploaded.').'</p>'."\n".
         if ($actionurl eq '') {                             $upload_output.'<br />'."\n";
               }
               if ($numexisting) {
                   $output .= '<h4>'.&mt('Uploaded dependencies (in use)').'</h4>'.
                              '<p>'.&mt('Upload a new file to replace the one currently in use.').'</p>'."\n".
                              $modify_output.'<br />'."\n";
                              $buttontext = &mt('Save changes');
               }
               if ($numunused) {
                   $output .= '<h4>'.&mt('Unused files').'</h4>'.
                              '<p>'.&mt('The following uploaded files are no longer used.').'</p>'."\n".
                              $delete_output.'<br />'."\n";
                              $buttontext = &mt('Save changes');
               }
           } else {
               $output .= $upload_output.'<br />'."\n";
           }
           $output .= '<input type ="hidden" name="number_embedded_items" value="'.
                      $counter.'" />'."\n";
           if ($actionurl eq '/adm/dependencies') { 
               $output .= '<input type ="hidden" name="number_newemb_items" value="'.
                          $numnew.'" />'."\n";
           } elsif ($actionurl eq '') {
             $output .=  '<input type="hidden" name="phase" value="three" />';              $output .=  '<input type="hidden" name="phase" value="three" />';
         }          }
     } elsif ($applies) {      } elsif ($applies) {
Line 9167  sub ask_for_embedded_content { Line 9837  sub ask_for_embedded_content {
         $output .= $upload_output.'<br />';          $output .= $upload_output.'<br />';
     }      }
     my ($pathchange_output,$chgcount);      my ($pathchange_output,$chgcount);
     $chgcount = $num;      $chgcount = $counter;
     if (keys(%pathchanges) > 0) {      if (keys(%pathchanges) > 0) {
         foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%pathchanges)) {          foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%pathchanges)) {
             if ($num) {              if ($counter) {
                 $output .= &embedded_file_element('pathchange',$chgcount,                  $output .= &embedded_file_element('pathchange',$chgcount,
                                                   $embed_file,\%mapping,                                                    $embed_file,\%mapping,
                                                   $allfiles,$codebase);                                                    $allfiles,$codebase,'change');
             } else {              } else {
                 $pathchange_output .=                   $pathchange_output .= 
                     &start_data_table_row().                      &start_data_table_row().
Line 9182  sub ask_for_embedded_content { Line 9852  sub ask_for_embedded_content {
                     '<td>'.$mapping{$embed_file}.'</td>'.                      '<td>'.$mapping{$embed_file}.'</td>'.
                     '<td>'.$embed_file.                      '<td>'.$embed_file.
                     &embedded_file_element('pathchange',$numpathchg,$embed_file,                      &embedded_file_element('pathchange',$numpathchg,$embed_file,
                                            \%mapping,$allfiles,$codebase).                                             \%mapping,$allfiles,$codebase,'change').
                     '</td>'.&end_data_table_row();                      '</td>'.&end_data_table_row();
             }              }
             $numpathchg ++;              $numpathchg ++;
             $chgcount ++;              $chgcount ++;
         }          }
     }      }
     if ($num) {      if ($counter) {
         if ($numpathchg) {          if ($numpathchg) {
             $output .= '<input type ="hidden" name="number_pathchange_items" value="'.              $output .= '<input type ="hidden" name="number_pathchange_items" value="'.
                        $numpathchg.'" />'."\n";                         $numpathchg.'" />'."\n";
Line 9199  sub ask_for_embedded_content { Line 9869  sub ask_for_embedded_content {
             $output .= '<input type="hidden" name="phase" value="three" />'."\n";              $output .= '<input type="hidden" name="phase" value="three" />'."\n";
         } elsif ($actionurl eq '/adm/portfolio' || $actionurl eq '/adm/coursegrp_portfolio') {          } elsif ($actionurl eq '/adm/portfolio' || $actionurl eq '/adm/coursegrp_portfolio') {
             $output .= '<input type="hidden" name="action" value="upload_embedded" />';              $output .= '<input type="hidden" name="action" value="upload_embedded" />';
           } elsif ($actionurl eq '/adm/dependencies') {
               $output .= '<input type="hidden" name="action" value="process_changes" />';
         }          }
         $output .=  '<input type ="submit" value="'.&mt('Upload Listed Files').'" />'."\n".          $output .=  '<input type ="submit" value="'.$buttontext.'" />'."\n".'</form>'."\n";
                     &mt('(only files for which a location has been provided will be uploaded)').'</form>'."\n";  
     } elsif ($numpathchg) {      } elsif ($numpathchg) {
         my %pathchange = ();          my %pathchange = ();
         $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);          $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);
Line 9209  sub ask_for_embedded_content { Line 9880  sub ask_for_embedded_content {
             $output .= '<p>'.&mt('or').'</p>';               $output .= '<p>'.&mt('or').'</p>'; 
         }           } 
     }      }
     return ($output,$num,$numpathchg);      return ($output,$counter,$numpathchg);
 }  }
   
 sub embedded_file_element {  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') &&      return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&
                    (ref($codebase) eq 'HASH'));                     (ref($codebase) eq 'HASH'));
     my $output;      my $output;
     if ($context eq 'upload_embedded') {      if (($context eq 'upload_embedded') && ($type ne 'delete')) {
        $output = '<input name="embedded_item_'.$num.'" type="file" value="" />'."\n";         $output = '<input name="embedded_item_'.$num.'" type="file" value="" />'."\n";
     }      }
     $output .= '<input name="embedded_orig_'.$num.'" type="hidden" value="'.      $output .= '<input name="embedded_orig_'.$num.'" type="hidden" value="'.
Line 9244  sub embedded_file_element { Line 9915  sub embedded_file_element {
     return $output;      return $output;
 }  }
   
   sub get_dependency_details {
       my ($currfile,$currsubfile,$embed_file) = @_;
       my ($size,$mtime,$showsize,$showmtime);
       if ((ref($currfile) eq 'HASH') && (ref($currsubfile))) {
           if ($embed_file =~ m{/}) {
               my ($path,$fname) = split(/\//,$embed_file);
               if (ref($currsubfile->{$path}{$fname}) eq 'ARRAY') {
                   ($size,$mtime) = @{$currsubfile->{$path}{$fname}};
               }
           } else {
               if (ref($currfile->{$embed_file}) eq 'ARRAY') {
                   ($size,$mtime) = @{$currfile->{$embed_file}};
               }
           }
           $showsize = $size/1024.0;
           $showsize = sprintf("%.1f",$showsize);
           if ($mtime > 0) {
               $showmtime = &Apache::lonlocal::locallocaltime($mtime);
           }
       }
       return ($showsize,$showmtime);
   }
   
   sub ask_embedded_js {
       return <<"END";
   <script type="text/javascript"">
   // <![CDATA[
   function toggleBrowse(counter) {
       var chkboxid = document.getElementById('mod_upload_dep_'+counter);
       var fileid = document.getElementById('embedded_item_'+counter);
       var uploaddivid = document.getElementById('moduploaddep_'+counter);
       if (chkboxid.checked == true) {
           uploaddivid.style.display='block';
       } else {
           uploaddivid.style.display='none';
           fileid.value = '';
       }
   }
   // ]]>
   </script>
   
   END
   }
   
 sub upload_embedded {  sub upload_embedded {
     my ($context,$dirpath,$uname,$udom,$dir_root,$url_root,$group,$disk_quota,      my ($context,$dirpath,$uname,$udom,$dir_root,$url_root,$group,$disk_quota,
         $current_disk_usage,$hiddenstate,$actionurl) = @_;          $current_disk_usage,$hiddenstate,$actionurl) = @_;
Line 9302  sub upload_embedded { Line 10017  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).'<br />';              $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).'<br />';
             next;              next;
         }          }
   
         $env{'form.embedded_item_'.$i.'.filename'}=$fname;          $env{'form.embedded_item_'.$i.'.filename'}=$fname;
         if ($context eq 'portfolio') {          if ($context eq 'portfolio') {
             my $result;              my $result;
Line 9359  sub upload_embedded { Line 10073  sub upload_embedded {
             if (!open($fh,'>'.$dest)) {              if (!open($fh,'>'.$dest)) {
                 &Apache::lonnet::logthis('Failed to create '.$dest);                  &Apache::lonnet::logthis('Failed to create '.$dest);
                 $output .= '<span class="LC_error">'.                  $output .= '<span class="LC_error">'.
                            &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}).
                            '</span><br />';                             '</span><br />';
             } else {              } else {
                 if (!print $fh $env{'form.embedded_item_'.$i}) {                  if (!print $fh $env{'form.embedded_item_'.$i}) {
                     &Apache::lonnet::logthis('Failed to write to '.$dest);                      &Apache::lonnet::logthis('Failed to write to '.$dest);
                     $output .= '<span class="LC_error">'.                      $output .= '<span class="LC_error">'.
                               &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}).
                               '</span><br />';                                '</span><br />';
                 } else {                  } else {
                     $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.                      $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
Line 9387  sub upload_embedded { Line 10103  sub upload_embedded {
     }      }
     $output .= &modify_html_form('upload_embedded',$actionurl,$hiddenstate,\%pathchange);      $output .= &modify_html_form('upload_embedded',$actionurl,$hiddenstate,\%pathchange);
     $returnflag = 'ok';      $returnflag = 'ok';
     if (keys(%pathchange) > 0) {      my $numpathchgs = scalar(keys(%pathchange));
       if ($numpathchgs > 0) {
         if ($context eq 'portfolio') {          if ($context eq 'portfolio') {
             $output .= '<p>'.&mt('or').'</p>';              $output .= '<p>'.&mt('or').'</p>';
         } elsif ($context eq 'testbank') {          } elsif ($context eq 'testbank') {
             $output .=  '<p>'.&mt('Or [_1]continue[_2] the testbank import without modifying the reference(s).','<a href="javascript:document.testbankForm.submit();">','</a>').'</p>';              $output .=  '<p>'.&mt('Or [_1]continue[_2] the testbank import without modifying the reference(s).',
                                     '<a href="javascript:document.testbankForm.submit();">','</a>').'</p>';
             $returnflag = 'modify_orightml';              $returnflag = 'modify_orightml';
         }          }
     }      }
     return ($output.$footer,$returnflag);      return ($output.$footer,$returnflag,$numpathchgs);
 }  }
   
 sub modify_html_form {  sub modify_html_form {
Line 9430  sub modify_html_form { Line 10148  sub modify_html_form {
                     '<input type="hidden" name="embedded_orig_'.$i.'" value="'.                      '<input type="hidden" name="embedded_orig_'.$i.'" value="'.
                     &escape($env{'form.embedded_orig_'.$i}).'" /></td>'.                      &escape($env{'form.embedded_orig_'.$i}).'" /></td>'.
                     &end_data_table_row();                      &end_data_table_row();
             }               }
         }          }
     } else {      } else {
         $modifyform = $pathchgtable;          $modifyform = $pathchgtable;
Line 9441  sub modify_html_form { Line 10159  sub modify_html_form {
         }          }
     }      }
     if ($modifyform) {      if ($modifyform) {
           if ($actionurl eq '/adm/dependencies') {
               $hiddenstate .= '<input type="hidden" name="action" value="modifyhrefs" />';
           }
         return '<h3>'.&mt('Changes in content of HTML file required').'</h3>'."\n".          return '<h3>'.&mt('Changes in content of HTML file required').'</h3>'."\n".
                '<p>'.&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:').'<ol>'."\n".                 '<p>'.&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:').'<ol>'."\n".
                '<li>'.&mt('For consistency between the reference(s) and the location of the corresponding stored file within LON-CAPA.').'</li>'."\n".                 '<li>'.&mt('For consistency between the reference(s) and the location of the corresponding stored file within LON-CAPA.').'</li>'."\n".
Line 9469  sub modify_html_refs { Line 10190  sub modify_html_refs {
         $container = $env{'form.container'};          $container = $env{'form.container'};
     } elsif ($context eq 'coursedoc') {      } elsif ($context eq 'coursedoc') {
         $container = $env{'form.primaryurl'};          $container = $env{'form.primaryurl'};
       } elsif ($context eq 'manage_dependencies') {
           (undef,undef,$container) = &Apache::lonnet::decode_symb($env{'form.symb'});
           $container = "/$container";
     } else {      } else {
         $container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'};          $container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'};
     }      }
     my (%allfiles,%codebase,$output,$content);      my (%allfiles,%codebase,$output,$content);
     my @changes = &get_env_multiple('form.namechange');      my @changes = &get_env_multiple('form.namechange');
     return unless (@changes > 0);      unless (@changes > 0) {
     if (($context eq 'portfolio') || ($context eq 'coursedoc')) {          if (wantarray) {
         return unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/});              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);          $content = &Apache::lonnet::getfile($container);
         return if ($content eq '-1');          if ($content eq '-1') {
               if (wantarray) {
                   return ('',0,0);
               } else {
                   return;
               }
           }
     } else {      } 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")) {          if (open(my $fh,"<$container")) {
             $content = join('', <$fh>);              $content = join('', <$fh>);
             close($fh);              close($fh);
         } else {          } else {
             return;              if (wantarray) {
                   return ('',0,0);
               } else {
                   return;
               }
         }          }
     }      }
     my ($count,$codebasecount) = (0,0);      my ($count,$codebasecount) = (0,0);
Line 9519  sub modify_html_refs { Line 10272  sub modify_html_refs {
             }              }
             if ($count || $codebasecount) {              if ($count || $codebasecount) {
                 my $saveresult;                  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);                      my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
                     if ($url eq $container) {                      if ($url eq $container) {
                         my ($fname) = ($container =~ m{/([^/]+)$});                          my ($fname) = ($container =~ m{/([^/]+)$});
                         $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',                          $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',
                                             $count,'<span class="LC_filename">'.                                              $count,'<span class="LC_filename">'.
                                             $fname.'</span>').'</p>';                                               $fname.'</span>').'</p>';
                     } else {                      } else {
                          $output = '<p class="LC_error">'.                           $output = '<p class="LC_error">'.
                                    &mt('Error: update failed for: [_1].',                                     &mt('Error: update failed for: [_1].',
Line 9552  sub modify_html_refs { Line 10306  sub modify_html_refs {
                      ' to modify references: '.$parse_result);                       ' to modify references: '.$parse_result);
         }          }
     }      }
     return $output;      if (wantarray) {
           return ($output,$count,$codebasecount);
       } else {
           return $output;
       }
 }  }
   
 sub check_for_existing {  sub check_for_existing {
Line 9719  sub is_archive_file { Line 10477  sub is_archive_file {
 }  }
   
 sub decompress_form {  sub decompress_form {
     my ($mimetype,$archiveurl,$action,$noextract,$hiddenelements) = @_;      my ($mimetype,$archiveurl,$action,$noextract,$hiddenelements,$dirlist) = @_;
     my %lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
         this => 'This file is an archive file.',          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.',          youm => 'You may wish to extract its contents.',
         camt => 'Extraction of contents is recommended for Camtasia zip files.',  
         perm => 'Permanently remove archive file after extraction of contents?',  
         extr => 'Extract contents',          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',          yes  => 'Yes',
         no   => 'No',          no   => 'No',
           fold => 'Title for folder containing movie',
           movi => 'Title for page containing embedded movie', 
     );      );
     my $output = '<p>'.$lt{'this'}.' '.$lt{'youm'}.'<br />';      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)}) {      if ($mimetype =~ m{^application/(x\-)?(compressed|zip)}) {
         $output .= $lt{'camt'};          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;
           }
     }      }
     $output .= '</p>';      my $output;
     $output .= <<"START";      if ($is_camtasia) {
 <div id="uploadfileresult">          $output = <<"ENDCAM";
   <form name="uploaded_decompress" action="$action" method="post">  <script type="text/javascript" language="Javascript">
   <input type="hidden" name="archiveurl" value="$archiveurl" />  // <![CDATA[
 START  
   function camtasiaToggle() {
       for (var i=0; i<document.uploaded_decompress.autoextract_camtasia.length; i++) {
           if (document.uploaded_decompress.autoextract_camtasia[i].checked) {
               if (document.uploaded_decompress.autoextract_camtasia[i].value == 1) {
   
                   document.getElementById('camtasia_titles').style.display='block';
               } else {
                   document.getElementById('camtasia_titles').style.display='none';
               }
           }
       }
       return;
   }
   
   // ]]>
   </script>
   <p>$lt{'camt'}</p>
   ENDCAM
       } else {
           $output = '<p>'.$lt{'this'};
           if ($info eq '') {
               $output .= ' '.$lt{'youm'}.'</p>'."\n";
           } else {
               $output .= ' '.$lt{'itsc'}.'</p>'."\n".
                          '<div><pre>'.$info.'</pre></div>';
           }
       }
       $output .= '<form name="uploaded_decompress" action="'.$action.'" method="post">'."\n";
       my $duplicates;
       my $num = 0;
       if (ref($dirlist) eq 'ARRAY') {
           foreach my $item (@{$dirlist}) {
               if (ref($item) eq 'ARRAY') {
                   if (exists($toplevel{$item->[0]})) {
                       $duplicates .= 
                           &start_data_table_row().
                           '<td><label><input type="radio" name="archive_overwrite_'.$num.'" '.
                           'value="0" checked="checked" />'.&mt('No').'</label>'.
                           '&nbsp;<label><input type="radio" name="archive_overwrite_'.$num.'" '.
                           'value="1" />'.&mt('Yes').'</label>'.
                           '<input type="hidden" name="archive_overwrite_name_'.$num.'" value="'.$item->[0].'" /></td>'."\n".
                           '<td>'.$item->[0].'</td>';
                       if ($item->[2]) {
                           $duplicates .= '<td>'.&mt('Directory').'</td>';
                       } else {
                           $duplicates .= '<td>'.&mt('File').'</td>';
                       }
                       $duplicates .= '<td>'.$item->[3].'</td>'.
                                      '<td>'.
                                      &Apache::lonlocal::locallocaltime($item->[4]).
                                      '</td>'.
                                      &end_data_table_row();
                       $num ++;
                   }
               }
           }
       }
       my $itemcount;
       if (@paths > 0) {
           $itemcount = scalar(@paths);
       } else {
           $itemcount = 1;
       }
       if ($is_camtasia) {
           $output .= $lt{'auto'}.'<br />'.
                      '<span class="LC_nobreak">'.$lt{'proa'}.'<label>'.
                      '<input type="radio" name="autoextract_camtasia" value="1" onclick="javascript:camtasiaToggle();" checked="checked" />'.
                      $lt{'yes'}.'</label>&nbsp;<label>'.
                      '<input type="radio" name="autoextract_camtasia" value="0" onclick="javascript:camtasiaToggle();" />'.
                      $lt{'no'}.'</label></span><br />'.
                      '<div id="camtasia_titles" style="display:block">'.
                      &Apache::lonhtmlcommon::start_pick_box().
                      &Apache::lonhtmlcommon::row_title($lt{'fold'}).
                      '<input type="textbox" name="camtasia_foldername" value="'.$env{'form.comment'}.'" />'."\n".
                      &Apache::lonhtmlcommon::row_closure().
                      &Apache::lonhtmlcommon::row_title($lt{'movi'}).
                      '<input type="textbox" name="camtasia_moviename" value="" />'."\n".
                      &Apache::lonhtmlcommon::row_closure(1).
                      &Apache::lonhtmlcommon::end_pick_box().
                      '</div>';
       }
       $output .= 
           '<input type="hidden" name="archive_overwrite_total" value="'.$num.'" />'.
           '<input type="hidden" name="archive_itemcount" value="'.$itemcount.'" />'.
           "\n";
       if ($duplicates ne '') {
           $output .= '<p><span class="LC_warning">'.
                      &mt('Warning: decompression of the archive will overwrite the following items which already exist:').'</span><br />'.  
                      &start_data_table().
                      &start_data_table_header_row().
                      '<th>'.&mt('Overwrite?').'</th>'.
                      '<th>'.&mt('Name').'</th>'.
                      '<th>'.&mt('Type').'</th>'.
                      '<th>'.&mt('Size').'</th>'.
                      '<th>'.&mt('Last modified').'</th>'.
                      &end_data_table_header_row().
                      $duplicates.
                      &end_data_table().
                      '</p>';
       }
       $output .= '<input type="hidden" name="archiveurl" value="'.$archiveurl.'" />'."\n";
     if (ref($hiddenelements) eq 'HASH') {      if (ref($hiddenelements) eq 'HASH') {
         foreach my $hidden (sort(keys(%{$hiddenelements}))) {          foreach my $hidden (sort(keys(%{$hiddenelements}))) {
             $output .= '<input type="hidden" name="'.$hidden.'" value="'.$hiddenelements->{$hidden}.'" />'."\n";              $output .= '<input type="hidden" name="'.$hidden.'" value="'.$hiddenelements->{$hidden}.'" />'."\n";
         }          }
     }      }
     $output .= <<"END";      $output .= <<"END";
 <input type="hidden" name="folderpath" value="$env{'form.folderpath'}" />  <br />
 <input type="hidden" name="pagepath" value="$env{'form.pagepath'}" />  
 <input type="hidden" name="cmd" value="$nextphase" />  
 <input type="hidden" name="newidx" value="$newidx" />  
 <input type="hidden" name="position" value="$position" />  
 <input type="hidden" name="phase" value="$nextphase" />  
 <span class="LC_nobreak">$lt{'perm'}&nbsp;  
 <label><input type="radio" name="archivedelete" value="0" checked="checked" />$lt{'no'}</label>&nbsp;&nbsp;  
 <label><input type="radio" name="archivedelete" value="1" />$lt{'yes'}</label></span><br />  
 <input type="submit" name="decompress" value="$lt{'extr'}" />  <input type="submit" name="decompress" value="$lt{'extr'}" />
 </form>  </form>
 $noextract  $noextract
 </div>  
 END  END
     return $output;      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 {  sub decompress_uploaded_file {
     my ($file,$dir) = @_;      my ($file,$dir) = @_;
     &Apache::lonnet::appenv({'cgi.file' => $file});      &Apache::lonnet::appenv({'cgi.file' => $file});
Line 9777  sub decompress_uploaded_file { Line 10712  sub decompress_uploaded_file {
     return ($decompressed,$result);      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.').
                    '<br />'.&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 = '<p class="LC_info">'.
                                 &mt('Files extracted successfully from archive.').
                                 '</p>'."\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 .= '<p class="LC_error">'.&mt('Not extracted.').'<br />'.
                      $error.'</p>'."\n";
       }
       if ($warning) {
           $output .= '<p class="LC_warning">'.$warning.'</p>'."\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().'<td align="right">'.$count.'</td>'."\n";
       my $offset = 0;
       foreach my $action ('display','dependency','discard') {
           $offset ++;
           if ($action ne 'display') {
               $offset ++;
           }  
           $output .= '<td><span class="LC_nobreak">'.
                      '<label><input type="radio" name="archive_'.$count.
                      '" id="archive_'.$action.'_'.$count.'" value="'.$action.'"';
           my $text = $choices{$action};
           if ($is_dir) {
               $output .= ' onclick="javascript:propagateCheck(this.form,'."'$count'".');"';
               if ($action eq 'display') {
                   $text = &mt('Add as folder');
               }
           } else {
               $output .= ' onclick="javascript:dependencyCheck(this.form,'."$count,$offset".');"';
   
           }
           $output .= ' />&nbsp;'.$choices{$action}.'</label></span>';
           if ($action eq 'dependency') {
               $output .= '<div id="arc_depon_'.$count.'" style="display:none;">'."\n".
                          &mt('Used by:').'&nbsp;<select name="archive_dependent_on_'.$count.'" '.
                          'onchange="propagateSelect(this.form,'."$count,$offset".')">'."\n".
                          '<option value=""></option>'."\n".
                          '</select>'."\n".
                          '</div>';
           } elsif ($action eq 'display') {
               $output .= '<div id="arc_title_'.$count.'" style="display:none;">'."\n".
                          &mt('Title:').'&nbsp;<input type="text" name="archive_title_'.$count.'" id="archive_title_'.$count.'" />'."\n".
                          '</div>';
           }
           $output .= '</td>';
       }
       $output .= '<td><input type="hidden" name="archive_content_'.$count.'" value="'.
                  &HTML::Entities::encode("$currdir/$item",'"<>&').'" />'.('&nbsp;' x 2);
       for (my $i=0; $i<$depth; $i++) {
           $output .= ('<img src="/adm/lonIcons/whitespace1.gif" class="LC_docs_spacer" alt="" />' x2)."\n";
       }
       if ($is_dir) {
           $output .= '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />&nbsp;'."\n".
                      '<input type="hidden" name="archive_directory" value="'.$count.'" />'."\n";
       } else {
           $output .= '<input type="hidden" name="archive_file" value="'.$count.'" />'."\n";
       }
       $output .= '&nbsp;'.$name.'</td>'."\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";
   <form name="$form" method="post" action="">
   <p><span class="LC_nobreak">$lt{'perm'}&nbsp;
   <label>
     <input type="radio" name="archivedelete" value="0" checked="checked" />$lt{'no'}
   </label>
   &nbsp;
   <label>
     <input type="radio" name="archivedelete" value="1" />$lt{'yes'}</label>
   </span>
   </p>
   <input type="hidden" name="phase" value="decompress_cleanup" />
   <br />$lt{'hows'}
   <div class="LC_columnSection">
     <fieldset>
       <legend>$lt{'cont'}</legend>
       <input type="button" value="$lt{'addf'}" onclick="javascript:checkAll(document.$form,'display');" /> 
       &nbsp;&nbsp;<input type="button" value="$lt{'incd'}" onclick="javascript:checkAll(document.$form,'dependency');" />
       &nbsp;&nbsp;<input type="button" value="$lt{'disc'}" onclick="javascript:checkAll(document.$form,'discard');" />
     </fieldset>
   </div>
   END
       return $output.
              &start_data_table()."\n".
              $display."\n".
              &end_data_table()."\n".
              '<input type="hidden" name="archive_count" value="'.$count.'" />'.
              $hiddenelem.
              '<br /><input type="submit" name="archive_submit" value="'.$lt{'save'}.'" />'.
              '</form>';
   }
   
   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 = <<START;
   <script type="text/javascript">
   // <![CDATA[
   
   function checkAll(form,prefix) {
       var idstr =  new RegExp("^archive_"+prefix+"_\\\\d+\$");
       for (var i=0; i < form.elements.length; i++) {
           var id = form.elements[i].id;
           if ((id != '') && (id != undefined)) {
               if (idstr.test(id)) {
                   if (form.elements[i].type == 'radio') {
                       form.elements[i].checked = true;
                       var nostart = i-$startcount;
                       var offset = nostart%7;
                       var count = (nostart-offset)/7;    
                       dependencyCheck(form,count,offset);
                   }
               }
           }
       }
   }
   
   function propagateCheck(form,count) {
       if (count > 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<numitems; i++) {
       parents[i] = new Array;
   }
   var maintitle = '$maintitle';
   
   START
   
       foreach my $container (sort { $a <=> $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 .= <<END;
   
   function containerCheck(form,count,offset) {
       if (count > 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<parents[count].length; j++) {
                       containerCheck(form,parents[count][j],offset);
                   }
               }
           }
       }
   }
   
   function dependencyCheck(form,count,offset) {
       if (count > 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<=numitems; i++) {
                   if (i == count) {
                       continue;
                   }
                   var startelement = $startcount + (i-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) {
                                   if (form.elements[item].value == 'display') {
                                       var n = form.elements[depitem].options.length;
                                       form.elements[depitem].options[n] = new Option(titles[i],i,false,false);
                                   }
                               }
                           }
                       }
                   }
               }
           } else {
               document.getElementById('arc_depon_'+count).style.display='none';
               form.elements[depitem].options.length = 0;
               form.elements[depitem].options[0] = new Option('Select','',true,true);
           }
           titleCheck(form,count,offset);
       }
   }
   
   function propagateSelect(form,count,offset) {
       if (count > 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<parents[count].length; j++) {
                       containerSelect(form,parents[count][j],offset,picked);
                   }
               }
           }
       }
   }
   
   function containerSelect(form,count,offset,picked) {
       if (count > 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<form.elements[item+1].options.length; i++) {
                           if (form.elements[item+1].options[i].value == picked) {
                               form.elements[item+1].selectedIndex = i;
                               break;
                           }
                       }
                   }
                   if (Object.prototype.toString.call(parents[count]) === '[object Array]') {
                       if (parents[count].length > 0) {
                           for (var j=0; j<parents[count].length; j++) {
                               containerSelect(form,parents[count][j],offset,picked);
                           }
                       }
                   }
               }
           }
       }
   }
   
   function titleCheck(form,count,offset) {
       if (count > 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;
   }
   
   // ]]>
   </script>
   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++) {
               next if ($env{'form.archive_'.$i} eq 'dependency');
               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,1);
                               $newseqid{$i} = $newidx;
                               unless ($errtext) {
                                   $result .=  '<li>'.&mt('Folder: [_1] added to course',$docstitle).'</li>'."\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,1);
                               unless ($errtext) {
                                   if (-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx/$title") {
                                       $result .= '<li>'.&mt('File: [_1] added to course',$docstitle).'</li>'."\n";
                                   }
                               }
                           }
                       }
                   }
               } else {
                   $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).'<br />';
               }
           }
           for (my $i=1; $i<=$numitems; $i++) {
               next unless ($env{'form.archive_'.$i} eq 'dependency');
               my $path = $env{'form.archive_content_'.$i};
               if ($path =~ /^\Q$pathtocheck\E/) {
                   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);
                           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 eq '') {
                               $itemidx =  0;
                           }
                           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 .= '<li>'.&mt('[_1] included as a dependency',$showpath).'</li>'."\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}}).'<br />';
                   }
               } else {
                   $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).'<br />';
               }
           }
           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 .= '<ul>'."\n".
                          $result."\n".
                          '</ul>';
           }
           unless ($ishome) {
               my $replicationfail;
               foreach my $item (keys(%prompttofetch)) {
                   my $fetchresult= &Apache::lonnet::reply('fetchuserfile:'.$item,$docuhome);
                   unless ($fetchresult eq 'ok') {
                       $replicationfail .= '<li>'.$item.'</li>'."\n";
                   }
               }
               if ($replicationfail) {
                   $output .= '<p class="LC_error">'.
                              &mt('Course home server failed to retrieve:').'<ul>'.
                              $replicationfail.
                              '</ul></p>';
               }
           }
       } else {
           $warning = &mt('No items found in archive.');
       }
       if ($error) {
           $output .= '<p class="LC_error">'.&mt('Not extracted.').'<br />'.
                      $error.'</p>'."\n";
       }
       if ($warning) {
           $output .= '<p class="LC_warning">'.$warning.'</p>'."\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  =pod
   
 =item * &get_turnedin_filepath()  =item * &get_turnedin_filepath()
Line 11922  sub init_user_environment { Line 13777  sub init_user_environment {
   
 # See if old ID present, if so, remove  # See if old ID present, if so, remove
   
     my ($filename,$cookie,$userroles);      my ($filename,$cookie,$userroles,$firstaccenv,$timerintenv);
     my $now=time;      my $now=time;
   
     if ($public) {      if ($public) {
Line 11960  sub init_user_environment { Line 13815  sub init_user_environment {
           
 # Initialize roles  # Initialize roles
   
  $userroles=&Apache::lonnet::rolesinit($domain,$username,$authhost);   ($userroles,$firstaccenv,$timerintenv) = 
               &Apache::lonnet::rolesinit($domain,$username,$authhost);
     }      }
 # ------------------------------------ Check browser type and MathML capability  # ------------------------------------ Check browser type and MathML capability
   
Line 12021  sub init_user_environment { Line 13877  sub init_user_environment {
             %domdef = &Apache::lonnet::get_domain_defaults($domain);              %domdef = &Apache::lonnet::get_domain_defaults($domain);
         }          }
   
         foreach my $tool ('aboutme','blog','portfolio') {          foreach my $tool ('aboutme','blog','webdav','portfolio') {
             $userenv{'availabletools.'.$tool} =               $userenv{'availabletools.'.$tool} = 
                 &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',                  &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',
                                                   undef,\%userenv,\%domdef,\%is_adv);                                                    undef,\%userenv,\%domdef,\%is_adv);
Line 12034  sub init_user_environment { Line 13890  sub init_user_environment {
                                                   \%userenv,\%domdef,\%is_adv);                                                    \%userenv,\%domdef,\%is_adv);
         }          }
   
           $userenv{'canrequest.author'} =
               &Apache::lonnet::usertools_access($username,$domain,'requestauthor',
                                           'reload','requestauthor',
                                           \%userenv,\%domdef,\%is_adv);
           my %reqauthor = &Apache::lonnet::get('requestauthor',['author_status','author'],
                                                $domain,$username);
           my $reqstatus = $reqauthor{'author_status'};
           if ($reqstatus eq 'approval' || $reqstatus eq 'approved') {
               if (ref($reqauthor{'author'}) eq 'HASH') {
                   $userenv{'requestauthorqueued'} = $reqstatus.':'.
                                                     $reqauthor{'author'}{'timestamp'};
               }
           }
   
  $env{'user.environment'} = "$lonids/$cookie.id";   $env{'user.environment'} = "$lonids/$cookie.id";
   
  if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id",   if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id",
  &GDBM_WRCREAT(),0640)) {   &GDBM_WRCREAT(),0640)) {
     &_add_to_env(\%disk_env,\%initial_env);      &_add_to_env(\%disk_env,\%initial_env);
     &_add_to_env(\%disk_env,\%userenv,'environment.');      &_add_to_env(\%disk_env,\%userenv,'environment.');
     &_add_to_env(\%disk_env,$userroles);      &_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'})) {      if (ref($args->{'extra_env'})) {
  &_add_to_env(\%disk_env,$args->{'extra_env'});   &_add_to_env(\%disk_env,$args->{'extra_env'});
     }      }
Line 12076  sub get_symb { Line 13952  sub get_symb {
     my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url)));      my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url)));
     if ($symb eq '') {      if ($symb eq '') {
         if (!$silent) {          if (!$silent) {
             $request->print("Unable to handle ambiguous references:$url:.");              if (ref($request)) { 
                   $request->print("Unable to handle ambiguous references:$url:.");
               }
             return ();              return ();
         }          }
     }      }
Line 12140  sub build_release_hashes { Line 14018  sub build_release_hashes {
     return;      return;
 }  }
   
   sub update_content_constraints {
       my ($cdom,$cnum,$chome,$cid) = @_;
       my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');
       my ($reqdmajor,$reqdminor) = split(/\./,$curr_reqd_hash{'internal.releaserequired'});
       my %checkresponsetypes;
       foreach my $key (keys(%Apache::lonnet::needsrelease)) {
           my ($item,$name,$value) = split(/:/,$key);
           if ($item eq 'resourcetag') {
               if ($name eq 'responsetype') {
                   $checkresponsetypes{$value} = $Apache::lonnet::needsrelease{$key}
               }
           }
       }
       my $navmap = Apache::lonnavmaps::navmap->new();
       if (defined($navmap)) {
           my %allresponses;
           foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_problem() },1,0)) {
               my %responses = $res->responseTypes();
               foreach my $key (keys(%responses)) {
                   next unless(exists($checkresponsetypes{$key}));
                   $allresponses{$key} += $responses{$key};
               }
           }
           foreach my $key (keys(%allresponses)) {
               my ($major,$minor) = split(/\./,$checkresponsetypes{$key});
               if (($major > $reqdmajor) || ($major == $reqdmajor && $minor > $reqdminor)) {
                   ($reqdmajor,$reqdminor) = ($major,$minor);
               }
           }
           undef($navmap);
       }
       unless (($reqdmajor eq '') && ($reqdminor eq '')) {
           &Apache::lonnet::update_released_required($reqdmajor.'.'.$reqdminor,$cdom,$cnum,$chome,$cid);
       }
       return;
   }
   
   sub parse_supplemental_title {
       my ($title) = @_;
   
       my ($foldertitle,$renametitle);
       if ($title =~ /&amp;&amp;&amp;/) {
           $title = &HTML::Entites::decode($title);
       }
       if ($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/) {
           $renametitle=$4;
           my ($time,$uname,$udom) = ($1,$2,$3);
           $foldertitle=&Apache::lontexconvert::msgtexconverted($4);
           my $name =  &plainname($uname,$udom);
           $name = &HTML::Entities::encode($name,'"<>&\'');
           $renametitle = &HTML::Entities::encode($renametitle,'"<>&\'');
           $title='<i>'.&Apache::lonlocal::locallocaltime($time).'</i> '.
               $name.': <br />'.$foldertitle;
       }
       if (wantarray) {
           return ($title,$foldertitle,$renametitle);
       }
       return $title;
   }
   
   sub captcha_display {
       my ($context,$lonhost) = @_;
       my ($output,$error);
       my ($captcha,$pubkey,$privkey) = &get_captcha_config($context,$lonhost);
       if ($captcha eq 'original') {
           $output = &create_captcha();
           unless ($output) {
               $error = 'captcha';
           }
       } elsif ($captcha eq 'recaptcha') {
           $output = &create_recaptcha($pubkey);
           unless ($output) {
               $error = 'recaptcha';
           }
       }
       return ($output,$error);
   }
   
   sub captcha_response {
       my ($context,$lonhost) = @_;
       my ($captcha_chk,$captcha_error);
       my ($captcha,$pubkey,$privkey) = &get_captcha_config($context,$lonhost);
       if ($captcha eq 'original') {
           ($captcha_chk,$captcha_error) = &check_captcha();
       } elsif ($captcha eq 'recaptcha') {
           $captcha_chk = &check_recaptcha($privkey);
       } else {
           $captcha_chk = 1;
       }
       return ($captcha_chk,$captcha_error);
   }
   
   sub get_captcha_config {
       my ($context,$lonhost) = @_;
       my ($captcha,$pubkey,$privkey,$hashtocheck);
       my $hostname = &Apache::lonnet::hostname($lonhost);
       my $serverhomeID = &Apache::lonnet::get_server_homeID($hostname);
       my $serverhomedom = &Apache::lonnet::host_domain($serverhomeID);
       if ($context eq 'usercreation') {
           my %domconfig = &Apache::lonnet::get_dom('configuration',[$context],$serverhomedom);
           if (ref($domconfig{$context}) eq 'HASH') {
               $hashtocheck = $domconfig{$context}{'cancreate'};
               if (ref($hashtocheck) eq 'HASH') {
                   if ($hashtocheck->{'captcha'} eq 'recaptcha') {
                       if (ref($hashtocheck->{'recaptchakeys'}) eq 'HASH') {
                           $pubkey = $hashtocheck->{'recaptchakeys'}{'public'};
                           $privkey = $hashtocheck->{'recaptchakeys'}{'private'};
                       }
                       if ($privkey && $pubkey) {
                           $captcha = 'recaptcha';
                       } else {
                           $captcha = 'original';
                       }
                   } elsif ($hashtocheck->{'captcha'} ne 'notused') {
                       $captcha = 'original';
                   }
               }
           } else {
               $captcha = 'captcha';
           }
       } elsif ($context eq 'login') {
           my %domconfhash = &Apache::loncommon::get_domainconf($serverhomedom);
           if ($domconfhash{$serverhomedom.'.login.captcha'} eq 'recaptcha') {
               $pubkey = $domconfhash{$serverhomedom.'.login.recaptchakeys_public'};
               $privkey = $domconfhash{$serverhomedom.'.login.recaptchakeys_private'};
               if ($privkey && $pubkey) {
                   $captcha = 'recaptcha';
               } else {
                   $captcha = 'original';
               }
           } elsif ($domconfhash{$serverhomedom.'.login.captcha'} eq 'original') {
               $captcha = 'original';
           }
       }
       return ($captcha,$pubkey,$privkey);
   }
   
   sub create_captcha {
       my %captcha_params = &captcha_settings();
       my ($output,$maxtries,$tries) = ('',10,0);
       while ($tries < $maxtries) {
           $tries ++;
           my $captcha = Authen::Captcha->new (
                                              output_folder => $captcha_params{'output_dir'},
                                              data_folder   => $captcha_params{'db_dir'},
                                             );
           my $md5sum = $captcha->generate_code($captcha_params{'numchars'});
   
           if (-e $Apache::lonnet::perlvar{'lonCaptchaDir'}.'/'.$md5sum.'.png') {
               $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n".
                         &mt('Type in the letters/numbers shown below').'&nbsp;'.
                        '<input type="text" size="5" name="code" value="" /><br />'.
                        '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" />';
               last;
           }
       }
       return $output;
   }
   
   sub captcha_settings {
       my %captcha_params = (
                              output_dir     => $Apache::lonnet::perlvar{'lonCaptchaDir'},
                              www_output_dir => "/captchaspool",
                              db_dir         => $Apache::lonnet::perlvar{'lonCaptchaDb'},
                              numchars       => '5',
                            );
       return %captcha_params;
   }
   
   sub check_captcha {
       my ($captcha_chk,$captcha_error);
       my $code = $env{'form.code'};
       my $md5sum = $env{'form.crypt'};
       my %captcha_params = &captcha_settings();
       my $captcha = Authen::Captcha->new(
                         output_folder => $captcha_params{'output_dir'},
                         data_folder   => $captcha_params{'db_dir'},
                     );
       my $captcha_chk = $captcha->check_code($code,$md5sum);
       my %captcha_hash = (
                           0       => 'Code not checked (file error)',
                          -1      => 'Failed: code expired',
                          -2      => 'Failed: invalid code (not in database)',
                          -3      => 'Failed: invalid code (code does not match crypt)',
       );
       if ($captcha_chk != 1) {
           $captcha_error = $captcha_hash{$captcha_chk}
       }
       return ($captcha_chk,$captcha_error);
   }
   
   sub create_recaptcha {
       my ($pubkey) = @_;
       my $captcha = Captcha::reCAPTCHA->new;
       return $captcha->get_options_setter({theme => 'white'})."\n".
              $captcha->get_html($pubkey).
              &mt('If either word is hard to read, [_1] will replace them.',
                  '<image src="/res/adm/pages/refresh.gif" alt="reCAPTCHA refresh" />').
              '<br /><br />';
   }
   
   sub check_recaptcha {
       my ($privkey) = @_;
       my $captcha_chk;
       my $captcha = Captcha::reCAPTCHA->new;
       my $captcha_result =
           $captcha->check_answer(
                                   $privkey,
                                   $ENV{'REMOTE_ADDR'},
                                   $env{'form.recaptcha_challenge_field'},
                                   $env{'form.recaptcha_response_field'},
                                 );
       if ($captcha_result->{is_valid}) {
           $captcha_chk = 1;
       }
       return $captcha_chk;
   }
   
 =pod  =pod
   
 =back  =back

Removed from v.1.1053  
changed lines
  Added in v.1.1075.2.14


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>