Diff for /loncom/interface/loncommon.pm between versions 1.976 and 1.1057

version 1.976, 2010/08/14 04:28:21 version 1.1057, 2012/03/04 15:42:52
Line 154  sub ssi_with_retries { Line 154  sub ssi_with_retries {
 # ----------------------------------------------- Filetypes/Languages/Copyright  # ----------------------------------------------- Filetypes/Languages/Copyright
 my %language;  my %language;
 my %supported_language;  my %supported_language;
   my %latex_language; # For choosing hyphenation in <transl..>
   my %latex_language_bykey; # for choosing hyphenation from metadata
 my %cprtag;  my %cprtag;
 my %scprtag;  my %scprtag;
 my %fe; my %fd; my %fm;  my %fe; my %fd; my %fm;
Line 186  BEGIN { Line 188  BEGIN {
             while (my $line = <$fh>) {              while (my $line = <$fh>) {
                 next if ($line=~/^\#/);                  next if ($line=~/^\#/);
                 chomp($line);                  chomp($line);
                 my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$line));                  my ($key,$two,$country,$three,$enc,$val,$sup,$latex)=(split(/\t/,$line));
                 $language{$key}=$val.' - '.$enc;                  $language{$key}=$val.' - '.$enc;
                 if ($sup) {                  if ($sup) {
                     $supported_language{$key}=$sup;                      $supported_language{$key}=$sup;
                 }                  }
    if ($latex) {
       $latex_language_bykey{$key} = $latex;
       $latex_language{$two} = $latex;
    }
             }              }
             close($fh);              close($fh);
         }          }
Line 409  sub studentbrowser_javascript { Line 415  sub studentbrowser_javascript {
 <script type="text/javascript" language="Javascript">  <script type="text/javascript" language="Javascript">
 // <![CDATA[  // <![CDATA[
     var stdeditbrowser;      var stdeditbrowser;
     function openstdbrowser(formname,uname,udom,roleflag,ignorefilter,courseadvonly) {      function openstdbrowser(formname,uname,udom,clicker,roleflag,ignorefilter,courseadvonly) {
         var url = '/adm/pickstudent?';          var url = '/adm/pickstudent?';
         var filter;          var filter;
  if (!ignorefilter) {   if (!ignorefilter) {
Line 421  sub studentbrowser_javascript { Line 427  sub studentbrowser_javascript {
    }     }
         }          }
         url += 'form=' + formname + '&unameelement='+uname+          url += 'form=' + formname + '&unameelement='+uname+
                                     '&udomelement='+udom;                                      '&udomelement='+udom+
                                       '&clicker='+clicker;
  if (roleflag) { url+="&roles=1"; }   if (roleflag) { url+="&roles=1"; }
         if (courseadvonly) { url+="&courseadvonly=1"; }          if (courseadvonly) { url+="&courseadvonly=1"; }
         var title = 'Student_Browser';          var title = 'Student_Browser';
Line 435  sub studentbrowser_javascript { Line 442  sub studentbrowser_javascript {
 ENDSTDBRW  ENDSTDBRW
 }  }
   
   sub resourcebrowser_javascript {
      unless ($env{'request.course.id'}) { return ''; }
      return (<<'ENDRESBRW');
   <script type="text/javascript" language="Javascript">
   // <![CDATA[
       var reseditbrowser;
       function openresbrowser(formname,reslink) {
           var url = '/adm/pickresource?form='+formname+'&reslink='+reslink;
           var title = 'Resource_Browser';
           var options = 'scrollbars=1,resizable=1,menubar=0';
           options += ',width=700,height=500';
           reseditbrowser = open(url,title,options,'1');
           reseditbrowser.focus();
       }
   // ]]>
   </script>
   ENDRESBRW
   }
   
 sub selectstudent_link {  sub selectstudent_link {
    my ($form,$unameele,$udomele,$courseadvonly)=@_;     my ($form,$unameele,$udomele,$courseadvonly,$clickerid)=@_;
    my $callargs = "'".$form."','".$unameele."','".$udomele."'";     my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','".
                         &Apache::lonhtmlcommon::entity_encode($unameele)."','".
                         &Apache::lonhtmlcommon::entity_encode($udomele)."'";
    if ($env{'request.course.id'}) {       if ($env{'request.course.id'}) {  
        if (!&Apache::lonnet::allowed('srm',$env{'request.course.id'})         if (!&Apache::lonnet::allowed('srm',$env{'request.course.id'})
    && !&Apache::lonnet::allowed('srm',$env{'request.course.id'}.     && !&Apache::lonnet::allowed('srm',$env{'request.course.id'}.
  '/'.$env{'request.course.sec'})) {   '/'.$env{'request.course.sec'})) {
    return '';     return '';
        }         }
          $callargs.=",'".&Apache::lonhtmlcommon::entity_encode($clickerid)."'";
        if ($courseadvonly)  {         if ($courseadvonly)  {
            $callargs .= ",'',1,1";             $callargs .= ",'',1,1";
        }         }
Line 452  sub selectstudent_link { Line 481  sub selectstudent_link {
               &mt('Select User').'</a></span>';                &mt('Select User').'</a></span>';
    }     }
    if ($env{'request.role'}=~/^(au|dc|su)/) {     if ($env{'request.role'}=~/^(au|dc|su)/) {
        $callargs .= ",1";          $callargs .= ",'',1"; 
        return '<span class="LC_nobreak">'.         return '<span class="LC_nobreak">'.
               '<a href="javascript:openstdbrowser('.$callargs.');">'.                '<a href="javascript:openstdbrowser('.$callargs.');">'.
               &mt('Select User').'</a></span>';                &mt('Select User').'</a></span>';
Line 460  sub selectstudent_link { Line 489  sub selectstudent_link {
    return '';     return '';
 }  }
   
   sub selectresource_link {
      my ($form,$reslink,$arg)=@_;
      
      my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','".
                         &Apache::lonhtmlcommon::entity_encode($reslink)."'";
      unless ($env{'request.course.id'}) { return $arg; }
      return '<span class="LC_nobreak">'.
                 '<a href="javascript:openresbrowser('.$callargs.');">'.
                 $arg.'</a></span>';
   }
   
   
   
 sub authorbrowser_javascript {  sub authorbrowser_javascript {
     return <<"ENDAUTHORBRW";      return <<"ENDAUTHORBRW";
 <script type="text/javascript" language="JavaScript">  <script type="text/javascript" language="JavaScript">
Line 596  ENDJS Line 638  ENDJS
   
 }  }
   
   sub javascript_array_indexof {
       return <<ENDJS;
   <script type="text/javascript" language="JavaScript">
   // <![CDATA[
   
   if (!Array.prototype.indexOf) {
       Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
           "use strict";
           if (this === void 0 || this === null) {
               throw new TypeError();
           }
           var t = Object(this);
           var len = t.length >>> 0;
           if (len === 0) {
               return -1;
           }
           var n = 0;
           if (arguments.length > 0) {
               n = Number(arguments[1]);
               if (n !== n) { // shortcut for verifying if it's NaN
                   n = 0;
               } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
                   n = (n > 0 || -1) * Math.floor(Math.abs(n));
               }
           }
           if (n >= len) {
               return -1;
           }
           var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
           for (; k < len; k++) {
               if (k in t && t[k] === searchElement) {
                   return k;
               }
           }
           return -1;
       }
   }
   
   // ]]>
   </script>
   
   ENDJS
   
   }
   
 sub userbrowser_javascript {  sub userbrowser_javascript {
     my $id_functions = &javascript_index_functions();      my $id_functions = &javascript_index_functions();
     return <<"ENDUSERBRW";      return <<"ENDUSERBRW";
Line 766  sub selectcourse_link { Line 853  sub selectcourse_link {
    } elsif ($selecttype eq 'Course/Community') {     } elsif ($selecttype eq 'Course/Community') {
        $linktext = &mt('Select Course/Community');         $linktext = &mt('Select Course/Community');
        $type = '';         $type = '';
      } elsif ($selecttype eq 'Select') {
          $linktext = &mt('Select');
          $type = '';
    }     }
    return '<span class="LC_nobreak">'     return '<span class="LC_nobreak">'
          ."<a href='"           ."<a href='"
Line 1102  sub help_open_topic { Line 1192  sub help_open_topic {
     my ($topic, $text, $stayOnPage, $width, $height, $imgid) = @_;      my ($topic, $text, $stayOnPage, $width, $height, $imgid) = @_;
     $text = "" if (not defined $text);      $text = "" if (not defined $text);
     $stayOnPage = 0 if (not defined $stayOnPage);      $stayOnPage = 0 if (not defined $stayOnPage);
     $width = 350 if (not defined $width);      $width = 500 if (not defined $width);
     $height = 400 if (not defined $height);      $height = 400 if (not defined $height);
     my $filename = $topic;      my $filename = $topic;
     $filename =~ s/ /_/g;      $filename =~ s/ /_/g;
Line 1113  sub help_open_topic { Line 1203  sub help_open_topic {
     $topic=~s/\W/\_/g;      $topic=~s/\W/\_/g;
   
     if (!$stayOnPage) {      if (!$stayOnPage) {
  $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";   $link = "javascript:openMyModal('/adm/help/${filename}.hlp',$width,$height,'yes');";
       } elsif ($stayOnPage eq 'popup') {
           $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
     } else {      } else {
  $link = "/adm/help/${filename}.hlp";   $link = "/adm/help/${filename}.hlp";
     }      }
Line 1146  sub help_open_topic { Line 1238  sub help_open_topic {
 # This is a quicky function for Latex cheatsheet editing, since it   # This is a quicky function for Latex cheatsheet editing, since it 
 # appears in at least four places  # appears in at least four places
 sub helpLatexCheatsheet {  sub helpLatexCheatsheet {
     my ($topic,$text,$not_author) = @_;      my ($topic,$text,$not_author,$stayOnPage) = @_;
     my $out;      my $out;
     my $addOther = '';      my $addOther = '';
     if ($topic) {      if ($topic) {
  $addOther = '<span>'.&Apache::loncommon::help_open_topic($topic,&mt($text),   $addOther = '<span>'.&help_open_topic($topic,&mt($text),$stayOnPage, undef, 600).'</span> ';
        undef, undef, 600).  
    '</span> ';  
     }      }
     $out = '<span>' # Start cheatsheet      $out = '<span>' # Start cheatsheet
   .$addOther    .$addOther
           .'<span>'            .'<span>'
   .&Apache::loncommon::help_open_topic('Greek_Symbols',&mt('Greek Symbols'),    .&help_open_topic('Greek_Symbols',&mt('Greek Symbols'),$stayOnPage,undef,600)
        undef,undef,600)  
   .'</span> <span>'    .'</span> <span>'
   .&Apache::loncommon::help_open_topic('Other_Symbols',&mt('Other Symbols'),    .&help_open_topic('Other_Symbols',&mt('Other Symbols'),$stayOnPage,undef,600)
        undef,undef,600)  
   .'</span>';    .'</span>';
     unless ($not_author) {      unless ($not_author) {
         $out .= ' <span>'          $out .= ' <span>'
        .&Apache::loncommon::help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),         .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600)
                                             undef,undef,600)  
        .'</span>';         .'</span>';
     }      }
     $out .= '</span>'; # End cheatsheet      $out .= '</span>'; # End cheatsheet
Line 1661  Inputs: $workbook Line 1748  Inputs: $workbook
   
 Returns: $format, a hash reference.  Returns: $format, a hash reference.
   
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 1722  sub create_workbook { Line 1810  sub create_workbook {
         return (undef);          return (undef);
     }      }
     #      #
     $workbook->set_tempdir('/home/httpd/perl/tmp');      $workbook->set_tempdir(LONCAPA::tempdir());
     #      #
     my $format = &Apache::loncommon::define_excel_formats($workbook);      my $format = &Apache::loncommon::define_excel_formats($workbook);
     return ($workbook,$filename,$format);      return ($workbook,$filename,$format);
Line 2274  function changed_text(choice,currentform Line 2362  function changed_text(choice,currentform
 }  }
   
 function set_auth_radio_buttons(newvalue,currentform) {  function set_auth_radio_buttons(newvalue,currentform) {
       var numauthchoices = currentform.login.length;
       if (typeof numauthchoices  == "undefined") {
           return;
       } 
     var i=0;      var i=0;
     while (i < currentform.login.length) {      while (i < numauthchoices) {
         if (currentform.login[i].value == newvalue) { break; }          if (currentform.login[i].value == newvalue) { break; }
         i++;          i++;
     }      }
     if (i == currentform.login.length) {      if (i == numauthchoices) {
         return;          return;
     }      }
     current.radiovalue = newvalue;      current.radiovalue = newvalue;
Line 2765  database which holds them. Line 2857  database which holds them.
   
 Uses global $thesaurus_db_file.  Uses global $thesaurus_db_file.
   
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 3142  sub languagedescription { Line 3235  sub languagedescription {
     ($supported_language{$code}?' ('.&mt('interface available').')':'');      ($supported_language{$code}?' ('.&mt('interface available').')':'');
 }  }
   
   =pod
   
   =item * &plainlanguagedescription
   
   Returns both the plain language description (e.g. 'Creoles and Pidgins, English-based (Other)')
   and the language character encoding (e.g. ISO) separated by a ' - ' string.
   
   =cut
   
 sub plainlanguagedescription {  sub plainlanguagedescription {
     my $code=shift;      my $code=shift;
     return $language{$code};      return $language{$code};
 }  }
   
   =pod
   
   =item * &supportedlanguagecode
   
   Returns the supported language code (e.g. sptutf maps to pt) given a language
   code.
   
   =cut
   
 sub supportedlanguagecode {  sub supportedlanguagecode {
     my $code=shift;      my $code=shift;
     return $supported_language{$code};      return $supported_language{$code};
Line 3154  sub supportedlanguagecode { Line 3265  sub supportedlanguagecode {
   
 =pod  =pod
   
   =item * &latexlanguage()
   
   Given a language key code returns the correspondnig language to use
   to select the correct hyphenation on LaTeX printouts.  This is undef if there
   is no supported hyphenation for the language code.
   
   =cut
   
   sub latexlanguage {
       my $code = shift;
       return $latex_language{$code};
   }
   
   =pod
   
   =item * &latexhyphenation()
   
   Same as above but what's supplied is the language as it might be stored
   in the metadata.
   
   =cut
   
   sub latexhyphenation {
       my $key = shift;
       return $latex_language_bykey{$key};
   }
   
   =pod
   
 =item * &copyrightids()   =item * &copyrightids() 
   
 returns list of all copyrights  returns list of all copyrights
Line 3411  sub get_previous_attempt { Line 3551  sub get_previous_attempt {
       }        }
       $prevattempts=&start_data_table().&start_data_table_header_row();        $prevattempts=&start_data_table().&start_data_table_header_row();
       $prevattempts.='<th>'.&mt('History').'</th>';        $prevattempts.='<th>'.&mt('History').'</th>';
       my %typeparts;        my (%typeparts,%lasthidden);
       my $showsurv=&Apache::lonnet::allowed('vas',$env{'request.course.id'});        my $showsurv=&Apache::lonnet::allowed('vas',$env{'request.course.id'});
       foreach my $key (sort(keys(%lasthash))) {        foreach my $key (sort(keys(%lasthash))) {
  my ($ign,@parts) = split(/\./,$key);   my ($ign,@parts) = split(/\./,$key);
  if ($#parts > 0) {   if ($#parts > 0) {
   my $data=$parts[-1];    my $data=$parts[-1];
             next if ($data eq 'foilorder');
   pop(@parts);    pop(@parts);
             $prevattempts.='<th>'.&mt('Part ').join('.',@parts).'<br />'.$data.'&nbsp;</th>';
           if ($data eq 'type') {            if ($data eq 'type') {
               unless ($showsurv) {                unless ($showsurv) {
                   my $id = join(',',@parts);                    my $id = join(',',@parts);
                   $typeparts{$ign.'.'.$id} = $lasthash{$key};                    $typeparts{$ign.'.'.$id} = $lasthash{$key};
                     if (($lasthash{$key} eq 'anonsurvey') || ($lasthash{$key} eq 'anonsurveycred')) {
                         $lasthidden{$ign.'.'.$id} = 1;
                     }
               }                }
               delete($lasthash{$key});            } 
           } else {  
       $prevattempts.='<th>'.&mt('Part ').join('.',@parts).'<br />'.$data.'&nbsp;</th>';  
           }  
  } else {   } else {
   if ($#parts == 0) {    if ($#parts == 0) {
     $prevattempts.='<th>'.$parts[0].'</th>';      $prevattempts.='<th>'.$parts[0].'</th>';
Line 3436  sub get_previous_attempt { Line 3578  sub get_previous_attempt {
  }   }
       }        }
       $prevattempts.=&end_data_table_header_row();        $prevattempts.=&end_data_table_header_row();
       my %lasthidden;  
       if ($getattempt eq '') {        if ($getattempt eq '') {
  for ($version=1;$version<=$returnhash{'version'};$version++) {   for ($version=1;$version<=$returnhash{'version'};$version++) {
             my @hidden;              my @hidden;
Line 3444  sub get_previous_attempt { Line 3585  sub get_previous_attempt {
                 foreach my $id (keys(%typeparts)) {                  foreach my $id (keys(%typeparts)) {
                     if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') || ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {                      if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') || ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {
                         push(@hidden,$id);                          push(@hidden,$id);
                         $lasthidden{$id} = 1;  
                     } elsif ($lasthidden{$id}) {  
                         if (exists($returnhash{$version.':'.$id.'.award'})) {  
                             delete($lasthidden{$id});  
                         }  
                     }                      }
                 }                  }
             }              }
Line 3456  sub get_previous_attempt { Line 3592  sub get_previous_attempt {
                            '<td>'.&mt('Transaction [_1]',$version).'</td>';                             '<td>'.&mt('Transaction [_1]',$version).'</td>';
             if (@hidden) {              if (@hidden) {
                 foreach my $key (sort(keys(%lasthash))) {                  foreach my $key (sort(keys(%lasthash))) {
                       next if ($key =~ /\.foilorder$/);
                     my $hide;                      my $hide;
                     foreach my $id (@hidden) {                      foreach my $id (@hidden) {
                         if ($key =~ /^\Q$id\E/) {                          if ($key =~ /^\Q$id\E/) {
Line 3484  sub get_previous_attempt { Line 3621  sub get_previous_attempt {
                 }                  }
             } else {              } else {
         foreach my $key (sort(keys(%lasthash))) {          foreach my $key (sort(keys(%lasthash))) {
                       next if ($key =~ /\.foilorder$/);
     my $value = &format_previous_attempt_value($key,      my $value = &format_previous_attempt_value($key,
             $returnhash{$version.':'.$key});              $returnhash{$version.':'.$key});
     $prevattempts.='<td>'.$value.'&nbsp;</td>';      $prevattempts.='<td>'.$value.'&nbsp;</td>';
Line 3495  sub get_previous_attempt { Line 3633  sub get_previous_attempt {
       my @currhidden = keys(%lasthidden);        my @currhidden = keys(%lasthidden);
       $prevattempts.=&start_data_table_row().'<td>'.&mt('Current').'</td>';        $prevattempts.=&start_data_table_row().'<td>'.&mt('Current').'</td>';
       foreach my $key (sort(keys(%lasthash))) {        foreach my $key (sort(keys(%lasthash))) {
             next if ($key =~ /\.foilorder$/);
           if (%typeparts) {            if (%typeparts) {
               my $hidden;                my $hidden;
               foreach my $id (@currhidden) {                foreach my $id (@currhidden) {
Line 3546  sub get_previous_attempt { Line 3685  sub get_previous_attempt {
   
 sub format_previous_attempt_value {  sub format_previous_attempt_value {
     my ($key,$value) = @_;      my ($key,$value) = @_;
     if ($key =~ /timestamp/) {      if (($key =~ /timestamp/) || ($key=~/duedate/)) {
  $value = &Apache::lonlocal::locallocaltime($value);   $value = &Apache::lonlocal::locallocaltime($value);
     } elsif (ref($value) eq 'ARRAY') {      } elsif (ref($value) eq 'ARRAY') {
  $value = '('.join(', ', @{ $value }).')';   $value = '('.join(', ', @{ $value }).')';
       } elsif ($key =~ /answerstring$/) {
           my %answers = &Apache::lonnet::str2hash($value);
           my @anskeys = sort(keys(%answers));
           if (@anskeys == 1) {
               my $answer = $answers{$anskeys[0]};
               if ($answer =~ m{\0}) {
                   $answer =~ s{\0}{,}g;
               }
               my $tag_internal_answer_name = 'INTERNAL';
               if ($anskeys[0] eq $tag_internal_answer_name) {
                   $value = $answer; 
               } else {
                   $value = $anskeys[0].'='.$answer;
               }
           } else {
               foreach my $ans (@anskeys) {
                   my $answer = $answers{$ans};
                   if ($answer =~ m{\0}) {
                       $answer =~ s{\0}{,}g;
                   }
                   $value .=  $ans.'='.$answer.'<br />';;
               } 
           }
     } else {      } else {
  $value = &unescape($value);   $value = &unescape($value);
     }      }
Line 3828  sub findallcourses { Line 3990  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 %roleshash = &Apache::lonnet::dump('roles',$udom,$uname);          my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
           my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,
                                                 $extra);
         if (!%roles) {          if (!%roles) {
             %roles = (              %roles = (
                        cc => 1,                         cc => 1,
Line 4242  sub get_domainconf { Line 4406  sub get_domainconf {
                     if (ref($domconfig{'login'}{$key}) eq 'HASH') {                      if (ref($domconfig{'login'}{$key}) eq 'HASH') {
                         if ($key eq 'loginvia') {                          if ($key eq 'loginvia') {
                             if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') {                              if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') {
                                 my @ids = &Apache::lonnet::current_machine_ids();                                  foreach my $hostname (keys(%{$domconfig{'login'}{'loginvia'}})) {
                                 foreach my $hostname (@ids) {  
                                     if (ref($domconfig{'login'}{'loginvia'}{$hostname}) eq 'HASH') {                                      if (ref($domconfig{'login'}{'loginvia'}{$hostname}) eq 'HASH') {
                                         if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {                                          if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {
                                             my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};                                              my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};
Line 4252  sub get_domainconf { Line 4415  sub get_domainconf {
   
                                                 $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};                                                  $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};
                                             } else {                                              } else {
                                                  $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};                                                  $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};
                                             }                                              }
                                             if ($domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}) {                                              if ($domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}) {
                                                 $designhash{$udom.'.login.loginvia_exempt_'.$hostname} = $domconfig{'login'}{'loginvia'}{$hostname}{'exempt'};                                                  $designhash{$udom.'.login.loginvia_exempt_'.$hostname} = $domconfig{'login'}{'loginvia'}{$hostname}{'exempt'};
Line 4335  sub get_legacy_domconf { Line 4498  sub get_legacy_domconf {
             close($fh);              close($fh);
         }          }
     }      }
     if (-e '/home/httpd/html/adm/lonDomLogos/'.$udom.'.gif') {      if (-e $Apache::lonnet::perlvar{'lonDocRoot'}.'/adm/lonDomLogos/'.$udom.'.gif') {
         $legacyhash{$udom.'.login.domlogo'} = "/adm/lonDomLogos/$udom.gif";          $legacyhash{$udom.'.login.domlogo'} = "/adm/lonDomLogos/$udom.gif";
     }      }
     return %legacyhash;      return %legacyhash;
Line 4393  sub designparm { Line 4556  sub designparm {
         return $env{'environment.color.'.$which};          return $env{'environment.color.'.$which};
     }      }
     $domain=&determinedomain($domain);      $domain=&determinedomain($domain);
     my %domdesign = &get_domainconf($domain);      my %domdesign;
       unless ($domain eq 'public') {
           %domdesign = &get_domainconf($domain);
       }
     my $output;      my $output;
     if ($domdesign{$domain.'.'.$which} ne '') {      if ($domdesign{$domain.'.'.$which} ne '') {
         $output = $domdesign{$domain.'.'.$which};          $output = $domdesign{$domain.'.'.$which};
Line 4418  sub designparm { Line 4584  sub designparm {
   
 =item * &authorspace()  =item * &authorspace()
   
 Inputs: ./.  Inputs: $url (usually will be undef).
   
 Returns: Path to the Construction Space of the current user's  Returns: Path to Construction Space containing the resource or 
          accessed author space           directory being viewed (or for which action is being taken). 
          The author space will be that of the current user           If $url is provided, and begins /priv/<domain>/<uname>
          when accessing the own author space           the path will be that portion of the $context argument.
          and that of the co-author/assistent co-author           Otherwise the path will be for the author space of the current
          when accessing the co-author's/assistent co-author's           user when the current role is author, or for that of the 
          space           co-author/assistant co-author space when the current role 
            is co-author or assistant co-author.
   
 =cut  =cut
   
 sub authorspace {  sub authorspace {
       my ($url) = @_;
       if ($url ne '') {
           if ($url =~ m{^(/priv/$match_domain/$match_username/)}) {
              return $1;
           }
       }
     my $caname = '';      my $caname = '';
     if ($env{'request.role'} =~ /^ca|^aa/) {      my $cadom = '';
         (undef,$caname) =      if ($env{'request.role'} =~ /^(?:ca|aa)/) {
           ($cadom,$caname) =
             ($env{'request.role'}=~/($match_domain)\/($match_username)$/);              ($env{'request.role'}=~/($match_domain)\/($match_username)$/);
     } else {      } elsif ($env{'request.role'} =~ m{^au\./($match_domain)/}) {
         $caname = $env{'user.name'};          $caname = $env{'user.name'};
           $cadom = $env{'user.domain'};
       }
       if (($caname ne '') && ($cadom ne '')) {
           return "/priv/$cadom/$caname/";
     }      }
     return '/priv/'.$caname.'/';      return;
 }  }
   
 ##############################################  ##############################################
Line 4456  Returns: HTML div with $content Line 4634  Returns: HTML div with $content
 sub head_subbox {  sub head_subbox {
     my ($content)=@_;      my ($content)=@_;
     my $output =      my $output =
         '<div id="LC_head_subbox">'          '<div class="LC_head_subbox">'
        .$content         .$content
        .'</div>'         .'</div>'
 }  }
Line 4466  sub head_subbox { Line 4644  sub head_subbox {
   
 =item * &CSTR_pageheader()  =item * &CSTR_pageheader()
   
 Inputs: ./.  Input: (optional) filename from which breadcrumb trail is built.
          In most cases no input as needed, as $env{'request.filename'}
          is appropriate for use in building the breadcrumb trail.
   
 Returns: HTML div with CSTR path and recent box  Returns: HTML div with CSTR path and recent box
          To be included on Construction Space pages           To be included on Construction Space pages
Line 4474  Returns: HTML div with CSTR path and rec Line 4654  Returns: HTML div with CSTR path and rec
 =cut  =cut
   
 sub CSTR_pageheader {  sub CSTR_pageheader {
     # this is for resources; directories have customtitle, and crumbs      my ($trailfile) = @_;
             # and select recent are created in lonpubdir.pm        if ($trailfile eq '') {
     my ($uname,$thisdisfn)=          $trailfile = $env{'request.filename'};
         ($env{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|);      }
     my $formaction='/priv/'.$uname.'/'.$thisdisfn;  
     $formaction=~s/\/+/\//g;  # this is for resources; directories have customtitle, and crumbs
   # and select recent are created in lonpubdir.pm
   
       my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
       my ($udom,$uname,$thisdisfn)=
           ($trailfile =~ m{^\Q$londocroot\E/priv/([^/]+)/([^/]+)/(.*)$});
       my $formaction = "/priv/$udom/$uname/$thisdisfn";
       $formaction =~ s{/+}{/}g;
   
     my $parentpath = '';      my $parentpath = '';
     my $lastitem = '';      my $lastitem = '';
Line 4496  sub CSTR_pageheader { Line 4683  sub CSTR_pageheader {
         .'<b>'.&mt('Construction Space:').'</b> '          .'<b>'.&mt('Construction Space:').'</b> '
         .'<form name="dirs" method="post" action="'.$formaction          .'<form name="dirs" method="post" action="'.$formaction
         .'" target="_top">' #FIXME lonpubdir: target="_parent"          .'" target="_top">' #FIXME lonpubdir: target="_parent"
         .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv',undef,undef);          .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv/'.$udom,undef,undef);
   
     if ($lastitem) {      if ($lastitem) {
         $output .=          $output .=
Line 4702  sub bodytag { Line 4889  sub bodytag {
   
 sub dc_courseid_toggle {  sub dc_courseid_toggle {
     my ($dc_info) = @_;      my ($dc_info) = @_;
     return ' <span id="dccidtext" class="LC_cusr_subheading">'.      return ' <span id="dccidtext" class="LC_cusr_subheading LC_nobreak">'.
            '<a href="javascript:showCourseID();">'.             '<a href="javascript:showCourseID();">'.
            &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 4848  body { Line 5035  body {
 a:focus,  a:focus,
 a:focus img {  a:focus img {
   color: red;    color: red;
   background: yellow;  
 }  }
   
 form, .inline {  form, .inline {
Line 4895  form, .inline { Line 5081  form, .inline {
   text-decoration:none;    text-decoration:none;
 }  }
   
   .LC_setting {
     text-decoration:underline;
   }
   
 .LC_error {  .LC_error {
   color: red;    color: red;
   font-size: larger;    font-size: larger;
Line 4939  div.LC_confirm_box .LC_success img { Line 5129  div.LC_confirm_box .LC_success img {
 }  }
   
 .LC_discussion {  .LC_discussion {
   background: $tabbg;    background: $data_table_dark;
   border: 1px solid black;    border: 1px solid black;
   margin: 2px;    margin: 2px;
 }  }
   
 .LC_disc_action_links_bar {  
   background: $tabbg;  
   border: none;  
   margin: 4px;  
 }  
   
 .LC_disc_action_left {  .LC_disc_action_left {
     background: $sidebg;
   text-align: left;    text-align: left;
     padding: 4px;
     margin: 2px;
 }  }
   
 .LC_disc_action_right {  .LC_disc_action_right {
     background: $sidebg;
   text-align: right;    text-align: right;
     padding: 4px;
     margin: 2px;
 }  }
   
 .LC_disc_new_item {  .LC_disc_new_item {
   background: white;    background: white;
   border: 2px solid red;    border: 2px solid red;
   margin: 2px;    margin: 4px;
     padding: 4px;
 }  }
   
 .LC_disc_old_item {  .LC_disc_old_item {
   background: white;    background: white;
   border: 1px solid black;    margin: 4px;
   margin: 2px;    padding: 4px;
 }  }
   
 table.LC_pastsubmission {  table.LC_pastsubmission {
Line 5059  td.LC_table_cell_checkbox { Line 5250  td.LC_table_cell_checkbox {
   overflow: hidden;    overflow: hidden;
   margin: 0;    margin: 0;
   padding: 0;    padding: 0;
     text-align: left;
 }  }
   
 #LC_head_subbox {  .LC_head_subbox {
   clear:both;    clear:both;
   background: #F8F8F8; /* $sidebg; */    background: #F8F8F8; /* $sidebg; */
   border: 1px solid $sidebg;    border: 1px solid $sidebg;
   margin: 0 0 10px 0;          margin: 0 0 10px 0;      
   padding: 3px;    padding: 3px;
     text-align: left;
 }  }
   
 .LC_fontsize_medium {  .LC_fontsize_medium {
Line 5087  td.LC_table_cell_checkbox { Line 5280  td.LC_table_cell_checkbox {
   vertical-align: middle;    vertical-align: middle;
 }  }
   
 li.LC_menubuttons_inline_text img,a {  li.LC_menubuttons_inline_text img {
   cursor:pointer;    cursor:pointer;
     text-decoration: none;
 }  }
   
 .LC_menubuttons_link {  .LC_menubuttons_link {
Line 5136  table.LC_nested { Line 5330  table.LC_nested {
   width: 100%;    width: 100%;
 }  }
   
 .ui-accordion,  
 .ui-accordion table.LC_data_table,  
 .ui-accordion table.LC_nested_outer{  
   border: 0px;  
   border-spacing: 0px;  
   margin: 3px;  
 }  
   
 table.LC_data_table tr th,  table.LC_data_table tr th,
 table.LC_calendar tr th,  table.LC_calendar tr th,
 table.LC_prior_tries tr th,  table.LC_prior_tries tr th,
Line 5259  table.LC_nested tr td.LC_right_item { Line 5445  table.LC_nested tr td.LC_right_item {
   text-align: right;    text-align: right;
 }  }
   
 .ui-accordion table.LC_nested tr.LC_odd_row td.LC_left_item,  
 .ui-accordion table.LC_nested tr.LC_even_row td.LC_left_item {  
   text-align: right;  
   width: 40%;  
   padding-right:10px;  
   vertical-align: top;  
   padding: 5px;  
 }  
   
 .ui-accordion table.LC_nested tr.LC_odd_row td.LC_right_item,  
 .ui-accordion table.LC_nested tr.LC_even_row td.LC_right_item {  
   text-align: left;  
   width: 60%;  
   padding: 2px 4px;  
 }  
   
 table.LC_nested tr.LC_odd_row td {  table.LC_nested tr.LC_odd_row td {
   background-color: #EEEEEE;    background-color: #EEEEEE;
 }  }
Line 5406  span.LC_current_location { Line 5576  span.LC_current_location {
   background: $pgbg;    background: $pgbg;
 }  }
   
   span.LC_current_nav_location {
     font-weight:bold;
     background: $sidebg;
   }
   
 span.LC_parm_menu_item {  span.LC_parm_menu_item {
   font-size: larger;    font-size: larger;
 }  }
Line 5433  span.LC_parm_symb { Line 5608  span.LC_parm_symb {
   color: #AAAAAA;    color: #AAAAAA;
 }  }
   
   ul.LC_parm_parmlist li {
     display: inline-block;
     padding: 0.3em 0.8em;
     vertical-align: top;
     width: 150px;
     border-top:1px solid $lg_border_color;
   }
   
 td.LC_parm_overview_level_menu,  td.LC_parm_overview_level_menu,
 td.LC_parm_overview_map_menu,  td.LC_parm_overview_map_menu,
 td.LC_parm_overview_parm_selectors,  td.LC_parm_overview_parm_selectors,
Line 5952  div.LC_createcourse { Line 6135  div.LC_createcourse {
   display:none;    display:none;
 }  }
   
 a:hover,  
 ol.LC_primary_menu a:hover,  ol.LC_primary_menu a:hover,
 ol#LC_MenuBreadcrumbs a:hover,  ol#LC_MenuBreadcrumbs a:hover,
 ol#LC_PathBreadcrumbs a:hover,  ol#LC_PathBreadcrumbs a:hover,
Line 6026  fieldset > legend { Line 6208  fieldset > legend {
   
 #LC_nav_bar {  #LC_nav_bar {
   float: left;    float: left;
     background-color: $pgbg_or_bgcolor;
   margin: 0 0 2px 0;    margin: 0 0 2px 0;
 }  }
   
Line 6034  fieldset > legend { Line 6217  fieldset > legend {
   padding: 0;    padding: 0;
   font-weight: bold;    font-weight: bold;
   text-align: center;    text-align: center;
     background-color: $pgbg_or_bgcolor;
 }  }
   
 #LC_nav_bar em {  #LC_nav_bar em {
Line 6041  fieldset > legend { Line 6225  fieldset > legend {
   font-style: normal;    font-style: normal;
 }  }
   
 /* Preliminary fix to hide nav_bar inside bookmarks window */  
 #LC_bookmarks #LC_nav_bar {  
   display:none;  
 }  
   
 ol.LC_primary_menu {  ol.LC_primary_menu {
   float: right;    float: right;
   margin: 0;    margin: 0;
     background-color: $pgbg_or_bgcolor;
 }  }
   
 ol#LC_PathBreadcrumbs {  ol#LC_PathBreadcrumbs {
Line 6108  ul#LC_secondary_menu { Line 6288  ul#LC_secondary_menu {
   padding: 0;    padding: 0;
   margin: 0;    margin: 0;
   width: 100%;    width: 100%;
     text-align: left;
 }  }
   
 ul#LC_secondary_menu li {  ul#LC_secondary_menu li {
Line 6124  ul.LC_TabContent { Line 6305  ul.LC_TabContent {
   background: $sidebg;    background: $sidebg;
   border-bottom: solid 1px $lg_border_color;    border-bottom: solid 1px $lg_border_color;
   list-style:none;    list-style:none;
   margin: 0 -10px;    margin: -1px -10px 0 -10px;
   padding: 0;    padding: 0;
 }  }
   
Line 6147  ul.LC_TabContent li { Line 6328  ul.LC_TabContent li {
   padding: 0 16px 0 10px;    padding: 0 16px 0 10px;
   background-color:$tabbg;    background-color:$tabbg;
   border-bottom:solid 1px $lg_border_color;    border-bottom:solid 1px $lg_border_color;
   border-right: solid 1px $font;    border-left: solid 1px $font;
 }  }
   
 ul.LC_TabContent .right {  ul.LC_TabContent .right {
Line 6187  ul.LC_TabContent li.active a { Line 6368  ul.LC_TabContent li.active a {
   background:#FFFFFF;    background:#FFFFFF;
   outline: none;    outline: none;
 }  }
   
   ul.LC_TabContent li.goback {
     float: left;
     border-left: none;
   }
   
 #maincoursedoc {  #maincoursedoc {
   clear:both;    clear:both;
 }  }
Line 6241  ul.LC_TabContentBigger li.active b { Line 6428  ul.LC_TabContentBigger li.active b {
   background:url('/adm/lonIcons/tabbgright.gif') right top no-repeat;    background:url('/adm/lonIcons/tabbgright.gif') right top no-repeat;
   color:$font;    color:$font;
   border: 0;    border: 0;
   cursor:default;  
 }  }
   
   
 ul.LC_CourseBreadcrumbs {  ul.LC_CourseBreadcrumbs {
   background: $sidebg;    background: $sidebg;
   line-height: 32px;    height: 2em;
   padding-left: 10px;    padding-left: 10px;
   margin: 0 0 10px 0;    margin: 0;
   list-style-position: inside;    list-style-position: inside;
   
 }  }
   
 ol#LC_MenuBreadcrumbs,  ol#LC_MenuBreadcrumbs,
Line 6293  ol#LC_PathBreadcrumbs li a { Line 6478  ol#LC_PathBreadcrumbs li a {
   padding: 0 10px 10px 10px;    padding: 0 10px 10px 10px;
 }  }
   
   .LC_DocsBox {
     border: solid 1px $lg_border_color;
     padding: 0 0 10px 10px;
   }
   
 .LC_AboutMe_Image {  .LC_AboutMe_Image {
   float:left;    float:left;
   margin-right:10px;    margin-right:10px;
Line 6433  a#LC_content_toolbar_changefolder_toggle Line 6623  a#LC_content_toolbar_changefolder_toggle
   background-image:url(/res/adm/pages/open-all-folders.gif);    background-image:url(/res/adm/pages/open-all-folders.gif);
 }  }
   
   a#LC_content_toolbar_edittoplevel {
     background-image:url(/res/adm/pages/edittoplevel.gif);
   }
   
 ul#LC_toolbar li a:hover {  ul#LC_toolbar li a:hover {
   background-position: bottom center;    background-position: bottom center;
 }  }
Line 6497  ul.LC_funclist li { Line 6691  ul.LC_funclist li {
   line-height: 150%;    line-height: 150%;
 }  }
   
 .ui-accordion .LC_advanced_toggle {  
   float: right;  
   font-size: 90%;  
   padding: 0px 4px  
 }  
   
 .LC_hidden {  .LC_hidden {
   display: none;    display: none;
 }  }
   
   .LCmodal-overlay {
    position:fixed;
    top:0;
    right:0;
    bottom:0;
    left:0;
    height:100%;
    width:100%;
    margin:0;
    padding:0;
    background:#999;
    opacity:.75;
    filter: alpha(opacity=75);
    -moz-opacity: 0.75;
    z-index:101;
   }
   
   * html .LCmodal-overlay {   
    position: absolute;
    height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
   }
   
   .LCmodal-window {
    position:fixed;
    top:50%;
    left:50%;
    margin:0;
    padding:0;
    z-index:102;
    }
   
   * html .LCmodal-window {
    position:absolute;
   }
   
   .LCclose-window {
    position:absolute;
    width:32px;
    height:32px;
    right:8px;
    top:8px;
    background:transparent url('/res/adm/pages/process-stop.png') no-repeat scroll right top;
    text-indent:-99999px;
    overflow:hidden;
    cursor:pointer;
   }
   
 END  END
 }  }
   
Line 6565  sub headtag { Line 6800  sub headtag {
  && !$args->{'only_body'}   && !$args->{'only_body'}
  && !$args->{'frameset'}) {   && !$args->{'frameset'}) {
  $result .= &help_menu_js();   $result .= &help_menu_js();
           $result.=&modal_window();
           $result.=&togglebox_script();
           $result.=&wishlist_window();
           $result.=&LCprogressbarUpdate_script();
       } else {
           if ($args->{'add_modal'}) {
              $result.=&modal_window();
           }
           if ($args->{'add_wishlist'}) {
              $result.=&wishlist_window();
           }
           if ($args->{'add_togglebox'}) {
              $result.=&togglebox_script();
           }
           if ($args->{'add_progressbar'}) {
              $result.=&LCprogressbarUpdate_script();
           }
     }      }
   
     if (ref($args->{'redirect'})) {      if (ref($args->{'redirect'})) {
  my ($time,$url,$inhibit_continue) = @{$args->{'redirect'}};   my ($time,$url,$inhibit_continue) = @{$args->{'redirect'}};
  $url = &Apache::lonenc::check_encrypt($url);   $url = &Apache::lonenc::check_encrypt($url);
Line 6680  $args - additional optional args support Line 6931  $args - additional optional args support
                                     should it have jsmath forced on by the                                      should it have jsmath forced on by the
                                     current page                                      current page
              bread_crumbs ->             Array containing breadcrumbs               bread_crumbs ->             Array containing breadcrumbs
              bread_crumbs_components ->  if exists show it as headline else show only the breadcrumbs               bread_crumbs_component ->  if exists show it as headline else show only the breadcrumbs
   
 =back  =back
   
Line 6691  $args - additional optional args support Line 6942  $args - additional optional args support
 sub start_page {  sub start_page {
     my ($title,$head_extra,$args) = @_;      my ($title,$head_extra,$args) = @_;
     #&Apache::lonnet::logthis("start_page ".join(':',caller(0)));      #&Apache::lonnet::logthis("start_page ".join(':',caller(0)));
 #SD  
 #I don't see why we copy certain elements of %$args to %head_args  
 #head args is passed to headtag() and this routine only reads those  
 #keys that are needed. There doesn't happen any writes or any processing  
 #of other keys.  
 #proposal: just pass $args to headtag instead of \%head_args and delete   
 #marked lines  
 #<- MARK  
     my %head_args;  
     foreach my $arg ('redirect','force_register','domain','function',  
      'bgcolor','frameset','no_nav_bar','only_body',  
      'no_auto_mt_title') {  
  if (defined($args->{$arg})) {  
     $head_args{$arg} = $args->{$arg};  
  }  
     }  
 #MARK ->  
   
     $env{'internal.start_page'}++;      $env{'internal.start_page'}++;
     my $result;      my $result;
   
     if (! exists($args->{'skip_phases'}{'head'}) ) {      if (! exists($args->{'skip_phases'}{'head'}) ) {
         $result .=           $result .= &xml_begin() . &headtag($title, $head_extra, $args);
                   &xml_begin() . &headtag($title,$head_extra,\%head_args);  
 #replace prev line by  
 #                 &xml_begin() . &headtag($title, $head_extra, $args);  
     }      }
           
     if (! exists($args->{'skip_phases'}{'body'}) ) {      if (! exists($args->{'skip_phases'}{'body'}) ) {
Line 6782  sub end_page { Line 7013  sub end_page {
  }   }
  $result .= &Apache::lonxml::xmlend($target,$parser);   $result .= &Apache::lonxml::xmlend($target,$parser);
     }      }
   
     if ($args->{'frameset'}) {      if ($args->{'frameset'}) {
  $result .= '</frameset>';   $result .= '</frameset>';
     } else {      } else {
Line 6801  sub end_page { Line 7031  sub end_page {
     return $result;      return $result;
 }  }
   
   sub wishlist_window {
       return(<<'ENDWISHLIST');
   <script type="text/javascript">
   // <![CDATA[
   // <!-- BEGIN LON-CAPA Internal
   function set_wishlistlink(title, path) {
       if (!title) {
           title = document.title;
           title = title.replace(/^LON-CAPA /,'');
       }
       if (!path) {
           path = location.pathname;
       }
       Win = window.open('/adm/wishlist?mode=newLink&setTitle='+title+'&setPath='+path,
                         'wishlistNewLink','width=560,height=350,scrollbars=0');
   }
   // END LON-CAPA Internal -->
   // ]]>
   </script>
   ENDWISHLIST
   }
   
   sub modal_window {
       return(<<'ENDMODAL');
   <script type="text/javascript">
   // <![CDATA[
   // <!-- BEGIN LON-CAPA Internal
   var modalWindow = {
    parent:"body",
    windowId:null,
    content:null,
    width:null,
    height:null,
    close:function()
    {
           $(".LCmodal-window").remove();
           $(".LCmodal-overlay").remove();
    },
    open:function()
    {
    var modal = "";
    modal += "<div class=\"LCmodal-overlay\"></div>";
    modal += "<div id=\"" + this.windowId + "\" class=\"LCmodal-window\" style=\"width:" + this.width + "px; height:" + this.height + "px; margin-top:-" + (this.height / 2) + "px; margin-left:-" + (this.width / 2) + "px;\">";
    modal += this.content;
    modal += "</div>";
   
    $(this.parent).append(modal);
   
    $(".LCmodal-window").append("<a class=\"LCclose-window\"></a>");
    $(".LCclose-window").click(function(){modalWindow.close();});
    $(".LCmodal-overlay").click(function(){modalWindow.close();});
    }
   };
    var openMyModal = function(source,width,height,scrolling)
    {
    modalWindow.windowId = "myModal";
    modalWindow.width = width;
    modalWindow.height = height;
    modalWindow.content = "<iframe width='"+width+"' height='"+height+"' frameborder='0' scrolling='"+scrolling+"' allowtransparency='true' src='" + source + "'>&lt/iframe>";
    modalWindow.open();
    };
   // END LON-CAPA Internal -->
   // ]]>
   </script>
   ENDMODAL
   }
   
   sub modal_link {
       my ($link,$linktext,$width,$height,$target,$scrolling,$title)=@_;
       unless ($width) { $width=480; }
       unless ($height) { $height=400; }
       unless ($scrolling) { $scrolling='yes'; }
       return '<a href="'.$link.'" target="'.$target.'" title="'.$title.'" onclick="openMyModal(\''.$link.'\','.$width.','.$height.',\''.$scrolling.'\'); return false;">'.
              $linktext.'</a>';
   }
   
   sub modal_adhoc_script {
       my ($funcname,$width,$height,$content)=@_;
       return (<<ENDADHOC);
   <script type="text/javascript">
   // <![CDATA[
           var $funcname = function()
           {
                   modalWindow.windowId = "myModal";
                   modalWindow.width = $width;
                   modalWindow.height = $height;
                   modalWindow.content = '$content';
                   modalWindow.open();
           };  
   // ]]>
   </script>
   ENDADHOC
   }
   
   sub modal_adhoc_inner {
       my ($funcname,$width,$height,$content)=@_;
       my $innerwidth=$width-20;
       $content=&js_ready(
                  &start_page('Dialog',undef,{'only_body'=>1,'bgcolor'=>'#FFFFFF'}).
                    &start_scrollbox($width.'px',$innerwidth.'px',$height.'px').
                       $content.
                    &end_scrollbox().
                  &end_page()
                );
       return &modal_adhoc_script($funcname,$width,$height,$content);
   }
   
   sub modal_adhoc_window {
       my ($funcname,$width,$height,$content,$linktext)=@_;
       return &modal_adhoc_inner($funcname,$width,$height,$content).
              "<a href=\"javascript:$funcname();void(0);\">".$linktext."</a>";
   }
   
   sub modal_adhoc_launch {
       my ($funcname,$width,$height,$content)=@_;
       return &modal_adhoc_inner($funcname,$width,$height,$content).(<<ENDLAUNCH);
   <script type="text/javascript">
   // <![CDATA[
   $funcname();
   // ]]>
   </script>
   ENDLAUNCH
   }
   
   sub modal_adhoc_close {
       return (<<ENDCLOSE);
   <script type="text/javascript">
   // <![CDATA[
   modalWindow.close();
   // ]]>
   </script>
   ENDCLOSE
   }
   
   sub togglebox_script {
      return(<<ENDTOGGLE);
   <script type="text/javascript"> 
   // <![CDATA[
   function LCtoggleDisplay(id,hidetext,showtext) {
      link = document.getElementById(id + "link").childNodes[0];
      with (document.getElementById(id).style) {
         if (display == "none" ) {
             display = "inline";
             link.nodeValue = hidetext;
           } else {
             display = "none";
             link.nodeValue = showtext;
          }
      }
   }
   // ]]>
   </script>
   ENDTOGGLE
   }
   
   sub start_togglebox {
       my ($id,$heading,$headerbg,$hidetext,$showtext)=@_;
       unless ($heading) { $heading=''; } else { $heading.=' '; }
       unless ($showtext) { $showtext=&mt('show'); }
       unless ($hidetext) { $hidetext=&mt('hide'); }
       unless ($headerbg) { $headerbg='#FFFFFF'; }
       return &start_data_table().
              &start_data_table_header_row().
              '<td bgcolor="'.$headerbg.'">'.$heading.
              '[<a id="'.$id.'link" href="javascript:LCtoggleDisplay(\''.$id.'\',\''.$hidetext.'\',\''.
              $showtext.'\')">'.$showtext.'</a>]</td>'.
              &end_data_table_header_row().
              '<tr id="'.$id.'" style="display:none""><td>';
   }
   
   sub end_togglebox {
       return '</td></tr>'.&end_data_table();
   }
   
   sub LCprogressbar_script {
      my ($id)=@_;
      return(<<ENDPROGRESS);
   <script type="text/javascript">
   // <![CDATA[
   \$('#progressbar$id').progressbar({
     value: 0,
     change: function(event, ui) {
       var newVal = \$(this).progressbar('option', 'value');
       \$('.pblabel', this).text(LCprogressTxt);
     }
   });
   // ]]>
   </script>
   ENDPROGRESS
   }
   
   sub LCprogressbarUpdate_script {
      return(<<ENDPROGRESSUPDATE);
   <style type="text/css">
   .ui-progressbar { position:relative; }
   .pblabel { position: absolute; width: 100%; text-align: center; line-height: 1.9em; }
   </style>
   <script type="text/javascript">
   // <![CDATA[
   var LCprogressTxt='---';
   
   function LCupdateProgress(percent,progresstext,id) {
      LCprogressTxt=progresstext;
      \$('#progressbar'+id).progressbar('value',percent);
   }
   // ]]>
   </script>
   ENDPROGRESSUPDATE
   }
   
   my $LClastpercent;
   my $LCidcnt;
   my $LCcurrentid;
   
   sub LCprogressbar {
       my ($r)=(@_);
       $LClastpercent=0;
       $LCidcnt++;
       $LCcurrentid=$$.'_'.$LCidcnt;
       my $starting=&mt('Starting');
       my $content=(<<ENDPROGBAR);
   <p>
     <div id="progressbar$LCcurrentid">
       <span class="pblabel">$starting</span>
     </div>
   </p>
   ENDPROGBAR
       &r_print($r,$content.&LCprogressbar_script($LCcurrentid));
   }
   
   sub LCprogressbarUpdate {
       my ($r,$val,$text)=@_;
       unless ($val) { 
          if ($LClastpercent) {
              $val=$LClastpercent;
          } else {
              $val=0;
          }
       }
       if ($val<0) { $val=0; }
       if ($val>100) { $val=0; }
       $LClastpercent=$val;
       unless ($text) { $text=$val.'%'; }
       $text=&js_ready($text);
       &r_print($r,<<ENDUPDATE);
   <script type="text/javascript">
   // <![CDATA[
   LCupdateProgress($val,'$text','$LCcurrentid');
   // ]]>
   </script>
   ENDUPDATE
   }
   
   sub LCprogressbarClose {
       my ($r)=@_;
       $LClastpercent=0;
       &r_print($r,<<ENDCLOSE);
   <script type="text/javascript">
   // <![CDATA[
   \$("#progressbar$LCcurrentid").hide('slow'); 
   // ]]>
   </script>
   ENDCLOSE
   }
   
   sub r_print {
       my ($r,$to_print)=@_;
       if ($r) {
         $r->print($to_print);
         $r->rflush();
       } else {
         print($to_print);
       }
   }
   
 sub html_encode {  sub html_encode {
     my ($result) = @_;      my ($result) = @_;
   
Line 6808  sub html_encode { Line 7313  sub html_encode {
           
     return $result;      return $result;
 }  }
   
 sub js_ready {  sub js_ready {
     my ($result) = @_;      my ($result) = @_;
   
Line 6844  sub validate_page { Line 7350  sub validate_page {
     }      }
 }  }
   
   
   sub start_scrollbox {
       my ($outerwidth,$width,$height,$id)=@_;
       unless ($outerwidth) { $outerwidth='520px'; }
       unless ($width) { $width='500px'; }
       unless ($height) { $height='200px'; }
       my ($table_id,$div_id);
       if ($id ne '') {
           $table_id = " id='table_$id'";
           $div_id = " id='div_$id'";
       }
       return "<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>";
   }
   
   sub end_scrollbox {
       return '</div></td></tr></table>';
   }
   
 sub simple_error_page {  sub simple_error_page {
     my ($r,$title,$msg) = @_;      my ($r,$title,$msg) = @_;
     my $page =      my $page =
Line 6871  sub simple_error_page { Line 7395  sub simple_error_page {
     }      }
   
     sub start_data_table {      sub start_data_table {
  my ($add_class) = @_;   my ($add_class,$id) = @_;
  my $css_class = (join(' ','LC_data_table',$add_class));   my $css_class = (join(' ','LC_data_table',$add_class));
           my $table_id;
           if (defined($id)) {
               $table_id = ' id="'.$id.'"';
           }
  &start_data_table_count();   &start_data_table_count();
  return '<table class="'.$css_class.'">'."\n";   return '<table class="'.$css_class.'"'.$table_id.'>'."\n";
     }      }
   
     sub end_data_table {      sub end_data_table {
Line 7001  sub get_users_function { Line 7529  sub get_users_function {
         $function='admin';          $function='admin';
     }      }
     if (($env{'request.role'}=~/^(au|ca|aa)/) ||      if (($env{'request.role'}=~/^(au|ca|aa)/) ||
         ($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {          ($ENV{'REQUEST_URI'}=~ m{/^(/priv)})) {
         $function='author';          $function='author';
     }      }
     return $function;      return $function;
Line 7059  role status: active, previous or future. Line 7587  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 %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);      my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
       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 7642  sub get_secgrprole_info { Line 8171  sub get_secgrprole_info {
 }  }
   
 sub user_picker {  sub user_picker {
     my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype) = @_;      my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype,$context) = @_;
     my $currdom = $dom;      my $currdom = $dom;
     my %curr_selected = (      my %curr_selected = (
                         srchin => 'dom',                          srchin => 'dom',
Line 7733  sub user_picker { Line 8262  sub user_picker {
     $srchtypesel .= "\n  </select>\n";      $srchtypesel .= "\n  </select>\n";
   
     my ($newuserscript,$new_user_create);      my ($newuserscript,$new_user_create);
       my $context_dom = $env{'request.role.domain'};
       if ($context eq 'requestcrs') {
           if ($env{'form.coursedom'} ne '') { 
               $context_dom = $env{'form.coursedom'};
           }
       }
     if ($forcenewuser) {      if ($forcenewuser) {
         if (ref($srch) eq 'HASH') {          if (ref($srch) eq 'HASH') {
             if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $env{'request.role.domain'}) {              if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $context_dom) {
                 if ($cancreate) {                  if ($cancreate) {
                     $new_user_create = '<p> <input type="submit" name="forcenew" value="'.&HTML::Entities::encode(&mt('Make new user "[_1]"',$srchterm),'<>&"').'" onclick="javascript:setSearch(\'1\','.$caller.');" /> </p>';                      $new_user_create = '<p> <input type="submit" name="forcenew" value="'.&HTML::Entities::encode(&mt('Make new user "[_1]"',$srchterm),'<>&"').'" onclick="javascript:setSearch(\'1\','.$caller.');" /> </p>';
                 } else {                  } else {
Line 7775  function setSearch(createnew,callingForm Line 8309  function setSearch(createnew,callingForm
             }              }
         }          }
         for (var i=0; i<callingForm.srchdomain.length; i++) {          for (var i=0; i<callingForm.srchdomain.length; i++) {
             if (callingForm.srchdomain.options[i].value == '$env{'request.role.domain'}') {              if (callingForm.srchdomain.options[i].value == '$context_dom') {
                 callingForm.srchdomain.selectedIndex = i;                  callingForm.srchdomain.selectedIndex = i;
             }              }
         }          }
Line 8110  sub get_standard_codeitems { Line 8644  sub get_standard_codeitems {
   
 =item * sorted_slots()  =item * sorted_slots()
   
 Sorts an array of slot names in order of slot start time (earliest first).   Sorts an array of slot names in order of an optional sort key,
   default sort is by slot start time (earliest first). 
   
 Inputs:  Inputs:
   
Line 8120  slotsarr  - Reference to array of unsort Line 8655  slotsarr  - Reference to array of unsort
   
 slots     - Reference to hash of hash, where outer hash keys are slot names.  slots     - Reference to hash of hash, where outer hash keys are slot names.
   
   sortkey   - Name of key in inner hash to be sorted on (e.g., starttime).
   
 =back  =back
   
 Returns:  Returns:
   
 =over 4  =over 4
   
 sorted   - An array of slot names sorted by the start time of the slot.  sorted   - An array of slot names sorted by a specified sort key 
              (default sort key is start time of the slot).
 =back  
   
 =back  =back
   
Line 8136  sorted   - An array of slot names sorted Line 8672  sorted   - An array of slot names sorted
   
   
 sub sorted_slots {  sub sorted_slots {
     my ($slotsarr,$slots) = @_;      my ($slotsarr,$slots,$sortkey) = @_;
       if ($sortkey eq '') {
           $sortkey = 'starttime';
       }
     my @sorted;      my @sorted;
     if ((ref($slotsarr) eq 'ARRAY') && (ref($slots) eq 'HASH')) {      if ((ref($slotsarr) eq 'ARRAY') && (ref($slots) eq 'HASH')) {
         @sorted =          @sorted =
             sort {              sort {
                      if (ref($slots->{$a}) && ref($slots->{$b})) {                       if (ref($slots->{$a}) && ref($slots->{$b})) {
                          return $slots->{$a}{'starttime'} <=> $slots->{$b}{'starttime'}                           return $slots->{$a}{$sortkey} <=> $slots->{$b}{$sortkey}
                      }                       }
                      if (ref($slots->{$a})) { return -1;}                       if (ref($slots->{$a})) { return -1;}
                      if (ref($slots->{$b})) { return 1;}                       if (ref($slots->{$b})) { return 1;}
Line 8152  sub sorted_slots { Line 8691  sub sorted_slots {
     return @sorted;      return @sorted;
 }  }
   
   =pod
   
   =item * get_future_slots()
   
   Inputs:
   
   =over 4
   
   cnum - course number
   
   cdom - course domain
   
   now - current UNIX time
   
   symb - optional symb
   
   =back
   
   Returns:
   
   =over 4
   
   sorted_reservable - ref to array of student_schedulable slots currently 
                       reservable, ordered by end date of reservation period.
   
   reservable_now - ref to hash of student_schedulable slots currently
                    reservable.
   
       Keys in inner hash are:
       (a) symb: either blank or symb to which slot use is restricted.
       (b) endreserve: end date of reservation period. 
   
   sorted_future - ref to array of student_schedulable slots reservable in
                   the future, ordered by start date of reservation period.
   
   future_reservable - ref to hash of student_schedulable slots reservable
                       in the future.
   
       Keys in inner hash are:
       (a) symb: either blank or symb to which slot use is restricted.
       (b) startreserve:  start date of reservation period.
   
   =back
   
   =cut
   
   sub get_future_slots {
       my ($cnum,$cdom,$now,$symb) = @_;
       my (%reservable_now,%future_reservable,@sorted_reservable,@sorted_future);
       my %slots = &Apache::lonnet::get_course_slots($cnum,$cdom);
       foreach my $slot (keys(%slots)) {
           next unless($slots{$slot}->{'type'} eq 'schedulable_student');
           if ($symb) {
               next if (($slots{$slot}->{'symb'} ne '') && 
                        ($slots{$slot}->{'symb'} ne $symb));
           }
           if (($slots{$slot}->{'starttime'} > $now) &&
               ($slots{$slot}->{'endtime'} > $now)) {
               if (($slots{$slot}->{'allowedsections'}) || ($slots{$slot}->{'allowedusers'})) {
                   my $userallowed = 0;
                   if ($slots{$slot}->{'allowedsections'}) {
                       my @allowed_sec = split(',',$slots{$slot}->{'allowedsections'});
                       if (!defined($env{'request.role.sec'})
                           && grep(/^No section assigned$/,@allowed_sec)) {
                           $userallowed=1;
                       } else {
                           if (grep(/^\Q$env{'request.role.sec'}\E$/,@allowed_sec)) {
                               $userallowed=1;
                           }
                       }
                       unless ($userallowed) {
                           if (defined($env{'request.course.groups'})) {
                               my @groups = split(/:/,$env{'request.course.groups'});
                               foreach my $group (@groups) {
                                   if (grep(/^\Q$group\E$/,@allowed_sec)) {
                                       $userallowed=1;
                                       last;
                                   }
                               }
                           }
                       }
                   }
                   if ($slots{$slot}->{'allowedusers'}) {
                       my @allowed_users = split(',',$slots{$slot}->{'allowedusers'});
                       my $user = $env{'user.name'}.':'.$env{'user.domain'};
                       if (grep(/^\Q$user\E$/,@allowed_users)) {
                           $userallowed = 1;
                       }
                   }
                   next unless($userallowed);
               }
               my $startreserve = $slots{$slot}->{'startreserve'};
               my $endreserve = $slots{$slot}->{'endreserve'};
               my $symb = $slots{$slot}->{'symb'};
               if (($startreserve < $now) &&
                   (!$endreserve || $endreserve > $now)) {
                   my $lastres = $endreserve;
                   if (!$lastres) {
                       $lastres = $slots{$slot}->{'starttime'};
                   }
                   $reservable_now{$slot} = {
                                              symb       => $symb,
                                              endreserve => $lastres
                                            };
               } elsif (($startreserve > $now) &&
                        (!$endreserve || $endreserve > $startreserve)) {
                   $future_reservable{$slot} = {
                                                 symb         => $symb,
                                                 startreserve => $startreserve
                                               };
               }
           }
       }
       my @unsorted_reservable = keys(%reservable_now);
       if (@unsorted_reservable > 0) {
           @sorted_reservable = 
               &sorted_slots(\@unsorted_reservable,\%reservable_now,'endreserve');
       }
       my @unsorted_future = keys(%future_reservable);
       if (@unsorted_future > 0) {
           @sorted_future =
               &sorted_slots(\@unsorted_future,\%future_reservable,'startreserve');
       }
       return (\@sorted_reservable,\%reservable_now,\@sorted_future,\%future_reservable);
   }
   
 =pod  =pod
   
   =back
   
 =head1 HTTP Helpers  =head1 HTTP Helpers
   
 =over 4  =over 4
Line 8293  sub get_env_multiple { Line 8959  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 $upload_output = '      my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges);
    <form name="upload_embedded" action="'.$actionurl.'"  
                   method="post" enctype="multipart/form-data">';  
     $upload_output .= $state;  
     $upload_output .= '<b>Upload embedded files</b>:<br />'.&start_data_table();  
   
     my $num = 0;      my $num = 0;
     foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%{$allfiles})) {      my $numremref = 0;
       my $numinvalid = 0;
       my $numpathchg = 0;
       my $numexisting = 0;
       my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath);
       if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
           my $current_path='/';
           if ($env{'form.currentpath'}) {
               $current_path = $env{'form.currentpath'};
           }
           if ($actionurl eq '/adm/coursegrp_portfolio') {
               $udom = $env{'course.'.$env{'request.course.id'}.'.domain'};
               $uname = $env{'course.'.$env{'request.course.id'}.'.num'};
               $url = '/userfiles/groups/'.$env{'form.group'}.'/portfolio';
           } else {
               $udom = $env{'user.domain'};
               $uname = $env{'user.name'};
               $url = '/userfiles/portfolio';
           }
           $toplevel = $url.'/';
           $url .= $current_path;
           $getpropath = 1;
       } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') ||
                ($actionurl eq '/adm/imsimport')) { 
           my ($udom,$uname,$rest) = ($args->{'current_path'} =~ m{/priv/($match_domain)/($match_username)/?(.*)$});
           $url = $Apache::lonnet::perlvar{'lonDocRoot'}."/priv/$udom/$uname/";
           $toplevel = $url;
           if ($rest ne '') {
               $url .= $rest;
           }
       } elsif ($actionurl eq '/adm/coursedocs') {
           if (ref($args) eq 'HASH') {
              $url = $args->{'docs_url'};
              $toplevel = $url;
           }
       }
       my $now = time();
       foreach my $embed_file (keys(%{$allfiles})) {
           my $absolutepath;
           if ($embed_file =~ m{^\w+://}) {
               $newfiles{$embed_file} = 1;
               $mapping{$embed_file} = $embed_file;
           } else {
               if ($embed_file =~ m{^/}) {
                   $absolutepath = $embed_file;
                   $embed_file =~ s{^(/+)}{};
               }
               if ($embed_file =~ m{/}) {
                   my ($path,$fname) = ($embed_file =~ m{^(.+)/([^/]*)$});
                   $path = &check_for_traversal($path,$url,$toplevel);
                   my $item = $fname;
                   if ($path ne '') {
                       $item = $path.'/'.$fname;
                       $subdependencies{$path}{$fname} = 1;
                   } else {
                       $dependencies{$item} = 1;
                   }
                   if ($absolutepath) {
                       $mapping{$item} = $absolutepath;
                   } else {
                       $mapping{$item} = $embed_file;
                   }
               } else {
                   $dependencies{$embed_file} = 1;
                   if ($absolutepath) {
                       $mapping{$embed_file} = $absolutepath;
                   } else {
                       $mapping{$embed_file} = $embed_file;
                   }
               }
           }
       }
       foreach my $path (keys(%subdependencies)) {
           my %currsubfile;
           if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) { 
               my ($sublistref,$listerror) =
                   &Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);
               if (ref($sublistref) eq 'ARRAY') {
                   foreach my $line (@{$sublistref}) {
                       my ($file_name,$rest) = split(/\&/,$line,2);
                       $currsubfile{$file_name} = 1;
                   }
               }
           } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
               if (opendir(my $dir,$url.'/'.$path)) {
                   my @subdir_list = grep(!/^\./,readdir($dir));
                   map {$currsubfile{$_} = 1;} @subdir_list;
               }
           }
           foreach my $file (keys(%{$subdependencies{$path}})) {
               if ($currsubfile{$file}) {
                   my $item = $path.'/'.$file;
                   unless ($mapping{$item} eq $item) {
                       $pathchanges{$item} = 1;
                   }
                   $existing{$item} = 1;
                   $numexisting ++;
               } else {
                   $newfiles{$path.'/'.$file} = 1;
               }
           }
       }
       my %currfile;
       if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
           my ($dirlistref,$listerror) =
               &Apache::lonnet::dirlist($url,$udom,$uname,$getpropath);
           if (ref($dirlistref) eq 'ARRAY') {
               foreach my $line (@{$dirlistref}) {
                   my ($file_name,$rest) = split(/\&/,$line,2);
                   $currfile{$file_name} = 1;
               }
           }
       } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
           if (opendir(my $dir,$url)) {
               my @dir_list = grep(!/^\./,readdir($dir));
               map {$currfile{$_} = 1;} @dir_list;
           }
       }
       foreach my $file (keys(%dependencies)) {
           if ($currfile{$file}) {
               unless ($mapping{$file} eq $file) {
                   $pathchanges{$file} = 1;
               }
               $existing{$file} = 1;
               $numexisting ++;
           } else {
               $newfiles{$file} = 1;
           }
       }
       foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) {
         $upload_output .= &start_data_table_row().          $upload_output .= &start_data_table_row().
             '<td>'.$embed_file.'</td><td>';                            '<td><span class="LC_filename">'.$embed_file.'</span>';
           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 .= '</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++;
         } 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++;
         } else {          } else {
             $upload_output .='              $upload_output .= &embedded_file_element('upload_embedded',$num,
            <input name="embedded_item_'.$num.'" type="file" value="" />                                                       $embed_file,\%mapping,
            <input name="embedded_orig_'.$num.'" type="hidden" value="'.&escape($embed_file).'" />';                                                       $allfiles,$codebase);
             my $attrib = join(':',@{$$allfiles{$embed_file}});              $num++;
             $upload_output .=          }
                 "\n\t\t".          $upload_output .= '</td>'.&Apache::loncommon::end_data_table_row()."\n";
                 '<input name="embedded_attrib_'.$num.'" type="hidden" value="'.      }
                 $attrib.'" />';      foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%existing)) {
             if (exists($$codebase{$embed_file})) {          $upload_output .= &start_data_table_row().
                 $upload_output .=                            '<td><span class="LC_filename">'.$embed_file.'</span></td>'.
                     "\n\t\t".                            '<td><span class="LC_warning">'.&mt('Already exists').'</span></td>'.
                     '<input name="codebase_'.$num.'" type="hidden" value="'.                            &Apache::loncommon::end_data_table_row()."\n";
                     &escape($$codebase{$embed_file}).'" />';      }
             }      if ($upload_output) {
         }          $upload_output = &start_data_table().
         $upload_output .= '</td>'.&Apache::loncommon::end_data_table_row();                           $upload_output.
         $num++;                           &end_data_table()."\n";
     }      }
     $upload_output .= &Apache::loncommon::end_data_table().'<br />      my $applies = 0;
    <input type ="hidden" name="number_embedded_items" value="'.$num.'" />      if ($numremref) {
    <input type ="submit" value="'.&mt('Upload Listed Files').'" />          $applies ++;
    '.&mt('(only files for which a location has been provided will be uploaded)').'      }
    </form>';      if ($numinvalid) {
     return $upload_output;          $applies ++;
       }
       if ($numexisting) {
           $applies ++;
       }
       if ($num) {
           $output = '<form name="upload_embedded" action="'.$actionurl.'"'.
                     ' method="post" enctype="multipart/form-data">'."\n".
                     $state.
                     '<h3>'.&mt('Upload embedded files').
                     ':</h3>'.$upload_output.'<br />'."\n".
                     '<input type ="hidden" name="number_embedded_items" value="'.
                     $num.'" />'."\n";
           if ($actionurl eq '') {
               $output .=  '<input type="hidden" name="phase" value="three" />';
           }
       } elsif ($applies) {
           $output = '<b>'.&mt('Referenced files').'</b>:<br />';
           if ($applies > 1) {
               $output .=  
                   &mt('No files need to be uploaded, as one of the following applies to each reference:').'<ul>';
               if ($numremref) {
                   $output .= '<li>'.&mt('reference is to a URL which points to another server').'</li>'."\n";
               }
               if ($numinvalid) {
                   $output .= '<li>'.&mt('reference is to file with a name containing invalid characters').'</li>'."\n";
               }
               if ($numexisting) {
                   $output .= '<li>'.&mt('reference is to an existing file at the specified location').'</li>'."\n";
               }
               $output .= '</ul><br />';
           } elsif ($numremref) {
               $output .= '<p>'.&mt('None to upload, as all references are to URLs pointing to another server.').'</p>';
           } elsif ($numinvalid) {
               $output .= '<p>'.&mt('None to upload, as all references are to files with names containing invalid characters.').'</p>';
           } elsif ($numexisting) {
               $output .= '<p>'.&mt('None to upload, as all references are to existing files.').'</p>';
           }
           $output .= $upload_output.'<br />';
       }
       my ($pathchange_output,$chgcount);
       $chgcount = $num;
       if (keys(%pathchanges) > 0) {
           foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%pathchanges)) {
               if ($num) {
                   $output .= &embedded_file_element('pathchange',$chgcount,
                                                     $embed_file,\%mapping,
                                                     $allfiles,$codebase);
               } else {
                   $pathchange_output .= 
                       &start_data_table_row().
                       '<td><input type ="checkbox" name="namechange" value="'.
                       $chgcount.'" checked="checked" /></td>'.
                       '<td>'.$mapping{$embed_file}.'</td>'.
                       '<td>'.$embed_file.
                       &embedded_file_element('pathchange',$numpathchg,$embed_file,
                                              \%mapping,$allfiles,$codebase).
                       '</td>'.&end_data_table_row();
               }
               $numpathchg ++;
               $chgcount ++;
           }
       }
       if ($num) {
           if ($numpathchg) {
               $output .= '<input type ="hidden" name="number_pathchange_items" value="'.
                          $numpathchg.'" />'."\n";
           }
           if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') || 
               ($actionurl eq '/adm/imsimport')) {
               $output .= '<input type="hidden" name="phase" value="three" />'."\n";
           } elsif ($actionurl eq '/adm/portfolio' || $actionurl eq '/adm/coursegrp_portfolio') {
               $output .= '<input type="hidden" name="action" value="upload_embedded" />';
           }
           $output .=  '<input type ="submit" value="'.&mt('Upload Listed Files').'" />'."\n".
                       &mt('(only files for which a location has been provided will be uploaded)').'</form>'."\n";
       } elsif ($numpathchg) {
           my %pathchange = ();
           $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);
           if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
               $output .= '<p>'.&mt('or').'</p>'; 
           } 
       }
       return ($output,$num,$numpathchg);
   }
   
   sub embedded_file_element {
       my ($context,$num,$embed_file,$mapping,$allfiles,$codebase) = @_;
       return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&
                      (ref($codebase) eq 'HASH'));
       my $output;
       if ($context eq 'upload_embedded') {
          $output = '<input name="embedded_item_'.$num.'" type="file" value="" />'."\n";
       }
       $output .= '<input name="embedded_orig_'.$num.'" type="hidden" value="'.
                  &escape($embed_file).'" />';
       unless (($context eq 'upload_embedded') && 
               ($mapping->{$embed_file} eq $embed_file)) {
           $output .='
           <input name="embedded_ref_'.$num.'" type="hidden" value="'.&escape($mapping->{$embed_file}).'" />';
       }
       my $attrib;
       if (ref($allfiles->{$mapping->{$embed_file}}) eq 'ARRAY') {
           $attrib = &escape(join(':',@{$allfiles->{$mapping->{$embed_file}}}));
       }
       $output .=
           "\n\t\t".
           '<input name="embedded_attrib_'.$num.'" type="hidden" value="'.
           $attrib.'" />';
       if (exists($codebase->{$mapping->{$embed_file}})) {
           $output .=
               "\n\t\t".
               '<input name="codebase_'.$num.'" type="hidden" value="'.
               &escape($codebase->{$mapping->{$embed_file}}).'" />';
       }
       return $output;
 }  }
   
 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) = @_;          $current_disk_usage,$hiddenstate,$actionurl) = @_;
     my $output;      my (%pathchange,$output,$modifyform,$footer,$returnflag);
     for (my $i=0; $i<$env{'form.number_embedded_items'}; $i++) {      for (my $i=0; $i<$env{'form.number_embedded_items'}; $i++) {
         next if (!exists($env{'form.embedded_item_'.$i.'.filename'}));          next if (!exists($env{'form.embedded_item_'.$i.'.filename'}));
         my $orig_uploaded_filename =          my $orig_uploaded_filename =
             $env{'form.embedded_item_'.$i.'.filename'};              $env{'form.embedded_item_'.$i.'.filename'};
           foreach my $type ('orig','ref','attrib','codebase') {
         $env{'form.embedded_orig_'.$i} =              if ($env{'form.embedded_'.$type.'_'.$i} ne '') {
             &unescape($env{'form.embedded_orig_'.$i});                  $env{'form.embedded_'.$type.'_'.$i} =
                       &unescape($env{'form.embedded_'.$type.'_'.$i});
               }
           }
         my ($path,$fname) =          my ($path,$fname) =
             ($env{'form.embedded_orig_'.$i} =~ m{(.*/)([^/]*)});              ($env{'form.embedded_orig_'.$i} =~ m{(.*/)([^/]*)});
         # no path, whole string is fname          # no path, whole string is fname
         if (!$fname) { $fname = $env{'form.embedded_orig_'.$i} };          if (!$fname) { $fname = $env{'form.embedded_orig_'.$i} };
   
         $path = $env{'form.currentpath'}.$path;  
         $fname = &Apache::lonnet::clean_filename($fname);          $fname = &Apache::lonnet::clean_filename($fname);
         # See if there is anything left          # See if there is anything left
         next if ($fname eq '');          next if ($fname eq '');
Line 8366  sub upload_embedded { Line 9277  sub upload_embedded {
             if ($group ne '') {              if ($group ne '') {
                 $port_path = "groups/$group/$port_path";                  $port_path = "groups/$group/$port_path";
             }              }
             ($state,$msg) = &check_for_upload($path,$fname,$group,'embedded_item_'.$i,              ($state,$msg) = &check_for_upload($env{'form.currentpath'}.$path,
                                                 $fname,$group,'embedded_item_'.$i,
                                               $dir_root,$port_path,$disk_quota,                                                $dir_root,$port_path,$disk_quota,
                                               $current_disk_usage,$uname,$udom);                                                $current_disk_usage,$uname,$udom);
             if ($state eq 'will_exceed_quota'              if ($state eq 'will_exceed_quota'
                 || $state eq 'file_locked'                  || $state eq 'file_locked') {
                 || $state eq 'file_exists' ) {  
                 $output .= $msg;                  $output .= $msg;
                 next;                  next;
             }              }
Line 8385  sub upload_embedded { Line 9296  sub upload_embedded {
         # Check if extension is valid          # Check if extension is valid
         if (($fname =~ /\.(\w+)$/) &&          if (($fname =~ /\.(\w+)$/) &&
             (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {              (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
             $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1);              $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1).'<br />';
             next;              next;
         } elsif (($fname =~ /\.(\w+)$/) &&          } elsif (($fname =~ /\.(\w+)$/) &&
                  (!defined(&Apache::loncommon::fileembstyle($1)))) {                   (!defined(&Apache::loncommon::fileembstyle($1)))) {
             $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);              $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1).'<br />';
             next;              next;
         } elsif ($fname=~/\.(\d+)\.(\w+)$/) {          } elsif ($fname=~/\.(\d+)\.(\w+)$/) {
             $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);              $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;
                 &Apache::lonnet::userfileupload('embedded_item_'.$i,'',              if ($state eq 'existingfile') {
                                                 $dirpath.$path);                  $result=
                       &Apache::lonnet::userfileupload('embedded_item_'.$i,'existingfile',
                                                       $dirpath.$env{'form.currentpath'}.$path);
               } else {
                   $result=
                       &Apache::lonnet::userfileupload('embedded_item_'.$i,'',
                                                       $dirpath.
                                                       $env{'form.currentpath'}.$path);
                   if ($result !~ m|^/uploaded/|) {
                       $output .= '<span class="LC_error">'
                                  .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
                                  ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i})
                                  .'</span><br />';
                       next;
                   } else {
                       $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
                                  $path.$fname.'</span>').'<br />';     
                   }
               }
           } elsif ($context eq 'coursedoc') {
               my $result =
                   &Apache::lonnet::userfileupload('embedded_item_'.$i,'coursedoc',
                                                   $dirpath.'/'.$path);
             if ($result !~ m|^/uploaded/|) {              if ($result !~ m|^/uploaded/|) {
                 $output .= '<span class="LC_error">'                  $output .= '<span class="LC_error">'
                       .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'                             .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
                            ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i})                             ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i})
                       .'</span><br />';                             .'</span><br />';
                 next;                      next;
             } else {              } else {
                 $output .= '<p>'.&mt('Uploaded [_1]','<span class="LC_filename">'.                  $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
                            $path.$fname.'</span>').'</p>';                                  $path.$fname.'</span>').'<br />';
             }              }
         } else {          } else {
 # Save the file  # Save the file
Line 8417  sub upload_embedded { Line 9350  sub upload_embedded {
             my $fullpath = $dir_root.$dirpath.'/'.$path;              my $fullpath = $dir_root.$dirpath.'/'.$path;
             my $dest = $fullpath.$fname;              my $dest = $fullpath.$fname;
             my $url = $url_root.$dirpath.'/'.$path.$fname;              my $url = $url_root.$dirpath.'/'.$path.$fname;
             my @parts=split(/\//,$fullpath);              my @parts=split(/\//,"$dirpath/$path");
             my $count;              my $count;
             my $filepath = $dir_root;              my $filepath = $dir_root;
             for ($count=4;$count<=$#parts;$count++) {              foreach my $subdir (@parts) {
                 $filepath .= "/$parts[$count]";                  $filepath .= "/$subdir";
                 if ((-e $filepath)!=1) {                  if (!-e $filepath) {
                     mkdir($filepath,0770);                      mkdir($filepath,0770);
                 }                  }
             }              }
Line 8439  sub upload_embedded { Line 9372  sub upload_embedded {
                               &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 {
                     if ($context eq 'testbank') {                      $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
                         $output .= &mt('Embedded file uploaded successfully:').                                 $url.'</span>').'<br />';
                                    '&nbsp;<a href="'.$url.'">'.                      unless ($context eq 'testbank') {
                                    $orig_uploaded_filename.'</a><br />';                          $footer .= &mt('View embedded file: [_1]',
                     } else {                                         '<a href="'.$url.'">'.$fname.'</a>').'<br />';
                         $output .= '<span class=\"LC_fontsize_large\">'.  
                                    &mt('View embedded file: [_1]','<a href="'.$url.'">'.  
                                    $orig_uploaded_filename.'</a>').'</span><br />';  
                     }                      }
                 }                  }
                 close($fh);                  close($fh);
             }              }
         }          }
           if ($env{'form.embedded_ref_'.$i}) {
               $pathchange{$i} = 1;
           }
       }
       if ($output) {
           $output = '<p>'.$output.'</p>';
       }
       $output .= &modify_html_form('upload_embedded',$actionurl,$hiddenstate,\%pathchange);
       $returnflag = 'ok';
       if (keys(%pathchange) > 0) {
           if ($context eq 'portfolio') {
               $output .= '<p>'.&mt('or').'</p>';
           } 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>';
               $returnflag = 'modify_orightml';
           }
       }
       return ($output.$footer,$returnflag);
   }
   
   sub modify_html_form {
       my ($context,$actionurl,$hiddenstate,$pathchange,$pathchgtable) = @_;
       my $end = 0;
       my $modifyform;
       if ($context eq 'upload_embedded') {
           return unless (ref($pathchange) eq 'HASH');
           if ($env{'form.number_embedded_items'}) {
               $end += $env{'form.number_embedded_items'};
           }
           if ($env{'form.number_pathchange_items'}) {
               $end += $env{'form.number_pathchange_items'};
           }
           if ($end) {
               for (my $i=0; $i<$end; $i++) {
                   if ($i < $env{'form.number_embedded_items'}) {
                       next unless($pathchange->{$i});
                   }
                   $modifyform .=
                       &start_data_table_row().
                       '<td><input type ="checkbox" name="namechange" value="'.$i.'" '.
                       'checked="checked" /></td>'.
                       '<td>'.$env{'form.embedded_ref_'.$i}.
                       '<input type="hidden" name="embedded_ref_'.$i.'" value="'.
                       &escape($env{'form.embedded_ref_'.$i}).'" />'.
                       '<input type="hidden" name="embedded_codebase_'.$i.'" value="'.
                       &escape($env{'form.embedded_codebase_'.$i}).'" />'.
                       '<input type="hidden" name="embedded_attrib_'.$i.'" value="'.
                       &escape($env{'form.embedded_attrib_'.$i}).'" /></td>'.
                       '<td>'.$env{'form.embedded_orig_'.$i}.
                       '<input type="hidden" name="embedded_orig_'.$i.'" value="'.
                       &escape($env{'form.embedded_orig_'.$i}).'" /></td>'.
                       &end_data_table_row();
               } 
           }
       } else {
           $modifyform = $pathchgtable;
           if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
               $hiddenstate .= '<input type="hidden" name="phase" value="four" />';
           } elsif (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
               $hiddenstate .= '<input type="hidden" name="action" value="modify_orightml" />';
           }
       }
       if ($modifyform) {
           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".
                  '<li>'.&mt('For consistency between the reference(s) and the location of the corresponding stored file within LON-CAPA.').'</li>'."\n".
                  '<li>'.&mt('To change absolute paths to relative paths, or replace directory traversal via "../" within the original reference.').'</li>'."\n".
                  '</ol></p>'."\n".'<p>'.
                  &mt('LON-CAPA can make the required changes to your HTML file.').'</p>'."\n".
                  '<form method="post" name="refchanger" action="'.$actionurl.'">'.
                  &start_data_table()."\n".
                  &start_data_table_header_row().
                  '<th>'.&mt('Change?').'</th>'.
                  '<th>'.&mt('Current reference').'</th>'.
                  '<th>'.&mt('Required reference').'</th>'.
                  &end_data_table_header_row()."\n".
                  $modifyform.
                  &end_data_table().'<br />'."\n".$hiddenstate.
                  '<input type="submit" name="pathchanges" value="'.&mt('Modify HTML file').'" />'.
                  '</form>'."\n";
       }
       return;
   }
   
   sub modify_html_refs {
       my ($context,$dirpath,$uname,$udom,$dir_root) = @_;
       my $container;
       if ($context eq 'portfolio') {
           $container = $env{'form.container'};
       } elsif ($context eq 'coursedoc') {
           $container = $env{'form.primaryurl'};
       } else {
           $container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'};
       }
       my (%allfiles,%codebase,$output,$content);
       my @changes = &get_env_multiple('form.namechange');
       return unless (@changes > 0);
       if (($context eq 'portfolio') || ($context eq 'coursedoc')) {
           return unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/});
           $content = &Apache::lonnet::getfile($container);
           return if ($content eq '-1');
       } else {
           return unless ($container =~ /^\Q$dir_root\E/); 
           if (open(my $fh,"<$container")) {
               $content = join('', <$fh>);
               close($fh);
           } else {
               return;
           }
       }
       my ($count,$codebasecount) = (0,0);
       my $mm = new File::MMagic;
       my $mime_type = $mm->checktype_contents($content);
       if ($mime_type eq 'text/html') {
           my $parse_result = 
               &Apache::lonnet::extract_embedded_items($container,\%allfiles,
                                                       \%codebase,\$content);
           if ($parse_result eq 'ok') {
               foreach my $i (@changes) {
                   my $orig = &unescape($env{'form.embedded_orig_'.$i});
                   my $ref = &unescape($env{'form.embedded_ref_'.$i});
                   if ($allfiles{$ref}) {
                       my $newname =  $orig;
                       my ($attrib_regexp,$codebase);
                       $attrib_regexp = &unescape($env{'form.embedded_attrib_'.$i});
                       if ($attrib_regexp =~ /:/) {
                           $attrib_regexp =~ s/\:/|/g;
                       }
                       if ($content =~ m{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}) {
                           my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);
                           $count += $numchg;
                       }
                       if ($env{'form.embedded_codebase_'.$i} ne '') {
                           $codebase = &unescape($env{'form.embedded_codebase_'.$i});
                           my $numchg = ($content =~ s/(codebase\s*=\s*["']?)\Q$codebase\E(["']?)/$1.$2/i); #' stupid emacs
                           $codebasecount ++;
                       }
                   }
               }
               if ($count || $codebasecount) {
                   my $saveresult;
                   if ($context eq 'portfolio' || $context eq 'coursedoc') {
                       my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
                       if ($url eq $container) {
                           my ($fname) = ($container =~ m{/([^/]+)$});
                           $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',
                                               $count,'<span class="LC_filename">'.
                                               $fname.'</span>').'</p>'; 
                       } else {
                            $output = '<p class="LC_error">'.
                                      &mt('Error: update failed for: [_1].',
                                      '<span class="LC_filename">'.
                                      $container.'</span>').'</p>';
                       }
                   } else {
                       if (open(my $fh,">$container")) {
                           print $fh $content;
                           close($fh);
                           $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',
                                     $count,'<span class="LC_filename">'.
                                     $container.'</span>').'</p>';
                       } else {
                            $output = '<p class="LC_error">'.
                                      &mt('Error: could not update [_1].',
                                      '<span class="LC_filename">'.
                                      $container.'</span>').'</p>';
                       }
                   }
               }
           } else {
               &logthis('Failed to parse '.$container.
                        ' to modify references: '.$parse_result);
           }
     }      }
     return $output;      return $output;
 }  }
Line 8475  sub check_for_existing { Line 9578  sub check_for_existing {
 sub check_for_upload {  sub check_for_upload {
     my ($path,$fname,$group,$element,$portfolio_root,$port_path,      my ($path,$fname,$group,$element,$portfolio_root,$port_path,
         $disk_quota,$current_disk_usage,$uname,$udom) = @_;          $disk_quota,$current_disk_usage,$uname,$udom) = @_;
     my $filesize = (length($env{'form.'.$element})) / 1000; #express in k (1024?)      my $filesize = length($env{'form.'.$element});
       if (!$filesize) {
           my $msg = '<span class="LC_error">'.
                     &mt('Unable to upload [_1]. (size = [_2] bytes)', 
                         '<span class="LC_filename">'.$fname.'</span>',
                         $filesize).'<br />'.
                     &mt('Either the file you attempted to upload was empty, or your web browser was unable to read its contents.').'<br />'.
                     '</span>';
           return ('zero_bytes',$msg);
       }
       $filesize =  $filesize/1000; #express in k (1024?)
     my $getpropath = 1;      my $getpropath = 1;
     my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,      my ($dirlistref,$listerror) =
                                             $getpropath);           &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,$getpropath);
     my $found_file = 0;      my $found_file = 0;
     my $locked_file = 0;      my $locked_file = 0;
     foreach my $line (@dir_list) {      my @lockers;
         my ($file_name)=split(/\&/,$line,2);      my $navmap;
         if ($file_name eq $fname){      if ($env{'request.course.id'}) {
             $file_name = $path.$file_name;          $navmap = Apache::lonnavmaps::navmap->new();
             if ($group ne '') {      }
                 $file_name = $group.$file_name;      if (ref($dirlistref) eq 'ARRAY') {
             }          foreach my $line (@{$dirlistref}) {
             $found_file = 1;              my ($file_name,$rest)=split(/\&/,$line,2);
             if (&Apache::lonnet::is_locked($file_name,$udom,$uname) eq 'true') {              if ($file_name eq $fname){
                 $locked_file = 1;                  $file_name = $path.$file_name;
                   if ($group ne '') {
                       $file_name = $group.$file_name;
                   }
                   $found_file = 1;
                   if (&Apache::lonnet::is_locked($file_name,$udom,$uname,\@lockers) eq 'true') {
                       foreach my $lock (@lockers) {
                           if (ref($lock) eq 'ARRAY') {
                               my ($symb,$crsid) = @{$lock};
                               if ($crsid eq $env{'request.course.id'}) {
                                   if (ref($navmap)) {
                                       my $res = $navmap->getBySymb($symb);
                                       foreach my $part (@{$res->parts()}) { 
                                           my ($slot_status,$slot_time,$slot_name)=$res->check_for_slot($part);
                                           unless (($slot_status == $res->RESERVED) ||
                                                   ($slot_status == $res->RESERVED_LOCATION)) {
                                               $locked_file = 1;
                                           }
                                       }
                                   } else {
                                       $locked_file = 1;
                                   }
                               } else {
                                   $locked_file = 1;
                               }
                           }
                      }
                   } else {
                       my @info = split(/\&/,$rest);
                       my $currsize = $info[6]/1000;
                       if ($currsize < $filesize) {
                           my $extra = $filesize - $currsize;
                           if (($current_disk_usage + $extra) > $disk_quota) {
                               my $msg = '<span class="LC_error">'.
                                         &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',
                                             '<span class="LC_filename">'.$fname.'</span>',$filesize,$currsize).'</span>'.
                                         '<br />'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
                                                      $disk_quota,$current_disk_usage);
                               return ('will_exceed_quota',$msg);
                           }
                       }
                   }
             }              }
         }          }
     }      }
Line 8508  sub check_for_upload { Line 9662  sub check_for_upload {
             return ('file_locked',$msg);              return ('file_locked',$msg);
         } else {          } else {
             my $msg = '<span class="LC_error">';              my $msg = '<span class="LC_error">';
             $msg .= &mt('Unable to upload [_1]. A file by that name was found in [_2].','<span class="LC_filename">'.$fname.'</span>',$port_path.$env{'form.currentpath'});              $msg .= &mt(' A file by that name: [_1] was found in [_2].','<span class="LC_filename">'.$fname.'</span>',$port_path.$env{'form.currentpath'});
             $msg .= '</span>';              $msg .= '</span>';
             $msg .= '<br />';              return ('existingfile',$msg);
             $msg .= &mt('To upload, rename or delete existing [_1] in [_2].','<span class="LC_filename">'.$fname.'</span>', $port_path.$env{'form.currentpath'});          }
             return ('file_exists',$msg);      }
   }
   
   sub check_for_traversal {
       my ($path,$url,$toplevel) = @_;
       my @parts=split(/\//,$path);
       my $cleanpath;
       my $fullpath = $url;
       for (my $i=0;$i<@parts;$i++) {
           next if ($parts[$i] eq '.');
           if ($parts[$i] eq '..') {
               $fullpath =~ s{([^/]+/)$}{};
           } else {
               $fullpath .= $parts[$i].'/';
           }
       }
       if ($fullpath =~ /^\Q$url\E(.*)$/) {
           $cleanpath = $1;
       } elsif ($fullpath =~ /^\Q$toplevel\E(.*)$/) {
           my $curr_toprel = $1;
           my @parts = split(/\//,$curr_toprel);
           my ($url_toprel) = ($url =~ /^\Q$toplevel\E(.*)$/);
           my @urlparts = split(/\//,$url_toprel);
           my $doubledots;
           my $startdiff = -1;
           for (my $i=0; $i<@urlparts; $i++) {
               if ($startdiff == -1) {
                   unless ($urlparts[$i] eq $parts[$i]) {
                       $startdiff = $i;
                       $doubledots .= '../';
                   }
               } else {
                   $doubledots .= '../';
               }
           }
           if ($startdiff > -1) {
               $cleanpath = $doubledots;
               for (my $i=$startdiff; $i<@parts; $i++) {
                   $cleanpath .= $parts[$i].'/';
               }
           }
       }
       $cleanpath =~ s{(/)$}{};
       return $cleanpath;
   }
   
   sub is_archive_file {
       my ($mimetype) = @_;
       if (($mimetype eq 'application/octet-stream') ||
           ($mimetype eq 'application/x-stuffit') ||
           ($mimetype =~ m{^application/(x\-)?(compressed|tar|zip|tgz|gz|gtar|gzip|gunzip|bz|bz2|bzip2)})) {
           return 1;
       }
       return;
   }
   
   sub decompress_form {
       my ($mimetype,$archiveurl,$action,$noextract,$hiddenelements) = @_;
       my %lt = &Apache::lonlocal::texthash (
           this => 'This file is an archive file.',
           youm => 'You may wish to extract its contents.',
           camt => 'Extraction of contents is recommended for Camtasia zip files.',
           perm => 'Permanently remove archive file after extraction of contents?',
           extr => 'Extract contents',
           yes  => 'Yes',
           no   => 'No',
       );
       my $output = '<p>'.$lt{'this'}.' '.$lt{'youm'}.'<br />';
       if ($mimetype =~ m{^application/(x\-)?(compressed|zip)}) {
           $output .= $lt{'camt'};
       }
       $output .= '</p>';
       $output .= <<"START";
   <div id="uploadfileresult">
     <form name="uploaded_decompress" action="$action" method="post">
     <input type="hidden" name="archiveurl" value="$archiveurl" />
   START
       if (ref($hiddenelements) eq 'HASH') {
           foreach my $hidden (sort(keys(%{$hiddenelements}))) {
               $output .= '<input type="hidden" name="'.$hidden.'" value="'.$hiddenelements->{$hidden}.'" />'."\n";
           }
       }
       $output .= <<"END";
   <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'}" />
   </form>
   $noextract
   </div>
   END
       return $output;
   }
   
   sub decompress_uploaded_file {
       my ($file,$dir) = @_;
       &Apache::lonnet::appenv({'cgi.file' => $file});
       &Apache::lonnet::appenv({'cgi.dir' => $dir});
       my $result = &Apache::lonnet::ssi_body('/cgi-bin/decompress.pl');
       my ($handle) = ($env{'user.environment'} =~m{/([^/]+)\.id$});
       my $lonidsdir = $Apache::lonnet::perlvar{'lonIDsDir'};
       &Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle,1);
       my $decompressed = $env{'cgi.decompressed'};
       &Apache::lonnet::delenv('cgi.file');
       &Apache::lonnet::delenv('cgi.dir');
       &Apache::lonnet::delenv('cgi.decompressed');
       return ($decompressed,$result);
   }
   
   sub process_decompression {
       my ($docudom,$docuname,$file,$destination,$dir_root,$hiddenelem) = @_;
       my ($dir,$error,$warning,$output);
       if ($file !~ /\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/) {
           $error = &mt('File name not a supported archive file type.').
                    '<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";
               my ($currdirlistref,$currlisterror) =
                   &Apache::lonnet::dirlist($currdir,$docudom,$docuname,1);
               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.');
                   }
               }
               if ($dir eq '') {
                   $error = &mt('Directory containing archive file unavailable.');
               } elsif (!$error) {
                   my ($decompressed,$display) = &decompress_uploaded_file($file,$dir);
                   if ($decompressed eq 'ok') {
                       $output = &mt('Files extracted successfully from archive.').'<br />';
                       my ($warning,$result,@contents);
                       my ($newdirlistref,$newlisterror) =
                           &Apache::lonnet::dirlist($currdir,$docudom,
                                                    $docuname,1);
                       my (%is_dir,%changes,@newitems);
                       my $dirptr = 16384;
                       if (ref($currdirlistref) eq 'ARRAY') {
                           my @curritems;
                           foreach my $dir_line (@{$currdirlistref}) {
                               my ($item,$rest)=split(/\&/,$dir_line,2);
                               unless ($item =~ /\.+$/) {
                                   push(@curritems,$item);
                               }
                           }
                           if (ref($newdirlistref) eq 'ARRAY') {
                               foreach my $dir_line (@{$newdirlistref}) {
                                   my ($item,undef,undef,$testdir)=split(/\&/,$dir_line,4);
                                   unless ($item =~ /^\.+$/) {
                                       if ($dirptr&$testdir) {
                                           $is_dir{$item} = 1;
                                       }
                                       push(@newitems,$item);
                                   }
                               }
                               my @diffs = &compare_arrays(\@curritems,\@newitems);
                               if (@diffs > 0) {
                                  foreach my $item (@diffs) {
                                      $changes{$item} = 1;
                                  }
                               }
                           }
                       } elsif (ref($newdirlistref) eq 'ARRAY') {
                           foreach my $dir_line (@{$newdirlistref}) {
                               my ($item,undef,undef,$testdir)=split(/\&/,$dir_line,5);
                               unless ($item =~ /\.+$/) {
                                   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 (%children,%parent,%dirorder,%titles);
                           my $wantform = 1;
                           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 = 4;
                               $output .= &archive_javascript($startcount,$count,
                                                              \%titles,\%children);
                           }
                       } 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 ++;
           $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>';
           }
           $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,$output,$count,$hiddenelem) = @_;
       return '<form name="'.$form.'" method="post" action="">'."\n".
              '<input type="hidden" name="phase" value="decompress_cleanup" />'."\n".
                       '<p>'.
                       &mt('How should each item be incorporated in the course?').
                       '</p>'.
                       '<div class="LC_columnSection"><fieldset>'.
                       '<legend>'.&mt('Content actions for all').'</legend>'.
                       '<input type="button" value="'.&mt('Display in Contents').'" '.
                       'onclick="javascript:checkAll(document.'.$form.",'display'".')" />'.
                       '&nbsp;&nbsp;<input type="button" value="'.&mt('Include as dependency for a displayed item').'"'.
                       ' onclick="javascript:checkAll(document.'.$form.",'dependency'".')" />'.
                       '&nbsp;&nbsp;<input type="button" value="'.&mt('Discard').'"'.
                       ' onclick="javascript:checkAll(document.'.$form.",'discard'".')" />'.
                        '</fieldset></div>'.
              &start_data_table()."\n".
              $output."\n".
              &end_data_table()."\n".
              '<input type="hidden" name="archive_count" value="'.$count.'" />'.
              $hiddenelem.
              '<br /><input type="submit" name="archive_submit" value="'.&mt('Save').'" />'.
              '</form>';
   }
   
   sub archive_javascript {
       my ($startcount,$numitems,$titles,$children) = @_;
       return unless ((ref($titles) eq 'HASH') && (ref($children) eq 'HASH'));
       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%6;
                       var count = (nostart-offset)/6;    
                       dependencyCheck(form,count,offset);
                   }
               }
           }
       }
   }
   
   function propagateCheck(form,count) {
       if (count > 0) {
           var startelement = $startcount + ((count-1) * 6);
           for (var j=1; j<5; j++) {
               if (j != 3) {
                   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;
   }
   
   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)+6*(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)+6*(count-1);
           var depitem = $startcount + ((count-1) * 6) + 3;
           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<count; i++) {
                   var startelement = $startcount + (i-1) * 6;
                   for (var j=1; j<5; j++) {
                       if (j != 3) {
                           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);
           }
       }
   }
   
   function propagateSelect(form,count,offset) {
       if (count > 0) {
           var item = (1+offset+$startcount)+6*(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)+6*(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);
                           }
                       }
                   }
               }
           }
       }
   }
   
   // ]]>
   </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);
       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);
       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,%newdest,%newseqid);
       if ($numitems) {
           for (my $i=1; $i<=$numitems; $i++) {
               my $path = $env{'form.archive_content_'.$i};
               if ($path =~ /^\Q$pathtocheck\E/) {
                   if ($env{'form.archive_'.$i} eq 'discard') {
                       if ($prefix ne '' && $path ne '') {
                           if (-e $prefix.$path) {
                               $todelete{$prefix.$path} = 1;
                           }
                       }
                   } elsif ($env{'form.archive_'.$i} eq 'display') {
                       my ($title,$url,$outer);
                       ($title) = ($path =~ m{/([^/]+)$});
                       $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]=
                                   $title.':'.$url.':false:normal:res';
                               push(@LONCAPA::map::order,$newidx);
                               my ($outtext,$errtext) =
                                   &LONCAPA::map::storemap('/uploaded/'.$docudom.'/'.
                                                           $docuname.'/'.$folders{$outer}.
                                                           '.'.$containers{$outer},1);
                               $newseqid{$i} = $newidx;
                           }
                       } 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";
                               }
                               $LONCAPA::map::resources[$newidx]=
                                   $title.':'.$url.':false:normal:res';
                               push(@LONCAPA::map::order, $newidx);
                               my ($outtext,$errtext)=
                                   &LONCAPA::map::storemap('/uploaded/'.$docudom.'/'.
                                                           $docuname.'/'.$folders{$outer}.
                                                           '.'.$containers{$outer},1);
                           }
                       }
                   } elsif ($env{'form.archive_'.$i} eq 'dependency') {
                       my ($title) = ($path =~ m{/([^/]+)$});
                       $referrer{$i} = $env{'form.archive_dependent_on_'.$i};
                       if ($env{'form.archive_'.$referrer{$i}} eq 'display') {
                           if (ref($dirorder{$i}) eq 'ARRAY') {
                               my ($itemidx,$fullpath);
                               for (my $j=0; $j<@{$dirorder{$i}}; $j++) {
                                   if (ref($dirorder{$referrer{$i}}) eq 'ARRAY') {
                                       my $container = $dirorder{$referrer{$i}}->[-1];
                                       for (my $j=0; $j<@{$dirorder{$i}}; $j++) {
                                           if ($dirorder{$i}->[$j] eq $container) {
                                               $itemidx = $j;
                                           }
                                       }
                                   }
                               }
                               if ($itemidx ne '') {
                                   if (grep(/^\Q$referrer{$i}\E$/,@archdirs)) {
                                       if ($mapinner{$referrer{$i}}) {
                                           $fullpath = "$prefix$dir/$docstype/$mapinner{$referrer{$i}}";
                                           for (my $j=$itemidx; $j<@{$dirorder{$i}}; $j++) {
                                               if (grep(/^\Q$dirorder{$i}->[$j]\E$/,@archdirs)) {
                                                   unless (defined($newseqid{$dirorder{$i}->[$j]})) {
                                                       $fullpath .= '/'.$titles{$dirorder{$i}->[$j]};
                                                       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]};
                                                   if (!-e $fullpath) {
                                                       mkdir($fullpath,0755);
                                                   }
                                               }
                                           } else {
                                               last;
                                           }
                                       }
                                   }
                                   if ($fullpath ne '') {
                                       system("mv $prefix$path $fullpath/$title");
                                   }
                               }
                           }
                       } 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);
                   unless ($ishome) {
                       #FIXME Need to notify homeserver to delete files.
                   }
               }
           }
       } 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;
 }  }
   
   =pod
   
   =item * &get_turnedin_filepath()
   
   Determines path in a user's portfolio file for storage of files uploaded
   to a specific essayresponse or dropbox item.
   
   Inputs: 3 required + 1 optional.
   $symb is symb for resource, $uname and $udom are for current user (required).
   $caller is optional (can be "submission", if routine is called when storing
   an upoaded file when "Submit Answer" button was pressed).
   
   Returns array containing $path and $multiresp. 
   $path is path in portfolio.  $multiresp is 1 if this resource contains more
   than one file upload item.  Callers of routine should append partid as a 
   subdirectory to $path in cases where $multiresp is 1.
   
   Called by: homework/essayresponse.pm and homework/structuretags.pm
   
   =cut
   
   sub get_turnedin_filepath {
       my ($symb,$uname,$udom,$caller) = @_;
       my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb);
       my $turnindir;
       my %userhash = &Apache::lonnet::userenvironment($udom,$uname,'turnindir');
       $turnindir = $userhash{'turnindir'};
       my ($path,$multiresp);
       if ($turnindir eq '') {
           if ($caller eq 'submission') {
               $turnindir = &mt('turned in');
               $turnindir =~ s/\W+/_/g;
               my %newhash = (
                               'turnindir' => $turnindir,
                             );
               &Apache::lonnet::put('environment',\%newhash,$udom,$uname);
           }
       }
       if ($turnindir ne '') {
           $path = '/'.$turnindir.'/';
           my ($multipart,$turnin,@pathitems);
           my $navmap = Apache::lonnavmaps::navmap->new();
           if (defined($navmap)) {
               my $mapres = $navmap->getResourceByUrl($map);
               if (ref($mapres)) {
                   my $pcslist = $mapres->map_hierarchy();
                   if ($pcslist ne '') {
                       foreach my $pc (split(/,/,$pcslist)) {
                           my $res = $navmap->getByMapPc($pc);
                           if (ref($res)) {
                               my $title = $res->compTitle();
                               $title =~ s/\W+/_/g;
                               if ($title ne '') {
                                   push(@pathitems,$title);
                               }
                           }
                       }
                   }
                   my $maptitle = $mapres->compTitle();
                   $maptitle =~ s/\W+/_/g;
                   if ($maptitle ne '') {
                       push(@pathitems,$maptitle);
                   }
                   unless ($env{'request.state'} eq 'construct') {
                       my $res = $navmap->getBySymb($symb);
                       if (ref($res)) {
                           my $partlist = $res->parts();
                           my $totaluploads = 0;
                           if (ref($partlist) eq 'ARRAY') {
                               foreach my $part (@{$partlist}) {
                                   my @types = $res->responseType($part);
                                   my @ids = $res->responseIds($part);
                                   for (my $i=0; $i < scalar(@ids); $i++) {
                                       if ($types[$i] eq 'essay') {
                                           my $partid = $part.'_'.$ids[$i];
                                           if (&Apache::lonnet::EXT("resource.$partid.uploadedfiletypes") ne '') {
                                               $totaluploads ++;
                                           }
                                       }
                                   }
                               }
                               if ($totaluploads > 1) {
                                   $multiresp = 1;
                               }
                           }
                       }
                   }
               } else {
                   return;
               }
           } else {
               return;
           }
           my $restitle=&Apache::lonnet::gettitle($symb);
           $restitle =~ s/\W+/_/g;
           if ($restitle eq '') {
               $restitle = ($resurl =~ m{/[^/]+$});
               if ($restitle eq '') {
                   $restitle = time;
               }
           }
           push(@pathitems,$restitle);
           $path .= join('/',@pathitems);
       }
       return ($path,$multiresp);
   }
   
 =pod  =pod
   
Line 10649  sub init_user_environment { Line 12663  sub init_user_environment {
     $env{'browser.interface'}=$form->{'interface'};      $env{'browser.interface'}=$form->{'interface'};
  }   }
   
           my %is_adv = ( is_adv => $env{'user.adv'} );
           my %domdef;
           unless ($domain eq 'public') {
               %domdef = &Apache::lonnet::get_domain_defaults($domain);
           }
   
         foreach my $tool ('aboutme','blog','portfolio') {          foreach my $tool ('aboutme','blog','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);
         }          }
   
         foreach my $crstype ('official','unofficial','community') {          foreach my $crstype ('official','unofficial','community') {
             $userenv{'canrequest.'.$crstype} =              $userenv{'canrequest.'.$crstype} =
                 &Apache::lonnet::usertools_access($username,$domain,$crstype,                  &Apache::lonnet::usertools_access($username,$domain,$crstype,
                                                   'reload','requestcourses');                                                    'reload','requestcourses',
                                                     \%userenv,\%domdef,\%is_adv);
         }          }
   
  $env{'user.environment'} = "$lonids/$cookie.id";   $env{'user.environment'} = "$lonids/$cookie.id";
Line 10736  sub clean_symb { Line 12758  sub clean_symb {
     return ($symb,$enc);      return ($symb,$enc);
 }  }
   
   sub build_release_hashes {
       my ($checkparms,$checkresponsetypes,$checkcrstypes,$anonsurvey,$randomizetry) = @_;
       return unless((ref($checkparms) eq 'HASH') && (ref($checkresponsetypes) eq 'HASH') &&
                     (ref($checkcrstypes) eq 'HASH') && (ref($anonsurvey) eq 'HASH') &&
                     (ref($randomizetry) eq 'HASH'));
       foreach my $key (keys(%Apache::lonnet::needsrelease)) {
           my ($item,$name,$value) = split(/:/,$key);
           if ($item eq 'parameter') {
               if (ref($checkparms->{$name}) eq 'ARRAY') {
                   unless(grep(/^\Q$name\E$/,@{$checkparms->{$name}})) {
                       push(@{$checkparms->{$name}},$value);
                   }
               } else {
                   push(@{$checkparms->{$name}},$value);
               }
           } elsif ($item eq 'resourcetag') {
               if ($name eq 'responsetype') {
                   $checkresponsetypes->{$value} = $Apache::lonnet::needsrelease{$key}
               }
           } elsif ($item eq 'course') {
               if ($name eq 'crstype') {
                   $checkcrstypes->{$value} = $Apache::lonnet::needsrelease{$key};
               }
           }
       }
       ($anonsurvey->{major},$anonsurvey->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'});
       ($randomizetry->{major},$randomizetry->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:randomizetry'});
       return;
   }
   
 =pod  =pod
   
 =back  =back

Removed from v.1.976  
changed lines
  Added in v.1.1057


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