Diff for /loncom/interface/loncommon.pm between versions 1.692.4.15 and 1.1028.2.1

version 1.692.4.15, 2009/08/15 19:30:58 version 1.1028.2.1, 2011/12/26 13:47:18
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; # Language name LaTeX uses for selecting hyphenation.
 my %cprtag;  my %cprtag;
 my %scprtag;  my %scprtag;
 my %fe; my %fd; my %fm;  my %fe; my %fd; my %fm;
Line 186  BEGIN { Line 187  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{$two} = $latex;
    }
             }              }
             close($fh);              close($fh);
         }          }
Line 271  BEGIN { Line 275  BEGIN {
         }          }
     }      }
     &Apache::lonnet::logthis(      &Apache::lonnet::logthis(
               "<font color=yellow>INFO: Read file types</font>");               "<span style='color:yellow;'>INFO: Read file types</span>");
     $readit=1;      $readit=1;
     }  # end of unless($readit)       }  # end of unless($readit) 
           
Line 409  sub studentbrowser_javascript { Line 413  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 425  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 440  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 479  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 487  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">  <script type="text/javascript" language="JavaScript">
 // <![CDATA[  // <![CDATA[
 var stdeditbrowser;  var stdeditbrowser;
   
Line 475  function openauthorbrowser(formname,udom Line 515  function openauthorbrowser(formname,udom
     stdeditbrowser = open(url,title,options,'1');      stdeditbrowser = open(url,title,options,'1');
     stdeditbrowser.focus();      stdeditbrowser.focus();
 }  }
   
 // ]]>  // ]]>
 </script>  </script>
 ENDAUTHORBRW  ENDAUTHORBRW
 }  }
   
 sub coursebrowser_javascript {  sub coursebrowser_javascript {
     my ($domainfilter,$sec_element,$formname)=@_;      my ($domainfilter,$sec_element,$formname,$role_element,$crstype) = @_;
     my $crs_or_grp_alert = &mt('Please select the type of LON-CAPA entity - Course or Community - for which you wish to add/modify a user role');      my $wintitle = 'Course_Browser';
       if ($crstype eq 'Community') {
           $wintitle = 'Community_Browser';
       }
     my $id_functions = &javascript_index_functions();      my $id_functions = &javascript_index_functions();
     my $output = '      my $output = '
 <script type="text/javascript" language="JavaScript">  <script type="text/javascript" language="JavaScript">
Line 490  sub coursebrowser_javascript { Line 534  sub coursebrowser_javascript {
     var stdeditbrowser;'."\n";      var stdeditbrowser;'."\n";
   
     $output .= <<"ENDSTDBRW";      $output .= <<"ENDSTDBRW";
     function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag,crstype) {      function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag,type,type_elem) {
         var url = '/adm/pickcourse?';          var url = '/adm/pickcourse?';
           var formid = getFormIdByName(formname);
         var domainfilter = getDomainFromSelectbox(formname,udom);          var domainfilter = getDomainFromSelectbox(formname,udom);
         if (domainfilter != null) {          if (domainfilter != null) {
            if (domainfilter != '') {             if (domainfilter != '') {
Line 511  sub coursebrowser_javascript { Line 556  sub coursebrowser_javascript {
             else {              else {
                 if (formname == 'portform') {                  if (formname == 'portform') {
                     url += '&setroles='+extra_element;                      url += '&setroles='+extra_element;
                   } else {
                       if (formname == 'rules') {
                           url += '&fixeddom='+extra_element; 
                       }
                 }                  }
             }                   }     
         }          }
           if (type != null && type != '') {
               url += '&type='+type;
           }
           if (type_elem != null && type_elem != '') {
               url += '&typeelement='+type_elem;
           }
         if (formname == 'ccrs') {          if (formname == 'ccrs') {
             var ownername = document.forms[formid].ccuname.value;              var ownername = document.forms[formid].ccuname.value;
             var ownerdom =  document.forms[formid].ccdomain.options[document.forms[formid].ccdomain.selectedIndex].value;              var ownerdom =  document.forms[formid].ccdomain.options[document.forms[formid].ccdomain.selectedIndex].value;
Line 522  sub coursebrowser_javascript { Line 577  sub coursebrowser_javascript {
         if (multflag !=null && multflag != '') {          if (multflag !=null && multflag != '') {
             url += '&multiple='+multflag;              url += '&multiple='+multflag;
         }          }
         if (crstype == 'Course/Community') {          var title = '$wintitle';
             if (formname == 'cu') {  
                 crstype = document.cu.crstype.options[document.cu.crstype.selectedIndex].value;   
                 if (crstype == "") {  
                     alert("$crs_or_grp_alert");  
                     return;  
                 }  
             }  
         }  
         if (crstype !=null && crstype != '') {  
             url += '&type='+crstype;  
         }  
         var title = 'Course_Browser';  
         var options = 'scrollbars=1,resizable=1,menubar=0';          var options = 'scrollbars=1,resizable=1,menubar=0';
         options += ',width=700,height=600';          options += ',width=700,height=600';
         stdeditbrowser = open(url,title,options,'1');          stdeditbrowser = open(url,title,options,'1');
Line 542  sub coursebrowser_javascript { Line 585  sub coursebrowser_javascript {
     }      }
 $id_functions  $id_functions
 ENDSTDBRW  ENDSTDBRW
     if ($sec_element ne '') {      if (($sec_element ne '') || ($role_element ne '')) {
         $output .= &setsec_javascript($sec_element,$formname);          $output .= &setsec_javascript($sec_element,$formname,$role_element);
     }      }
     $output .= '      $output .= '
 // ]]>  // ]]>
Line 593  ENDJS Line 636  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";
   
 function openuserbrowser(formname,uname,udom,ulast,ufirst,uemail,hideudom,crsdom) {  function openuserbrowser(formname,uname,udom,ulast,ufirst,uemail,hideudom,crsdom,caller) {
     var url = '/adm/pickuser?';      var url = '/adm/pickuser?';
     var userdom = getDomainFromSelectbox(formname,udom);      var userdom = getDomainFromSelectbox(formname,udom);
     if (userdom != null) {      if (userdom != null) {
Line 612  function openuserbrowser(formname,uname, Line 700  function openuserbrowser(formname,uname,
                                 '&uemailelement='+uemail+                                  '&uemailelement='+uemail+
                                 '&hideudomelement='+hideudom+                                  '&hideudomelement='+hideudom+
                                 '&coursedom='+crsdom;                                  '&coursedom='+crsdom;
       if ((caller != null) && (caller != undefined)) {
           url += '&caller='+caller;
       }
     var title = 'User_Browser';      var title = 'User_Browser';
     var options = 'scrollbars=1,resizable=1,menubar=0';      var options = 'scrollbars=1,resizable=1,menubar=0';
     options += ',width=700,height=600';      options += ',width=700,height=600';
Line 619  function openuserbrowser(formname,uname, Line 710  function openuserbrowser(formname,uname,
     stdeditbrowser.focus();      stdeditbrowser.focus();
 }  }
   
 function fix_domain (formname,udom,origdom) {  function fix_domain (formname,udom,origdom,uname) {
     var formid = getFormIdByName(formname);      var formid = getFormIdByName(formname);
     if (formid > -1) {      if (formid > -1) {
           var unameid = getIndexByName(formid,uname);
         var domid = getIndexByName(formid,udom);          var domid = getIndexByName(formid,udom);
         var hidedomid = getIndexByName(formid,origdom);          var hidedomid = getIndexByName(formid,origdom);
         if (hidedomid > -1) {          if (hidedomid > -1) {
             var fixeddom = document.forms[formid].elements[hidedomid].value;              var fixeddom = document.forms[formid].elements[hidedomid].value;
             if (domid > -1) {              var unameval = document.forms[formid].elements[unameid].value;
                 var slct = document.forms[formid].elements[domid];              if ((fixeddom != '') && (fixeddom != undefined) && (fixeddom != null) && (unameval != '') && (unameval != undefined) && (unameval != null)) {
                 if (slct.type == 'select-one') {                  if (domid > -1) {
                     var i;                      var slct = document.forms[formid].elements[domid];
                     for (i=0;i<slct.length;i++) {                      if (slct.type == 'select-one') {
                         if (slct.options[i].value==fixeddom) { slct.selectedIndex=i; }                          var i;
                           for (i=0;i<slct.length;i++) {
                               if (slct.options[i].value==fixeddom) { slct.selectedIndex=i; }
                           }
                       }
                       if (slct.type == 'hidden') {
                           slct.value = fixeddom;
                     }                      }
                 }  
                 if (slct.type == 'hidden') {  
                     slct.value = fixeddom;  
                 }                  }
             }              }
         }          }
Line 647  $id_functions Line 742  $id_functions
 ENDUSERBRW  ENDUSERBRW
 }  }
   
   
 sub setsec_javascript {  sub setsec_javascript {
     my ($sec_element,$formname) = @_;      my ($sec_element,$formname,$role_element) = @_;
       my (@courserolenames,@communityrolenames,$rolestr,$courserolestr,
           $communityrolestr);
       if ($role_element ne '') {
           my @allroles = ('st','ta','ep','in','ad');
           foreach my $crstype ('Course','Community') {
               if ($crstype eq 'Community') {
                   foreach my $role (@allroles) {
                       push(@communityrolenames,&Apache::lonnet::plaintext($role,$crstype));
                   }
                   push(@communityrolenames,&Apache::lonnet::plaintext('co'));
               } else {
                   foreach my $role (@allroles) {
                       push(@courserolenames,&Apache::lonnet::plaintext($role,$crstype));
                   }
                   push(@courserolenames,&Apache::lonnet::plaintext('cc'));
               }
           }
           $rolestr = '"'.join('","',@allroles).'"';
           $courserolestr = '"'.join('","',@courserolenames).'"';
           $communityrolestr = '"'.join('","',@communityrolenames).'"';
       }
     my $setsections = qq|      my $setsections = qq|
 function setSect(sectionlist) {  function setSect(sectionlist) {
     var sectionsArray = new Array();      var sectionsArray = new Array();
Line 683  function setSect(sectionlist) { Line 798  function setSect(sectionlist) {
         }          }
     }      }
 }  }
   
   function setRole(crstype) {
 |;  |;
       if ($role_element eq '') {
           $setsections .= '    return;
   }
   ';
       } else {
           $setsections .= qq|
       var elementLength = document.$formname.$role_element.length;
       var allroles = Array($rolestr);
       var courserolenames = Array($courserolestr);
       var communityrolenames = Array($communityrolestr);
       if (elementLength != undefined) {
           if (document.$formname.$role_element.options[5].value == 'cc') {
               if (crstype == 'Course') {
                   return;
               } else {
                   allroles[5] = 'co';
                   for (var i=0; i<6; i++) {
                       document.$formname.$role_element.options[i].value = allroles[i];
                       document.$formname.$role_element.options[i].text = communityrolenames[i];
                   }
               }
           } else {
               if (crstype == 'Community') {
                   return;
               } else {
                   allroles[5] = 'cc';
                   for (var i=0; i<6; i++) {
                       document.$formname.$role_element.options[i].value = allroles[i];
                       document.$formname.$role_element.options[i].text = courserolenames[i];
                   }
               }
           }
       }
       return;
   }
   |;
       }
     return $setsections;      return $setsections;
 }  }
   
   
 sub selectcourse_link {  sub selectcourse_link {
    my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype)=@_;     my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype,
          $typeelement) = @_;
      my $type = $selecttype;
    my $linktext = &mt('Select Course');     my $linktext = &mt('Select Course');
    if ($selecttype eq 'Community') {     if ($selecttype eq 'Community') {
        $linktext = &mt('Select Community');         $linktext = &mt('Select Community');
      } elsif ($selecttype eq 'Course/Community') {
          $linktext = &mt('Select Course/Community');
          $type = '';
      } elsif ($selecttype eq 'Select') {
          $linktext = &mt('Select');
          $type = '';
    }     }
    return '<span class="LC_nobreak">'     return '<span class="LC_nobreak">'
          ."<a href='"           ."<a href='"
          .'javascript:opencrsbrowser("'.$form.'","'.$unameele           .'javascript:opencrsbrowser("'.$form.'","'.$unameele
          .'","'.$udomele.'","'.$desc.'","'.$extra_element           .'","'.$udomele.'","'.$desc.'","'.$extra_element
          .'","'.$multflag.'","'.$selecttype.'");'           .'","'.$multflag.'","'.$type.'","'.$typeelement.'");'
          ."'>".$linktext.'</a>'           ."'>".$linktext.'</a>'
          .'</span>';           .'</span>';
 }  }
Line 711  sub selectauthor_link { Line 872  sub selectauthor_link {
   
 sub selectuser_link {  sub selectuser_link {
     my ($form,$unameelem,$domelem,$lastelem,$firstelem,$emailelem,$hdomelem,      my ($form,$unameelem,$domelem,$lastelem,$firstelem,$emailelem,$hdomelem,
         $coursedom,$linktext) = @_;          $coursedom,$linktext,$caller) = @_;
     return '<a href="javascript:openuserbrowser('."'$form','$unameelem','$domelem',".      return '<a href="javascript:openuserbrowser('."'$form','$unameelem','$domelem',".
            "'$lastelem','$firstelem','$emailelem','$hdomelem','$coursedom'".             "'$lastelem','$firstelem','$emailelem','$hdomelem','$coursedom','$caller'".
            ');">'.$linktext.'</a>';             ');">'.$linktext.'</a>';
 }  }
   
Line 827  sub select_language { Line 988  sub select_language {
             $langchoices{$code} = &plainlanguagedescription($id);              $langchoices{$code} = &plainlanguagedescription($id);
         }          }
     }      }
     return &select_form($selected,$name,%langchoices);      return &select_form($selected,$name,\%langchoices);
 }  }
   
 =pod  =pod
Line 999  END Line 1160  END
   
 =pod  =pod
   
 =item * &help_open_topic($topic,$text,$stayOnPage,$width,$height)  =item * &help_open_topic($topic,$text,$stayOnPage,$width,$height,$imgid)
   
 Returns a string corresponding to an HTML link to the given help  Returns a string corresponding to an HTML link to the given help
 $topic, where $topic corresponds to the name of a .tex file in  $topic, where $topic corresponds to the name of a .tex file in
Line 1017  a new window using Javascript. (Default Line 1178  a new window using Javascript. (Default
   
 $width and $height are optional numerical parameters that will  $width and $height are optional numerical parameters that will
 override the width and height of the popped up window, which may  override the width and height of the popped up window, which may
 be useful for certain help topics with big pictures included.   be useful for certain help topics with big pictures included.
   
   $imgid is the id of the img tag used for the help icon. This may be
   used in a javascript call to switch the image src.  See 
   lonhtmlcommon::htmlareaselectactive() for an example.
   
 =cut  =cut
   
 sub help_open_topic {  sub help_open_topic {
     my ($topic, $text, $stayOnPage, $width, $height) = @_;      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);
     if ($env{'browser.interface'} eq 'textual') {  
  $stayOnPage=1;  
     }  
     $width = 350 if (not defined $width);      $width = 350 if (not defined $width);
     $height = 400 if (not defined $height);      $height = 400 if (not defined $height);
     my $filename = $topic;      my $filename = $topic;
Line 1045  sub help_open_topic { Line 1207  sub help_open_topic {
     }      }
   
     # Add the text      # Add the text
     if ($text ne "") {      if ($text ne "") {
  $template .=    $template.='<span class="LC_help_open_topic">'
             "<table bgcolor='#3333AA' cellspacing='1' cellpadding='1' border='0'><tr>".                    .'<a target="_top" href="'.$link.'">'
             "<td bgcolor='#5555FF'><span class=\"LC_nobreak\"><a target=\"_top\" href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";                    .$text.'</a>';
     }      }
   
     # Add the graphic      # (Always) Add the graphic
     my $title = &mt('Online Help');      my $title = &mt('Online Help');
     my $helpicon=&lonhttpdurl("/adm/help/help.png");      my $helpicon=&lonhttpdurl("/adm/help/help.png");
     $template .= '<a target="_top" href="'.$link.'" title="'.$title.'">'.      if ($imgid ne '') {
                  '<img src="'.$helpicon.'" border="0" alt="'.&mt('Help: [_1]',$topic).          $imgid = ' id="'.$imgid.'"';
                  '" title="'.$title.'" /></a>';      }
     if ($text ne '') {      $template.=' <a target="_top" href="'.$link.'" title="'.$title.'">'
         $template.='</span></td></tr></table>';                .'<img src="'.$helpicon.'" border="0"'
                 .' alt="'.&mt('Help: [_1]',$topic).'"'
                 .' title="'.$title.'" style="vertical-align:middle;"'.$imgid 
                 .' /></a>';
       if ($text ne "") {
           $template.='</span>';
     }      }
     return $template;      return $template;
   
Line 1071  sub helpLatexCheatsheet { Line 1238  sub helpLatexCheatsheet {
     my $out;      my $out;
     my $addOther = '';      my $addOther = '';
     if ($topic) {      if ($topic) {
  $addOther = &Apache::loncommon::help_open_topic($topic,$text,   $addOther = '<span>'.&Apache::loncommon::help_open_topic($topic,&mt($text),
        undef, undef, 600) .         undef, undef, 600).
    '</td><td>';     '</span> ';
     }      }
     $out = '<table><tr><td>'.      $out = '<span>' # Start cheatsheet
            $addOther .    .$addOther
            &Apache::loncommon::help_open_topic("Greek_Symbols",&mt('Greek Symbols'),            .'<span>'
                                                undef,undef,600).    .&Apache::loncommon::help_open_topic('Greek_Symbols',&mt('Greek Symbols'),
            '</td><td>'.         undef,undef,600)
            &Apache::loncommon::help_open_topic("Other_Symbols",&mt('Other Symbols'),    .'</span> <span>'
                                                undef,undef,600).    .&Apache::loncommon::help_open_topic('Other_Symbols',&mt('Other Symbols'),
            '</td>';         undef,undef,600)
     .'</span>';
     unless ($not_author) {      unless ($not_author) {
         $out .= '<td>'.          $out .= ' <span>'
                 &Apache::loncommon::help_open_topic("Authoring_Output_Tags",&mt('Output Tags'),         .&Apache::loncommon::help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),
                                                     undef,undef,600).                                              undef,undef,600)
                 '</td>';         .'</span>';
     }      }
     $out .= '</tr></table>';      $out .= '</span>'; # End cheatsheet
     return $out;      return $out;
 }  }
   
Line 1097  sub general_help { Line 1265  sub general_help {
     my $helptopic='Student_Intro';      my $helptopic='Student_Intro';
     if ($env{'request.role'}=~/^(ca|au)/) {      if ($env{'request.role'}=~/^(ca|au)/) {
  $helptopic='Authoring_Intro';   $helptopic='Authoring_Intro';
     } elsif ($env{'request.role'}=~/^cc/) {      } elsif ($env{'request.role'}=~/^(cc|co)/) {
  $helptopic='Course_Coordination_Intro';   $helptopic='Course_Coordination_Intro';
     } elsif ($env{'request.role'}=~/^dc/) {      } elsif ($env{'request.role'}=~/^dc/) {
         $helptopic='Domain_Coordination_Intro';          $helptopic='Domain_Coordination_Intro';
Line 1129  ENDOUTPUT Line 1297  ENDOUTPUT
 sub help_open_menu {  sub help_open_menu {
     my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text)       my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text) 
  = @_;       = @_;    
     $stayOnPage = 0 if (not defined $stayOnPage);      $stayOnPage = 1;
     # only use pop-up help (stayOnPage == 0)  
     # if environment.remote is on (using remote control UI)  
     if ($env{'browser.interface'} eq 'textual' ||  
     $env{'environment.remote'} eq 'off' ) {  
         $stayOnPage=1;  
     }  
     my $output;      my $output;
     if ($component_help) {      if ($component_help) {
  if (!$text) {   if (!$text) {
Line 1156  sub help_open_menu { Line 1318  sub help_open_menu {
 sub top_nav_help {  sub top_nav_help {
     my ($text) = @_;      my ($text) = @_;
     $text = &mt($text);      $text = &mt($text);
     my $stay_on_page =       my $stay_on_page = 1;
  ($env{'browser.interface'}  eq 'textual' ||  
  $env{'environment.remote'} eq 'off' );  
     my $link = ($stay_on_page) ? "javascript:helpMenu('display')"      my $link = ($stay_on_page) ? "javascript:helpMenu('display')"
                      : "javascript:helpMenu('open')";                       : "javascript:helpMenu('open')";
     my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);      my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);
Line 1173  END Line 1334  END
   
 sub help_menu_js {  sub help_menu_js {
     my ($text) = @_;      my ($text) = @_;
       my $stayOnPage = 1;
     my $stayOnPage =   
  ($env{'browser.interface'}  eq 'textual' ||  
  $env{'environment.remote'} eq 'off' );  
   
     my $width = 620;      my $width = 620;
     my $height = 600;      my $height = 600;
     my $helptopic=&general_help();      my $helptopic=&general_help();
Line 1234  sub help_open_bug { Line 1391  sub help_open_bug {
     unless ($env{'user.adv'}) { return ''; }      unless ($env{'user.adv'}) { return ''; }
     unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; }      unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; }
     $text = "" if (not defined $text);      $text = "" if (not defined $text);
     $stayOnPage = 0 if (not defined $stayOnPage);  
     if ($env{'browser.interface'} eq 'textual' ||  
  $env{'environment.remote'} eq 'off' ) {  
  $stayOnPage=1;   $stayOnPage=1;
     }  
     $width = 600 if (not defined $width);      $width = 600 if (not defined $width);
     $height = 600 if (not defined $height);      $height = 600 if (not defined $height);
   
Line 1260  sub help_open_bug { Line 1413  sub help_open_bug {
     {      {
  $template .=    $template .= 
   "<table bgcolor='#AA3333' cellspacing='1' cellpadding='1' border='0'><tr>".    "<table bgcolor='#AA3333' cellspacing='1' cellpadding='1' border='0'><tr>".
   "<td bgcolor='#FF5555'><a target=\"_top\" href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";    "<td bgcolor='#FF5555'><a target=\"_top\" href=\"$link\"><span style=\"color:#FFFFFF;font-size:10pt;\">$text</span></a>";
     }      }
   
     # Add the graphic      # Add the graphic
Line 1279  sub help_open_faq { Line 1432  sub help_open_faq {
     unless ($env{'user.adv'}) { return ''; }      unless ($env{'user.adv'}) { return ''; }
     unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; }      unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; }
     $text = "" if (not defined $text);      $text = "" if (not defined $text);
     $stayOnPage = 0 if (not defined $stayOnPage);  
     if ($env{'browser.interface'} eq 'textual' ||  
  $env{'environment.remote'} eq 'off' ) {  
  $stayOnPage=1;   $stayOnPage=1;
     }  
     $width = 350 if (not defined $width);      $width = 350 if (not defined $width);
     $height = 400 if (not defined $height);      $height = 400 if (not defined $height);
   
Line 1305  sub help_open_faq { Line 1454  sub help_open_faq {
     {      {
  $template .=    $template .= 
   "<table bgcolor='#337733' cellspacing='1' cellpadding='1' border='0'><tr>".    "<table bgcolor='#337733' cellspacing='1' cellpadding='1' border='0'><tr>".
   "<td bgcolor='#448844'><a target=\"_top\" href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";    "<td bgcolor='#448844'><a target=\"_top\" href=\"$link\"><span style=\"color:#FFFFFF; font-size:10pt;\">$text</span></a>";
     }      }
   
     # Add the graphic      # Add the graphic
Line 1651  sub create_workbook { Line 1800  sub create_workbook {
     my $workbook  = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);      my $workbook  = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
     if (! defined($workbook)) {      if (! defined($workbook)) {
         $r->log_error("Error creating excel spreadsheet $filename: $!");          $r->log_error("Error creating excel spreadsheet $filename: $!");
         $r->print('<p>'.&mt("Unable to create new Excel file.  ".          $r->print(
                             "This error has been logged.  ".              '<p class="LC_error">'
                             "Please alert your LON-CAPA administrator").             .&mt('Problems occurred in creating the new Excel file.')
                   '</p>');             .' '.&mt('This error has been logged.')
              .' '.&mt('Please alert your LON-CAPA administrator.')
              .'</p>'
           );
         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 1694  sub create_text_file { Line 1846  sub create_text_file {
     $fh = Apache::File->new('>/home/httpd'.$filename);      $fh = Apache::File->new('>/home/httpd'.$filename);
     if (! defined($fh)) {      if (! defined($fh)) {
         $r->log_error("Couldn't open $filename for output $!");          $r->log_error("Couldn't open $filename for output $!");
         $r->print(&mt('Problems occurred in creating the output file. '          $r->print(
                      .'This error has been logged. '              '<p class="LC_error">'
                      .'Please alert your LON-CAPA administrator.'));             .&mt('Problems occurred in creating the output file.')
              .' '.&mt('This error has been logged.')
              .' '.&mt('Please alert your LON-CAPA administrator.')
              .'</p>'
           );
     }      }
     return ($fh,$filename)      return ($fh,$filename)
 }  }
Line 1725  sub domain_select { Line 1881  sub domain_select {
  return &multiple_select_form($name,$value,4,\%domains);   return &multiple_select_form($name,$value,4,\%domains);
     } else {      } else {
  $domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))];   $domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))];
  return &select_form($name,$value,%domains);   return &select_form($name,$value,\%domains);
     }      }
 }  }
   
Line 1787  sub multiple_select_form { Line 1943  sub multiple_select_form {
   
 =pod  =pod
   
 =item * &select_form($defdom,$name,%hash)  =item * &select_form($defdom,$name,$hashref,$onchange)
   
 Returns a string containing a <select name='$name' size='1'> form to   Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select options from a hash option_name => displayed text.    allow a user to select options from a ref to a hash containing:
   option_name => displayed text. An optional $onchange can include
   a javascript onchange item, e.g., onchange="this.form.submit();"  
   
 See lonrights.pm for an example invocation and use.  See lonrights.pm for an example invocation and use.
   
 =cut  =cut
   
 #-------------------------------------------  #-------------------------------------------
 sub select_form {  sub select_form {
     my ($def,$name,%hash) = @_;      my ($def,$name,$hashref,$onchange) = @_;
     my $selectform = "<select name=\"$name\" size=\"1\">\n";      return unless (ref($hashref) eq 'HASH');
       if ($onchange) {
           $onchange = ' onchange="'.$onchange.'"';
       }
       my $selectform = "<select name=\"$name\" size=\"1\"$onchange>\n";
     my @keys;      my @keys;
     if (exists($hash{'select_form_order'})) {      if (exists($hashref->{'select_form_order'})) {
  @keys=@{$hash{'select_form_order'}};   @keys=@{$hashref->{'select_form_order'}};
     } else {      } else {
  @keys=sort(keys(%hash));   @keys=sort(keys(%{$hashref}));
     }      }
     foreach my $key (@keys) {      foreach my $key (@keys) {
         $selectform.=          $selectform.=
     '<option value="'.&HTML::Entities::encode($key,'"<>&').'" '.      '<option value="'.&HTML::Entities::encode($key,'"<>&').'" '.
             ($key eq $def ? 'selected="selected" ' : '').              ($key eq $def ? 'selected="selected" ' : '').
                 ">".&mt($hash{$key})."</option>\n";                  ">".$hashref->{$key}."</option>\n";
     }      }
     $selectform.="</select>";      $selectform.="</select>";
     return $selectform;      return $selectform;
Line 1827  sub display_filter { Line 1990  sub display_filter {
            &mt('Filter [_1]',             &mt('Filter [_1]',
    &select_form($env{'form.displayfilter'},     &select_form($env{'form.displayfilter'},
  'displayfilter',   'displayfilter',
  ('currentfolder' => 'Current folder/page',   {'currentfolder' => 'Current folder/page',
  'containing' => 'Containing phrase',   'containing' => 'Containing phrase',
  'none' => 'None'))).   'none' => 'None'})).
  '<input type="text" name="containingphrase" size="30" value="'.&HTML::Entities::encode($env{'form.containingphrase'}).'" /></span>';   '<input type="text" name="containingphrase" size="30" value="'.&HTML::Entities::encode($env{'form.containingphrase'}).'" /></span>';
 }  }
   
Line 1874  sub select_level_form { Line 2037  sub select_level_form {
   
 =pod  =pod
   
 =item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange)  =item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms)
   
 Returns a string containing a <select name='$name' size='1'> form to   Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select the domain to preform an operation in.    allow a user to select the domain to preform an operation in.  
Line 1887  If the $showdomdesc flag is set, the dom Line 2050  If the $showdomdesc flag is set, the dom
   
 The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.  The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.
   
   The optional $incdoms is a reference to an array of domains which will be the only available options. 
   
 =cut  =cut
   
 #-------------------------------------------  #-------------------------------------------
 sub select_dom_form {  sub select_dom_form {
     my ($defdom,$name,$includeempty,$showdomdesc,$onchange) = @_;      my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) = @_;
     if ($onchange) {      if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';          $onchange = ' onchange="'.$onchange.'"';
     }      }
     my @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());      my @domains;
       if (ref($incdoms) eq 'ARRAY') {
           @domains = sort {lc($a) cmp lc($b)} (@{$incdoms});
       } else {
           @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
       }
     if ($includeempty) { @domains=('',@domains); }      if ($includeempty) { @domains=('',@domains); }
     my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange>\n";      my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange>\n";
     foreach my $dom (@domains) {      foreach my $dom (@domains) {
Line 2192  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 2911  sub screenname { Line 3085  sub screenname {
     return $names{'screenname'};      return $names{'screenname'};
 }  }
   
   
 # ------------------------------------------------------------- Confirm Wrapper  # ------------------------------------------------------------- Confirm Wrapper
 =pod  =pod
   
Line 2941  sub messagewrapper { Line 3116  sub messagewrapper {
  '&amp;subject='.&escape($subject).'&amp;text='.&escape($text).'" '.   '&amp;subject='.&escape($subject).'&amp;text='.&escape($text).'" '.
         'title="'.&mt('Send message').'">'.$link.'</a>';          'title="'.&mt('Send message').'">'.$link.'</a>';
 }  }
   
 # --------------------------------------------------------------- Notes Wrapper  # --------------------------------------------------------------- Notes Wrapper
   
 sub noteswrapper {  sub noteswrapper {
     my ($link,$un,$do)=@_;      my ($link,$un,$do)=@_;
     return       return 
 "<a href='/adm/email?recordftf=retrieve&recname=$un&recdom=$do'>$link</a>";  "<a href='/adm/email?recordftf=retrieve&amp;recname=$un&amp;recdom=$do'>$link</a>";
 }  }
   
 # ------------------------------------------------------------- Aboutme Wrapper  # ------------------------------------------------------------- Aboutme Wrapper
   
 sub aboutmewrapper {  sub aboutmewrapper {
Line 2955  sub aboutmewrapper { Line 3132  sub aboutmewrapper {
     if (!defined($username)  && !defined($domain)) {      if (!defined($username)  && !defined($domain)) {
         return;          return;
     }      }
     return '<a href="/adm/'.$domain.'/'.$username.'/aboutme"'.      return '<a href="/adm/'.$domain.'/'.$username.'/aboutme?forcestudent=1"'.
  ($target?' target="$target"':'').' title="'.&mt("View this user's personal information page").'">'.$link.'</a>';   ($target?' target="$target"':'').' title="'.&mt("View this user's personal information page").'">'.$link.'</a>';
 }  }
   
 # ------------------------------------------------------------ Syllabus Wrapper  # ------------------------------------------------------------ Syllabus Wrapper
   
   
 sub syllabuswrapper {  sub syllabuswrapper {
     my ($linktext,$coursedir,$domain,$fontcolor)=@_;      my ($linktext,$coursedir,$domain)=@_;
     if ($fontcolor) {   
         $linktext='<font color="'.$fontcolor.'">'.$linktext.'</font>';   
     }  
     return qq{<a href="/public/$domain/$coursedir/syllabus">$linktext</a>};      return qq{<a href="/public/$domain/$coursedir/syllabus">$linktext</a>};
 }  }
   
   # -----------------------------------------------------------------------------
   
 sub track_student_link {  sub track_student_link {
     my ($linktext,$sname,$sdom,$target,$start) = @_;      my ($linktext,$sname,$sdom,$target,$start,$only_body) = @_;
     my $link ="/adm/trackstudent?";      my $link ="/adm/trackstudent?";
     my $title = 'View recent activity';      my $title = 'View recent activity';
     if (defined($sname) && $sname !~ /^\s*$/ &&      if (defined($sname) && $sname !~ /^\s*$/ &&
Line 2985  sub track_student_link { Line 3160  sub track_student_link {
         $target = '';          $target = '';
     }      }
     if ($start) { $link.='&amp;start='.$start; }      if ($start) { $link.='&amp;start='.$start; }
       if ($only_body) { $link .= '&amp;only_body=1'; }
     $title = &mt($title);      $title = &mt($title);
     $linktext = &mt($linktext);      $linktext = &mt($linktext);
     return qq{<a href="$link" title="$title" $target>$linktext</a>}.      return qq{<a href="$link" title="$title" $target>$linktext</a>}.
Line 3058  sub languagedescription { Line 3234  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 3070  sub supportedlanguagecode { Line 3264  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 * &copyrightids()   =item * &copyrightids() 
   
 returns list of all copyrights  returns list of all copyrights
Line 3162  sub filemimetype { Line 3371  sub filemimetype {
 sub filecategoryselect {  sub filecategoryselect {
     my ($name,$value)=@_;      my ($name,$value)=@_;
     return &select_form($value,$name,      return &select_form($value,$name,
  '' => &mt('Any category'),                          {'' => &mt('Any category'), map { $_,$_ } sort(keys(%category_extensions))});
  map { $_,$_ } sort(keys(%category_extensions)));  
 }  }
   
 =pod  =pod
Line 3271  sub user_lang { Line 3479  sub user_lang {
     return $user_lh;      return $user_lh;
 }  }
   
   
 ###############################################################  ###############################################################
 ##               Student Answer Attempts                     ##  ##               Student Answer Attempts                     ##
 ###############################################################  ###############################################################
Line 3327  sub get_previous_attempt { Line 3536  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,%lasthidden);
         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>';            $prevattempts.='<th>'.&mt('Part ').join('.',@parts).'<br />'.$data.'&nbsp;</th>';
             if ($data eq 'type') {
                 unless ($showsurv) {
                     my $id = join(',',@parts);
                     $typeparts{$ign.'.'.$id} = $lasthash{$key};
                     if (($lasthash{$key} eq 'anonsurvey') || ($lasthash{$key} eq 'anonsurveycred')) {
                         $lasthidden{$ign.'.'.$id} = 1;
                     }
                 }
             } 
  } else {   } else {
   if ($#parts == 0) {    if ($#parts == 0) {
     $prevattempts.='<th>'.$parts[0].'</th>';      $prevattempts.='<th>'.$parts[0].'</th>';
Line 3344  sub get_previous_attempt { Line 3565  sub get_previous_attempt {
       $prevattempts.=&end_data_table_header_row();        $prevattempts.=&end_data_table_header_row();
       if ($getattempt eq '') {        if ($getattempt eq '') {
  for ($version=1;$version<=$returnhash{'version'};$version++) {   for ($version=1;$version<=$returnhash{'version'};$version++) {
   $prevattempts.=&start_data_table_row().              my @hidden;
       '<td>'.&mt('Transaction [_1]',$version).'</td>';              if (%typeparts) {
     foreach my $key (sort(keys(%lasthash))) {                  foreach my $id (keys(%typeparts)) {
  my $value = &format_previous_attempt_value($key,                      if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') || ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {
    $returnhash{$version.':'.$key});                          push(@hidden,$id);
  $prevattempts.='<td>'.$value.'&nbsp;</td>';                         }
     }                  }
   $prevattempts.=&end_data_table_row();              }
               $prevattempts.=&start_data_table_row().
                              '<td>'.&mt('Transaction [_1]',$version).'</td>';
               if (@hidden) {
                   foreach my $key (sort(keys(%lasthash))) {
                       next if ($key =~ /\.foilorder$/);
                       my $hide;
                       foreach my $id (@hidden) {
                           if ($key =~ /^\Q$id\E/) {
                               $hide = 1;
                               last;
                           }
                       }
                       if ($hide) {
                           my ($id,$data) = ($key =~ /^(.+)\.([^.]+)$/);
                           if (($data eq 'award') || ($data eq 'awarddetail')) {
                               my $value = &format_previous_attempt_value($key,
                                                $returnhash{$version.':'.$key});
                               $prevattempts.='<td>'.$value.'&nbsp;</td>';
                           } else {
                               $prevattempts.='<td>&nbsp;</td>';
                           }
                       } else {
                           if ($key =~ /\./) {
                               my $value = &format_previous_attempt_value($key,
                                                 $returnhash{$version.':'.$key});
                               $prevattempts.='<td>'.$value.'&nbsp;</td>';
                           } else {
                               $prevattempts.='<td>&nbsp;</td>';
                           }
                       }
                   }
               } else {
           foreach my $key (sort(keys(%lasthash))) {
                       next if ($key =~ /\.foilorder$/);
       my $value = &format_previous_attempt_value($key,
               $returnhash{$version.':'.$key});
       $prevattempts.='<td>'.$value.'&nbsp;</td>';
           }
               }
       $prevattempts.=&end_data_table_row();
  }   }
       }        }
         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))) {
  my $value = &format_previous_attempt_value($key,$lasthash{$key});            next if ($key =~ /\.foilorder$/);
  if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}            if (%typeparts) {
  $prevattempts.='<td>'.$value.'&nbsp;</td>';                my $hidden;
                 foreach my $id (@currhidden) {
                     if ($key =~ /^\Q$id\E/) {
                         $hidden = 1;
                         last;
                     }
                 }
                 if ($hidden) {
                     my ($id,$data) = ($key =~ /^(.+)\.([^.]+)$/);
                     if (($data eq 'award') || ($data eq 'awarddetail')) {
                         my $value = &format_previous_attempt_value($key,$lasthash{$key});
                         if ($key =~/$regexp$/ && (defined &$gradesub)) {
                             $value = &$gradesub($value);
                         }
                         $prevattempts.='<td>'.$value.'&nbsp;</td>';
                     } else {
                         $prevattempts.='<td>&nbsp;</td>';
                     }
                 } else {
                     my $value = &format_previous_attempt_value($key,$lasthash{$key});
                     if ($key =~/$regexp$/ && (defined &$gradesub)) {
                         $value = &$gradesub($value);
                     }
                     $prevattempts.='<td>'.$value.'&nbsp;</td>';
                 }
             } else {
         my $value = &format_previous_attempt_value($key,$lasthash{$key});
         if ($key =~/$regexp$/ && (defined &$gradesub)) {
                     $value = &$gradesub($value);
                 }
         $prevattempts.='<td>'.$value.'&nbsp;</td>';
             }
       }        }
       $prevattempts.= &end_data_table_row().&end_data_table();        $prevattempts.= &end_data_table_row().&end_data_table();
     } else {      } else {
Line 3377  sub get_previous_attempt { Line 3670  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 3531  sub submlink { Line 3847  sub submlink {
     }      }
     if (!$symb) { $symb=&Apache::lonnet::symbread(); }      if (!$symb) { $symb=&Apache::lonnet::symbread(); }
     $symb=&escape($symb);      $symb=&escape($symb);
     if ($target) { $target="target=\"$target\""; }      if ($target) { $target=" target=\"$target\""; }
     return '<a href="/adm/grades?&command=submission&'.      return
  'symb='.$symb.'&student='.$uname.          '<a href="/adm/grades?command=submission'.
  '&userdom='.$udom.'" '.$target.'>'.$text.'</a>';          '&amp;symb='.$symb.
           '&amp;student='.$uname.
           '&amp;userdom='.$udom.'"'.
           $target.'>'.$text.'</a>';
 }  }
 ##############################################  ##############################################
   
Line 3656  sub findallcourses { Line 3975  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,
                          co => 1,
                        in => 1,                         in => 1,
                        ep => 1,                         ep => 1,
                        ta => 1,                         ta => 1,
Line 3850  sub blockcheck { Line 4172  sub blockcheck {
                  ($env{'request.role'} !~ m{^st\./\Q$cdom\E/\Q$cnum\E}));                   ($env{'request.role'} !~ m{^st\./\Q$cdom\E/\Q$cnum\E}));
         next if ($no_userblock);          next if ($no_userblock);
   
         # Retrieve blocking times and identity of blocker for course          # Retrieve blocking times and identity of locker for course
         # of specified user, unless user has 'evb' privilege.          # of specified user, unless user has 'evb' privilege.
                   
         my ($start,$end)=&get_blocks($setters,$activity,$cdom,$cnum);          my ($start,$end)=&get_blocks($setters,$activity,$cdom,$cnum);
Line 3915  sub parse_block_record { Line 4237  sub parse_block_record {
     return ($setuname,$setudom,$title,$blocks);      return ($setuname,$setudom,$title,$blocks);
 }  }
   
 sub build_block_table {  
     my ($startblock,$endblock,$setters) = @_;  
     my %lt = &Apache::lonlocal::texthash(  
         'cacb' => 'Currently active communication blocks',  
         'cour' => 'Course',  
         'dura' => 'Duration',  
         'blse' => 'Block set by'  
     );  
     my $output;  
     $output = '<br />'.$lt{'cacb'}.':<br />';  
     $output .= &start_data_table();  
     $output .= '  
 <tr>  
  <th>'.$lt{'cour'}.'</th>  
  <th>'.$lt{'dura'}.'</th>  
  <th>'.$lt{'blse'}.'</th>  
 </tr>  
 ';  
     foreach my $course (keys(%{$setters})) {  
         my %courseinfo=&Apache::lonnet::coursedescription($course);  
         for (my $i=0; $i<@{$$setters{$course}{staff}}; $i++) {  
             my ($uname,$udom) = @{$$setters{$course}{staff}[$i]};  
             my $fullname = &plainname($uname,$udom);  
             if (defined($env{'user.name'}) && defined($env{'user.domain'})  
                 && $env{'user.name'} ne 'public'   
                 && $env{'user.domain'} ne 'public') {  
                 $fullname = &aboutmewrapper($fullname,$uname,$udom);  
             }  
             my ($openblock,$closeblock) = @{$$setters{$course}{times}[$i]};  
             $openblock = &Apache::lonlocal::locallocaltime($openblock);  
             $closeblock= &Apache::lonlocal::locallocaltime($closeblock);  
             $output .= &Apache::loncommon::start_data_table_row().  
                        '<td>'.$courseinfo{'description'}.'</td>'.  
                        '<td>'.$openblock.' to '.$closeblock.'</td>'.  
                        '<td>'.$fullname.'</td>'.  
                         &Apache::loncommon::end_data_table_row();  
         }  
     }  
     $output .= &end_data_table();  
 }  
   
 sub blocking_status {  sub blocking_status {
     my ($activity,$uname,$udom) = @_;    my ($activity,$uname,$udom) = @_;
     my %setters;    my %setters;
     my ($blocked,$output,$ownitem,$is_course);  
     my ($startblock,$endblock)=&blockcheck(\%setters,$activity,$uname,$udom);    # check for active blocking
     if ($startblock && $endblock) {    my ($startblock,$endblock)=&blockcheck(\%setters,$activity,$uname,$udom);
         $blocked = 1;  
         if (wantarray) {    my $blocked = $startblock && $endblock ? 1 : 0;
             my $category;  
             if ($activity eq 'boards') {    # caller just wants to know whether a block is active
                 $category = 'Discussion posts in this course';    if (!wantarray) { return $blocked; }
             } elsif ($activity eq 'blogs') {  
                 $category = 'Blogs';    # build a link to a popup window containing the details
             } elsif ($activity eq 'port') {    my $querystring  = "?activity=$activity";
                 if (defined($uname) && defined($udom)) {    # $uname and $udom decide whose portfolio the user is trying to look at
                     if ($uname eq $env{'user.name'} &&       $querystring .= "&amp;udom=$udom"      if $udom;
                         $udom eq $env{'user.domain'}) {       $querystring .= "&amp;uname=$uname"    if $uname;
                         $ownitem = 1;  
                     }    my $output .= <<'END_MYBLOCK';
                 }      function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                 $is_course = &Apache::lonnet::is_course($udom,$uname);          var options = "width=" + w + ",height=" + h + ",";
                 if ($ownitem) {           options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                     $category = 'Your portfolio files';            options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                 } elsif ($is_course) {          var newWin = window.open(url, wdwName, options);
                     my $coursedesc;          newWin.focus();
                     foreach my $course (keys(%setters)) {      }
                         my %courseinfo =  END_MYBLOCK
                              &Apache::lonnet::coursedescription($course);  
                         $coursedesc = $courseinfo{'description'};    $output = Apache::lonhtmlcommon::scripttag($output);
                     }    
                     $category = "Group portfolio files in the course '$coursedesc'";    my $popupUrl = "/adm/blockingstatus/$querystring";
                 } else {    my $text = mt('Communication Blocked');
                     $category = 'Portfolio files belonging to ';  
                     if ($env{'user.name'} eq 'public' &&     $output .= <<"END_BLOCK";
                         $env{'user.domain'} eq 'public') {  <div class='LC_comblock'>
                         $category .= &plainname($uname,$udom);    <a onclick='openWindow("$popupUrl","Blocking Table",600,300,"no","no");return false;' href='/adm/blockingstatus/$querystring'
                     } else {    title='$text'>
                         $category .= &aboutmewrapper(&plainname($uname,$udom),$uname,$udom);      <img class='LC_noBorder LC_middle' title='$text' src='/res/adm/pages/comblock.png' alt='$text'/></a>
                     }    <a onclick='openWindow("$popupUrl","Blocking Table",600,300,"no","no");return false;' href='/adm/blockingstatus/$querystring' 
                 }    title='$text'>$text</a>
             } elsif ($activity eq 'groups') {  </div>
                 $category = 'Groups in this course';  
             }  END_BLOCK
             my $showstart = &Apache::lonlocal::locallocaltime($startblock);  
             my $showend = &Apache::lonlocal::locallocaltime($endblock);    return ($blocked, $output);
             $output = '<br />'.&mt('[_1] will be inaccessible between [_2] and [_3] because communication is being blocked.',$category,$showstart,$showend).'<br />';  
             if (!($activity eq 'port' && !($ownitem) && !($is_course))) {   
                 $output .= &build_block_table($startblock,$endblock,\%setters);  
             }  
         }  
     }  
     if (wantarray) {  
         return ($blocked,$output);  
     } else {  
         return $blocked;  
     }  
 }  }
   
 ###############################################  ###############################################
Line 4089  sub determinedomain { Line 4359  sub determinedomain {
     my $domain=shift;      my $domain=shift;
     if (! $domain) {      if (! $domain) {
         # Determine domain if we have not been given one          # Determine domain if we have not been given one
         $domain = $Apache::lonnet::perlvar{'lonDefDomain'};          $domain = &Apache::lonnet::default_login_domain();
         if ($env{'user.domain'}) { $domain=$env{'user.domain'}; }          if ($env{'user.domain'}) { $domain=$env{'user.domain'}; }
         if ($env{'request.role.domain'}) {           if ($env{'request.role.domain'}) { 
             $domain=$env{'request.role.domain'};               $domain=$env{'request.role.domain'}; 
Line 4112  sub get_domainconf { Line 4382  sub get_domainconf {
     if (defined($cached)) { return %{$result}; }      if (defined($cached)) { return %{$result}; }
   
     my %domconfig = &Apache::lonnet::get_dom('configuration',      my %domconfig = &Apache::lonnet::get_dom('configuration',
      ['login','rolecolors'],$udom);       ['login','rolecolors','autoenroll'],$udom);
     my (%designhash,%legacy);      my (%designhash,%legacy);
     if (keys(%domconfig) > 0) {      if (keys(%domconfig) > 0) {
         if (ref($domconfig{'login'}) eq 'HASH') {          if (ref($domconfig{'login'}) eq 'HASH') {
             if (keys(%{$domconfig{'login'}})) {              if (keys(%{$domconfig{'login'}})) {
                 foreach my $key (keys(%{$domconfig{'login'}})) {                  foreach my $key (keys(%{$domconfig{'login'}})) {
                     if (ref($domconfig{'login'}{$key}) eq 'HASH') {                      if (ref($domconfig{'login'}{$key}) eq 'HASH') {
                         foreach my $img (keys(%{$domconfig{'login'}{$key}})) {                          if ($key eq 'loginvia') {
                             $designhash{$udom.'.login.'.$key.'_'.$img} =                              if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') {
                                 $domconfig{'login'}{$key}{$img};                                  foreach my $hostname (keys(%{$domconfig{'login'}{'loginvia'}})) {
                                       if (ref($domconfig{'login'}{'loginvia'}{$hostname}) eq 'HASH') {
                                           if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {
                                               my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};
                                               $designhash{$udom.'.login.loginvia'} = $server;
                                               if ($domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'} eq 'custom') {
   
                                                   $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};
                                               } else {
                                                   $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};
                                               }
                                               if ($domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}) {
                                                   $designhash{$udom.'.login.loginvia_exempt_'.$hostname} = $domconfig{'login'}{'loginvia'}{$hostname}{'exempt'};
                                               }
                                           }
                                       }
                                   }
                               }
                           } else {
                               foreach my $img (keys(%{$domconfig{'login'}{$key}})) {
                                   $designhash{$udom.'.login.'.$key.'_'.$img} = 
                                       $domconfig{'login'}{$key}{$img};
                               }
                         }                          }
                     } else {                      } else {
                         $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};                          $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};
Line 4148  sub get_domainconf { Line 4440  sub get_domainconf {
         } else {          } else {
             $legacy{'rolecolors'} = 1;              $legacy{'rolecolors'} = 1;
         }          }
           if (ref($domconfig{'autoenroll'}) eq 'HASH') {
               if ($domconfig{'autoenroll'}{'co-owners'}) {
                   $designhash{$udom.'.autoassign.co-owners'}=$domconfig{'autoenroll'}{'co-owners'};
               }
           }
         if (keys(%legacy) > 0) {          if (keys(%legacy) > 0) {
             my %legacyhash = &get_legacy_domconf($udom);              my %legacyhash = &get_legacy_domconf($udom);
             foreach my $item (keys(%legacyhash)) {              foreach my $item (keys(%legacyhash)) {
Line 4186  sub get_legacy_domconf { Line 4483  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 4240  Returns: value of designparamter $which Line 4537  Returns: value of designparamter $which
 ##############################################  ##############################################
 sub designparm {  sub designparm {
     my ($which,$domain)=@_;      my ($which,$domain)=@_;
     if ($env{'browser.blackwhite'} eq 'on') {  
  if ($which=~/\.(font|alink|vlink|link|textcol)$/) {  
     return '#000000';  
  }  
  if ($which=~/\.(pgbg|sidebg|bgcol)$/) {  
     return '#FFFFFF';  
  }  
  if ($which=~/\.tabbg$/) {  
     return '#CCCCCC';  
  }  
     }  
     if (exists($env{'environment.color.'.$which})) {      if (exists($env{'environment.color.'.$which})) {
  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};
     } else {      } else {
         $output = $defaultdesign{$which};          $output = $defaultdesign{$which};
     }      }
     if (($which =~ /^(student|coordinator|author|admin)\.img$/) ||      if (($which =~ /^(student|coordinator|author|admin)\.img$/) ||
         ($which =~ /login\.(img|logo|domlogo|login)/)) {          ($which =~ /login\.(img|logo|domlogo|login)/)) {
         if ($output =~ m{^/(adm|res)/}) {          if ($output =~ m{^/(adm|res)/}) {
     if ($output =~ m{^/res/}) {              if ($output =~ m{^/res/}) {
  my $local_name = &Apache::lonnet::filelocation('',$output);                  my $local_name = &Apache::lonnet::filelocation('',$output);
  &Apache::lonnet::repcopy($local_name);                  &Apache::lonnet::repcopy($local_name);
     }              }
             $output = &lonhttpdurl($output);              $output = &lonhttpdurl($output);
         }          }
     }      }
     return $output;      return $output;
 }  }
   
   ##############################################
   =pod
   
   =item * &authorspace()
   
   Inputs: $url (usually will be undef).
   
   Returns: Path to Construction Space containing the resource or 
            directory being viewed (or for which action is being taken). 
            If $url is provided, and begins /priv/<domain>/<uname>
            the path will be that portion of the $context argument.
            Otherwise the path will be for the author space of the current
            user when the current role is author, or for that of the 
            co-author/assistant co-author space when the current role 
            is co-author or assistant co-author.
   
   =cut
   
   sub authorspace {
       my ($url) = @_;
       if ($url ne '') {
           if ($url =~ m{^(/priv/$match_domain/$match_username/)}) {
              return $1;
           }
       }
       my $caname = '';
       my $cadom = '';
       if ($env{'request.role'} =~ /^(?:ca|aa)/) {
           ($cadom,$caname) =
               ($env{'request.role'}=~/($match_domain)\/($match_username)$/);
       } elsif ($env{'request.role'} =~ m{^au\./($match_domain)/}) {
           $caname = $env{'user.name'};
           $cadom = $env{'user.domain'};
       }
       if (($caname ne '') && ($cadom ne '')) {
           return "/priv/$cadom/$caname/";
       }
       return;
   }
   
   ##############################################
   =pod
   
   =item * &head_subbox()
   
   Inputs: $content (contains HTML code with page functions, etc.)
   
   Returns: HTML div with $content
            To be included in page header
   
   =cut
   
   sub head_subbox {
       my ($content)=@_;
       my $output =
           '<div class="LC_head_subbox">'
          .$content
          .'</div>'
   }
   
   ##############################################
   =pod
   
   =item * &CSTR_pageheader()
   
   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
            To be included on Construction Space pages
   
   =cut
   
   sub CSTR_pageheader {
       my ($trailfile) = @_;
       if ($trailfile eq '') {
           $trailfile = $env{'request.filename'};
       }
   
   # 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 $lastitem = '';
       if ($thisdisfn =~ m-(.+/)([^/]*)$-) {
           $parentpath = $1;
           $lastitem = $2;
       } else {
           $lastitem = $thisdisfn;
       }
   
       my $output =
            '<div>'
           .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?
           .'<b>'.&mt('Construction Space:').'</b> '
           .'<form name="dirs" method="post" action="'.$formaction
           .'" target="_top">' #FIXME lonpubdir: target="_parent"
           .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv/'.$udom,undef,undef);
   
       if ($lastitem) {
           $output .=
                '<span class="LC_filename">'
               .$lastitem
               .'</span>';
       }
       $output .=
            '<br />'
           #FIXME lonpubdir: &Apache::lonhtmlcommon::crumbs($uname.$thisdisfn.'/','_top','/priv','','+1',1)."</b></tt><br />"
           .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()')
           .'</form>'
           .&Apache::lonmenu::constspaceform()
           .'</div>';
   
       return $output;
   }
   
 ###############################################  ###############################################
 ###############################################  ###############################################
   
Line 4307  Inputs: Line 4719  Inputs:
 =item * $forcereg, if page should register as content page (relevant for   =item * $forcereg, if page should register as content page (relevant for 
             text interface only)              text interface only)
   
 =item * $customtitle, alternate text to use instead of $title  =item * $no_nav_bar, if true, keep the 'what is this' info but remove the
                       in the title box that appears, this text                       navigational links
                       is not auto translated like the $title is  
   
 =item * $notopbar, if true, keep the 'what is this' info but remove the  
                    navigational links  
   
 =item * $bgcolor, used to override the bgcolor on a webpage to a specific value  =item * $bgcolor, used to override the bgcolor on a webpage to a specific value
   
 =item * $notitle, if true keep the nav controls, but remove the title bar  
   
 =item * $no_inline_link, if true and in remote mode, don't show the   
          'Switch To Inline Menu' link  
   
 =item * $args, optional argument valid values are  =item * $args, optional argument valid values are
             no_auto_mt_title -> prevents &mt()ing the title arg              no_auto_mt_title -> prevents &mt()ing the title arg
             inherit_jsmath -> when creating popup window in a page,              inherit_jsmath -> when creating popup window in a page,
Line 4337  other decorations will be returned. Line 4740  other decorations will be returned.
 =cut  =cut
   
 sub bodytag {  sub bodytag {
     my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,$customtitle,      my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,
  $notopbar,$bgcolor,$notitle,$no_inline_link,$args)=@_;          $no_nav_bar,$bgcolor,$args)=@_;
   
       my $public;
       if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
           || ($env{'user.name'} eq '') && ($env{'user.domain'} eq '')) {
           $public = 1;
       }
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }      if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
   
     $function = &get_users_function() if (!$function);      $function = &get_users_function() if (!$function);
Line 4366  sub bodytag { Line 4774  sub bodytag {
         if ($env{'request.role'} !~ /^cr/) {          if ($env{'request.role'} !~ /^cr/) {
             $role = &Apache::lonnet::plaintext($role,&course_type());              $role = &Apache::lonnet::plaintext($role,&course_type());
         }          }
           if ($env{'request.course.sec'}) {
               $role .= ('&nbsp;'x2).'-&nbsp;'.&mt('section:').'&nbsp;'.$env{'request.course.sec'};
           }   
  $realm = $env{'course.'.$env{'request.course.id'}.'.description'};   $realm = $env{'course.'.$env{'request.course.id'}.'.description'};
     } else {      } else {
         $role = &Apache::lonnet::plaintext($role);          $role = &Apache::lonnet::plaintext($role);
     }      }
   
     if (!$realm) { $realm='&nbsp;'; }      if (!$realm) { $realm='&nbsp;'; }
 # Set messages  
     my $messages=&domainlogo($domain);  
   
     my $extra_body_attr = &make_attr_string($forcereg,\%design);      my $extra_body_attr = &make_attr_string($forcereg,\%design);
   
Line 4383  sub bodytag { Line 4792  sub bodytag {
   
     if ($bodyonly) {      if ($bodyonly) {
         return $bodytag;          return $bodytag;
     } elsif ($env{'browser.interface'} eq 'textual') {      } 
 # Accessibility  
             
  $bodytag.=&Apache::lonmenu::menubuttons($forcereg,$forcereg);  
  if (!$notitle) {  
     $bodytag.='<h1>LON-CAPA: '.$title.'</h1>';  
  }  
  return $bodytag;  
     }  
   
     my $name = &plainname($env{'user.name'},$env{'user.domain'});      my $name = &plainname($env{'user.name'},$env{'user.domain'});
     if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {      if ($public) {
  undef($role);   undef($role);
     } else {      } else {
  $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});   $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});
     }      }
           
     my $roleinfo=(<<ENDROLE);      my $titleinfo = '<h1>'.$title.'</h1>';
 <td class="LC_title_bar_who">  
 <div class="LC_title_bar_name">  
     $name  
     &nbsp;  
 </div>  
 <div class="LC_title_bar_role">  
 $role&nbsp;  
 </div>  
 <div class="LC_title_bar_realm">  
 $realm&nbsp;  
 </div>  
 </td>  
 ENDROLE  
   
     my $titleinfo = '<span class="LC_title_bar_title">'.$title.'</span>';  
     if ($customtitle) {  
         $titleinfo = $customtitle;  
     }  
     #      #
     # Extra info if you are the DC      # Extra info if you are the DC
     my $dc_info = '';      my $dc_info = '';
Line 4426  ENDROLE Line 4809  ENDROLE
                         $env{'course.'.$env{'request.course.id'}.                          $env{'course.'.$env{'request.course.id'}.
                                  '.domain'}.'/'})) {                                   '.domain'}.'/'})) {
         my $cid = $env{'request.course.id'};          my $cid = $env{'request.course.id'};
         $dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};          $dc_info = $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
         $dc_info =~ s/\s+$//;          $dc_info =~ s/\s+$//;
         $dc_info = '('.$dc_info.')';  
     }      }
   
     if (($env{'environment.remote'} eq 'off') || ($args->{'suppress_header_logos'})) {      $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;
         # No Remote      &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
  if ($env{'request.state'} eq 'construct') {  
     $forcereg=1;  
  }  
   
  if (!$customtitle && $env{'request.state'} eq 'construct') {          if ($no_nav_bar || $env{'form.inhibitmenu'} eq 'yes') { 
     # this is for resources; directories have customtitle, and crumbs              return $bodytag; 
             # and select recent are created in lonpubdir.pm            } 
     my ($uname,$thisdisfn)=  
  ($env{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|);          if ($env{'request.state'} eq 'construct') { $forcereg=1; }
     my $formaction='/priv/'.$uname.'/'.$thisdisfn;  
     $formaction=~s/\/+/\//g;          #    if ($env{'request.state'} eq 'construct') {
           #        $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls
     my $parentpath = '';          #    }
     my $lastitem = '';  
     if ($thisdisfn =~ m-(.+/)([^/]*)$-) {  
  $parentpath = $1;  
  $lastitem = $2;          if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
     } else {               if ($dc_info) {
  $lastitem = $thisdisfn;                   $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;
     }               }
     $titleinfo =                $bodytag .= qq|<div id="LC_nav_bar">$name $role<br />
  &Apache::loncommon::help_open_menu('','',3,'Authoring')                  <em>$realm</em> $dc_info</div>|;
  .'<b>'.&mt('Construction Space').'</b>:&nbsp;'              return $bodytag;
  .'<form name="dirs" method="post" action="'.$formaction          }
  .'" target="_top"><tt><b>'  
  .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv','','+1',1)."<font size=\"+1\">$lastitem</font></b></tt><br />"          unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
  .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()')              $bodytag .= qq|<div id="LC_nav_bar">$name $role</div>|;
  .'</form>'          }
  .&Apache::lonmenu::constspaceform();  
         }          $bodytag .= Apache::lonhtmlcommon::scripttag(
               Apache::lonmenu::utilityfunctions(), 'start');
         my $titletable;  
  if (!$notitle) {          $bodytag .= Apache::lonmenu::primary_menu();
     $titletable =  
  '<table id="LC_title_bar">'.          if ($dc_info) {
                          "<tr><td> $titleinfo $dc_info</td>".$roleinfo.              $dc_info = &dc_courseid_toggle($dc_info);
  '</tr></table>';          }
  }          $bodytag .= qq|<div id="LC_realm">$realm $dc_info</div>|;
  if ($notopbar) {  
     $bodytag .= $titletable;          #don't show menus for public users
  } else {          if (!$public){
     if ($env{'request.state'} eq 'construct') {              $bodytag .= Apache::lonmenu::secondary_menu();
                 $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg,              $bodytag .= Apache::lonmenu::serverform();
   $titletable);              $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
             } else {              if ($env{'request.state'} eq 'construct') {
                 $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg).                  $bodytag .= &Apache::lonmenu::innerregister($forcereg,
     $titletable;                                  $args->{'bread_crumbs'});
               } elsif ($forcereg) { 
                   $bodytag .= &Apache::lonmenu::innerregister($forcereg);
             }              }
           }else{
               # this is to seperate menu from content when there's no secondary
               # menu. Especially needed for public accessible ressources.
               $bodytag .= '<hr style="clear:both" />';
               $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); 
         }          }
         return $bodytag;  
     }  
   
 #          return $bodytag;
 # Top frame rendering, Remote is up  }
 #  
   
     my $imgsrc = $img;  sub dc_courseid_toggle {
     if ($img =~ /^\/adm/) {      my ($dc_info) = @_;
         $imgsrc = &lonhttpdurl($img);      return ' <span id="dccidtext" class="LC_cusr_subheading LC_nobreak">'.
     }             '<a href="javascript:showCourseID();">'.
     my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />';             &mt('(More ...)').'</a></span>'.
              '<div id="dccid" class="LC_dccid">'.$dc_info.'</div>';
     # Explicit link to get inline menu  
     my $menu= ($no_inline_link?''  
        :'<br /><a href="/adm/remote?action=collapse">'.&mt('Switch to Inline Menu Mode').'</a>');  
     #  
     if ($notitle) {  
  return $bodytag;  
     }  
     return(<<ENDBODY);  
 $bodytag  
 <table id="LC_title_bar" class="LC_with_remote">  
 <tr><td class="LC_title_bar_role_logo">$upperleft</td>  
     <td class="LC_title_bar_domain_logo">$messages&nbsp;</td>  
 </tr>  
 <tr><td>$titleinfo $dc_info $menu</td>  
 $roleinfo  
 </tr>  
 </table>  
 ENDBODY  
 }  }
   
 sub make_attr_string {  sub make_attr_string {
Line 4536  sub make_attr_string { Line 4901  sub make_attr_string {
  delete($attr_ref->{$key});   delete($attr_ref->{$key});
     }      }
  }   }
  $attr_ref->{'onload'}  =   $attr_ref->{'onload'}  = $on_load;
     &Apache::lonmenu::loadevents().  $on_load;   $attr_ref->{'onunload'}= $on_unload;
  $attr_ref->{'onunload'}=  
     &Apache::lonmenu::unloadevents().$on_unload;  
     }  
   
 # Accessibility font enhance  
     if ($env{'browser.fontenhance'} eq 'on') {  
  my $style;  
  foreach my $key (keys(%{$attr_ref})) {  
     if (lc($key) eq 'style') {  
  $style.=$attr_ref->{$key}.';';  
  delete($attr_ref->{$key});  
     }  
  }  
  $attr_ref->{'style'}=$style.'; font-size: x-large;';  
     }  
   
     if ($env{'browser.blackwhite'} eq 'on') {  
  delete($attr_ref->{'font'});  
  delete($attr_ref->{'link'});  
  delete($attr_ref->{'alink'});  
  delete($attr_ref->{'vlink'});  
  delete($attr_ref->{'bgcolor'});  
  delete($attr_ref->{'background'});  
     }      }
   
     my $attr_string;      my $attr_string;
Line 4623  sub standard_css { Line 4965  sub standard_css {
     my $img    = &designparm($function.'.img',   $domain);      my $img    = &designparm($function.'.img',   $domain);
     my $tabbg  = &designparm($function.'.tabbg', $domain);      my $tabbg  = &designparm($function.'.tabbg', $domain);
     my $font   = &designparm($function.'.font',  $domain);      my $font   = &designparm($function.'.font',  $domain);
       my $fontmenu = &designparm($function.'.fontmenu', $domain);
   #second colour for later usage
     my $sidebg = &designparm($function.'.sidebg',$domain);      my $sidebg = &designparm($function.'.sidebg',$domain);
     my $pgbg_or_bgcolor =      my $pgbg_or_bgcolor =
          $bgcolor ||           $bgcolor ||
Line 4634  sub standard_css { Line 4978  sub standard_css {
   
     my $sans                 = 'Verdana,Arial,Helvetica,sans-serif';      my $sans                 = 'Verdana,Arial,Helvetica,sans-serif';
     my $mono                 = 'monospace';      my $mono                 = 'monospace';
     my $data_table_head      = $tabbg;      my $data_table_head      = $sidebg;
     my $data_table_light     = '#FAFAFA';      my $data_table_light     = '#FAFAFA';
     my $data_table_dark      = '#F0F0F0';      my $data_table_dark      = '#F0F0F0';
     my $data_table_darker    = '#CCCCCC';      my $data_table_darker    = '#CCCCCC';
Line 4650  sub standard_css { Line 4994  sub standard_css {
     my $table_header         = '#DDDDDD';      my $table_header         = '#DDDDDD';
     my $feedback_link_bg     = '#BBBBBB';      my $feedback_link_bg     = '#BBBBBB';
     my $lg_border_color      = '#C8C8C8';      my $lg_border_color      = '#C8C8C8';
       my $button_hover         = '#BF2317';
   
     my $border = ($env{'browser.type'} eq 'explorer' ||      my $border = ($env{'browser.type'} eq 'explorer' ||
   $env{'browser.type'} eq 'safari'     ) ? '0 2px 0 2px'        $env{'browser.type'} eq 'safari'     ) ? '0 2px 0 2px'
                                                  : '0 3px 0 4px';                                               : '0 3px 0 4px';
   
   
     return <<END;      return <<END;
 h1, h2, h3, th { font-family: $sans }  
 a:focus { color: red; background: yellow }   
   
 hr {  /* needed for iframe to allow 100% height in FF */
   clear: both;  body, html { 
   color: $tabbg;      margin: 0;
   background-color: $tabbg;      padding: 0 0.5%;
   height: 3px;      height: 99%; /* to avoid scrollbars */
   border: none;  
 }  }
   
 table.thinborder,  body {
     font-family: $sans;
     line-height:130%;
     font-size:0.83em;
     color:$font;
   }
   
 table.thinborder tr th {  a:focus,
   border-style: solid;  a:focus img {
   border-width: 1px;    color: red;
   background: $tabbg;    background: yellow;
 }  }
 table.thinborder tr td {  
   border-style: solid;  form, .inline {
   border-width: 1px    display: inline;
   }
   
   .LC_right {
     text-align:right;
   }
   
   .LC_middle {
     vertical-align:middle;
   }
   
   .LC_400Box {
     width:400px;
   }
   
   .LC_iframecontainer {
       width: 98%;
       margin: 0;
       position: fixed;
       top: 8.5em;
       bottom: 0;
   }
   
   .LC_iframecontainer iframe{
       border: none;
       width: 100%;
       height: 100%;
   }
   
   .LC_filename {
     font-family: $mono;
     white-space:pre;
     font-size: 120%;
   }
   
   .LC_fileicon {
     border: none;
     height: 1.3em;
     vertical-align: text-bottom;
     margin-right: 0.3em;
     text-decoration:none;
   }
   
   .LC_setting {
     text-decoration:underline;
 }  }
   
 form, .inline { display: inline; }  
 .center { text-align: center; }  
 .LC_filename {font-family: $mono; white-space:pre;}  
 .LC_error {  .LC_error {
   color: red;    color: red;
   font-size: larger;    font-size: larger;
 }  }
   
 .LC_warning,  .LC_warning,
 .LC_diff_removed {  .LC_diff_removed {
   color: red;    color: red;
Line 4712  div.LC_confirm_box .LC_success img { Line 5101  div.LC_confirm_box .LC_success img {
   
 .LC_icon {  .LC_icon {
   border: none;    border: none;
     vertical-align: middle;
 }  }
 .LC_indexer_icon {  
   border: 0;  
   height: 22px;  
 }  
 .LC_docs_spacer {  .LC_docs_spacer {
   width: 25px;    width: 25px;
   height: 1px;    height: 1px;
Line 4727  div.LC_confirm_box .LC_success img { Line 5114  div.LC_confirm_box .LC_success img {
   color: #999999;    color: #999999;
 }  }
   
   .LC_discussion {
     background: $tabbg;
     border: 1px solid black;
     margin: 2px;
   }
   
   .LC_disc_action_links_bar {
     background: $tabbg;
     border: none;
     margin: 4px;
   }
   
   .LC_disc_action_left {
     text-align: left;
   }
   
   .LC_disc_action_right {
     text-align: right;
   }
   
   .LC_disc_new_item {
     background: white;
     border: 2px solid red;
     margin: 2px;
   }
   
   .LC_disc_old_item {
     background: white;
     border: 1px solid black;
     margin: 2px;
   }
   
 table.LC_pastsubmission {  table.LC_pastsubmission {
   border: 1px solid black;    border: 1px solid black;
   margin: 2px;    margin: 2px;
 }  }
   
 table#LC_top_nav, table#LC_menubuttons,table#LC_nav_location {  table#LC_menubuttons {
   width: 100%;    width: 100%;
   background: $pgbg;    background: $pgbg;
   border: 2px;    border: 2px;
Line 4740  table#LC_top_nav, table#LC_menubuttons,t Line 5159  table#LC_top_nav, table#LC_menubuttons,t
   padding: 0;    padding: 0;
 }  }
   
 table#LC_title_bar, table.LC_breadcrumbs,   table#LC_title_bar a {
     color: $fontmenu;
   }
   
   table#LC_title_bar {
     clear: both;
     display: none;
   }
   
   table#LC_title_bar,
   table.LC_breadcrumbs, /* obsolete? */
 table#LC_title_bar.LC_with_remote {  table#LC_title_bar.LC_with_remote {
   width: 100%;    width: 100%;
   border-color: $pgbg;    border-color: $pgbg;
   border-style: solid;    border-style: solid;
   border-width: $border;    border-width: $border;
   
   background: $pgbg;    background: $pgbg;
   font-family: $sans;    color: $fontmenu;
   border-collapse: collapse;    border-collapse: collapse;
   padding: 0;    padding: 0;
     margin: 0;
 }  }
   
 table.LC_docs_path {  ul.LC_breadcrumb_tools_outerlist {
   width: 100%;      margin: 0;
   border: 0;      padding: 0;
   background: $pgbg;      position: relative;
   font-family: $sans;      list-style: none;
   border-collapse: collapse;  }
   padding: 0;  ul.LC_breadcrumb_tools_outerlist li {
       display: inline;
   }
   
   .LC_breadcrumb_tools_navigation {
       padding: 0;
       margin: 0;
       float: left;
   }
   .LC_breadcrumb_tools_tools {
       padding: 0;
       margin: 0;
       float: right;
 }  }
   
 table#LC_title_bar td {  table#LC_title_bar td {
   background: $tabbg;    background: $tabbg;
 }  }
 table#LC_title_bar td.LC_title_bar_who {  
   background: $tabbg;  table#LC_menubuttons img {
   color: $font;    border: none;
   font: small $sans;  
   text-align: right;  
 }  }
 span.LC_metadata {  
     font-family: $sans;  .LC_breadcrumbs_component {
     float: right;
     margin: 0 1em;
 }  }
 span.LC_title_bar_title {  .LC_breadcrumbs_component img {
   font: bold x-large $sans;    vertical-align: middle;
 }  }
 table#LC_title_bar td.LC_title_bar_domain_logo {  
   background: $sidebg;  td.LC_table_cell_checkbox {
   text-align: right;    text-align: center;
   padding: 0;  
 }  }
 table#LC_title_bar td.LC_title_bar_role_logo {  
   background: $sidebg;  .LC_fontsize_small {
   padding: 0;    font-size: 70%;
 }  }
   
 table#LC_menubuttons_mainmenu {  #LC_breadcrumbs {
   width: 100%;    clear:both;
   border: 0;    background: $sidebg;
   border-spacing: 1px;    border-bottom: 1px solid $lg_border_color;
   padding: 0 1px;    line-height: 2.5em;
     overflow: hidden;
   margin: 0;    margin: 0;
   border-collapse: separate;    padding: 0;
 }  
 table#LC_menubuttons img, table#LC_menubuttons_mainmenu img {  
   border: none;  
 }  
 table#LC_top_nav td {  
   background: $tabbg;  
   border: none;  
   font-size: small;  
 }  
 table#LC_top_nav td a, div#LC_top_nav a {  
   color: $font;  
   font-family: $sans;  
 }  
 table#LC_top_nav td.LC_top_nav_logo {  
   background: $tabbg;  
   text-align: left;    text-align: left;
   white-space: nowrap;  
   width: 31px;  
 }  
 table#LC_top_nav td.LC_top_nav_logo img {  
   border: none;  
   vertical-align: bottom;  
 }  }
 table#LC_top_nav td.LC_top_nav_exit,  
 table#LC_top_nav td.LC_top_nav_help {  .LC_head_subbox {
   width: 2.0em;    clear:both;
     background: #F8F8F8; /* $sidebg; */
     border: 1px solid $sidebg;
     margin: 0 0 10px 0;      
     padding: 3px;
     text-align: left;
 }  }
 table#LC_top_nav td.LC_top_nav_login {  
   width: 4.0em;  .LC_fontsize_medium {
   text-align: center;    font-size: 85%;
 }  }
 table.LC_breadcrumbs td, table.LC_docs_path td  {  
   background: $tabbg;  .LC_fontsize_large {
   color: $font;    font-size: 120%;
   font-family: $sans;  
   font-size: smaller;  
 }  }
 table.LC_breadcrumbs td.LC_breadcrumbs_component,  
 table.LC_docs_path td.LC_docs_path_component {  .LC_menubuttons_inline_text {
   background: $tabbg;  
   color: $font;    color: $font;
   font-family: $sans;    font-size: 90%;
   font-size: larger;    padding-left:3px;
   text-align: right;  
 }  
 td.LC_table_cell_checkbox {  
   text-align: center;  
 }  }
 table#LC_mainmenu td.LC_mainmenu_column {  
     vertical-align: top;  .LC_menubuttons_inline_text img{
     vertical-align: middle;
 }  }
   
 .LC_menubuttons_inline_text {  li.LC_menubuttons_inline_text img,a {
   color: $font;    cursor:pointer;
   font-family: $sans;    text-decoration: none;
   font-size: smaller;  
 }  }
   
 .LC_menubuttons_link {  .LC_menubuttons_link {
   text-decoration: none;    text-decoration: none;
 }  }
 /*2008--9-5: new menu style sheet.Changed category*/  
 .LC_menubuttons_category {  .LC_menubuttons_category {
   color: $font;    color: $font;
   background: $pgbg;    background: $pgbg;
   font-family: $sans;  
   font-size: larger;    font-size: larger;
   font-weight: bold;    font-weight: bold;
 }  }
   
 td.LC_menubuttons_text {  td.LC_menubuttons_text {
   width: 90%;  
   color: $font;    color: $font;
   font-family: $sans;  
 }  
   
 td.LC_menubuttons_img {  
 }  }
   
 .LC_current_location {  .LC_current_location {
   font-family: $sans;  
   background: $tabbg;    background: $tabbg;
 }  }
 .LC_new_mail {  
   font-family: $sans;  
   background: $tabbg;  
   font-weight: bold;  
 }  
   
 .LC_dropadd_labeltext {  table.LC_data_table {
   font-family: $sans;  
   text-align: right;  
 }  
   
 .LC_preferences_labeltext {  
   font-family: $sans;  
   text-align: right;  
 }  
   
 .LC_roleslog_note {  
   font-size: smaller;  
 }  
   
 .LC_mail_functions {  
     font-weight: bold;  
 }  
   
 table.LC_aboutme_port {  
   border: none;  
   border-collapse: collapse;  
   border-spacing: 0;  
 }  
 table.LC_data_table, table.LC_mail_list {  
   border: 1px solid #000000;    border: 1px solid #000000;
   border-collapse: separate;    border-collapse: separate;
   border-spacing: 1px;    border-spacing: 1px;
   background: $pgbg;    background: $pgbg;
 }  }
   
 .LC_data_table_dense {  .LC_data_table_dense {
   font-size: small;    font-size: small;
 }  }
   
 table.LC_nested_outer {  table.LC_nested_outer {
   border: 1px solid #000000;    border: 1px solid #000000;
   border-collapse: collapse;    border-collapse: collapse;
   border-spacing: 0;    border-spacing: 0;
   width: 100%;    width: 100%;
 }  }
   
 table.LC_innerpickbox,  table.LC_innerpickbox,
 table.LC_nested {  table.LC_nested {
   border: none;    border: none;
Line 4928  table.LC_nested { Line 5314  table.LC_nested {
   border-spacing: 0;    border-spacing: 0;
   width: 100%;    width: 100%;
 }  }
 table.LC_data_table tr th, table.LC_calendar tr th, table.LC_mail_list tr th,  
   table.LC_data_table tr th,
   table.LC_calendar tr th,
 table.LC_prior_tries tr th,  table.LC_prior_tries tr th,
 table.LC_innerpickbox tr th {  table.LC_innerpickbox tr th {
   font-weight: bold;    font-weight: bold;
   background-color: $data_table_head;    background-color: $data_table_head;
   font-size: smaller;    color:$fontmenu;
     font-size:90%;
 }  }
   
 table.LC_innerpickbox tr th,  table.LC_innerpickbox tr th,
 table.LC_innerpickbox tr td {  table.LC_innerpickbox tr td {
   vertical-align: top;    vertical-align: top;
 }  }
   
 table.LC_data_table tr.LC_info_row > td {  table.LC_data_table tr.LC_info_row > td {
   background-color: #CCCCCC;    background-color: #CCCCCC;
   font-weight: bold;    font-weight: bold;
   text-align: left;    text-align: left;
 }  }
 table.LC_data_table tr.LC_odd_row > td,   
 table.LC_pick_box tr > td.LC_odd_row,  table.LC_data_table tr.LC_odd_row > td {
 table.LC_aboutme_port tr td {  
   background-color: $data_table_light;    background-color: $data_table_light;
   padding: 2px;    padding: 2px;
     vertical-align: top;
   }
   
   table.LC_pick_box tr > td.LC_odd_row {
     background-color: $data_table_light;
     vertical-align: top;
 }  }
 table.LC_data_table tr.LC_even_row > td,  
 table.LC_pick_box tr > td.LC_even_row,  table.LC_data_table tr.LC_even_row > td {
 table.LC_aboutme_port tr.LC_even_row td {  
   background-color: $data_table_dark;    background-color: $data_table_dark;
   padding: 2px;    padding: 2px;
     vertical-align: top;
 }  }
   
   table.LC_pick_box tr > td.LC_even_row {
     background-color: $data_table_dark;
     vertical-align: top;
   }
   
 table.LC_data_table tr.LC_data_table_highlight td {  table.LC_data_table tr.LC_data_table_highlight td {
   background-color: $data_table_darker;    background-color: $data_table_darker;
 }  }
   
 table.LC_data_table tr td.LC_leftcol_header {  table.LC_data_table tr td.LC_leftcol_header {
   background-color: $data_table_head;    background-color: $data_table_head;
   font-weight: bold;    font-weight: bold;
 }  }
   
 table.LC_data_table tr.LC_empty_row td,  table.LC_data_table tr.LC_empty_row td,
 table.LC_nested tr.LC_empty_row td {  table.LC_nested tr.LC_empty_row td {
   background-color: #FFFFFF;  
   font-weight: bold;    font-weight: bold;
   font-style: italic;    font-style: italic;
   text-align: center;    text-align: center;
   padding: 8px;    padding: 8px;
 }  }
   
   table.LC_data_table tr.LC_empty_row td {
     background-color: $sidebg;
   }
   
   table.LC_nested tr.LC_empty_row td {
     background-color: #FFFFFF;
   }
   
   table.LC_caption {
   }
   
 table.LC_nested tr.LC_empty_row td {  table.LC_nested tr.LC_empty_row td {
   padding: 4ex    padding: 4ex
 }  }
   
 table.LC_nested_outer tr th {  table.LC_nested_outer tr th {
   font-weight: bold;    font-weight: bold;
     color:$fontmenu;
   background-color: $data_table_head;    background-color: $data_table_head;
   font-size: smaller;    font-size: small;
   border-bottom: 1px solid #000000;    border-bottom: 1px solid #000000;
 }  }
   
 table.LC_nested_outer tr td.LC_subheader {  table.LC_nested_outer tr td.LC_subheader {
   background-color: $data_table_head;    background-color: $data_table_head;
   font-weight: bold;    font-weight: bold;
Line 4987  table.LC_nested_outer tr td.LC_subheader Line 5405  table.LC_nested_outer tr td.LC_subheader
   border-bottom: 1px solid #000000;    border-bottom: 1px solid #000000;
   text-align: right;    text-align: right;
 }  }
   
 table.LC_nested tr.LC_info_row td {  table.LC_nested tr.LC_info_row td {
   background-color: #CCCCCC;    background-color: #CCCCCC;
   font-weight: bold;    font-weight: bold;
   font-size: small;    font-size: small;
   text-align: center;    text-align: center;
 }  }
   
 table.LC_nested tr.LC_info_row td.LC_left_item,  table.LC_nested tr.LC_info_row td.LC_left_item,
 table.LC_nested_outer tr th.LC_left_item {  table.LC_nested_outer tr th.LC_left_item {
   text-align: left;    text-align: left;
 }  }
   
 table.LC_nested td {  table.LC_nested td {
   background-color: #FFFFFF;    background-color: #FFFFFF;
   font-size: small;    font-size: small;
 }  }
   
 table.LC_nested_outer tr th.LC_right_item,  table.LC_nested_outer tr th.LC_right_item,
 table.LC_nested tr.LC_info_row td.LC_right_item,  table.LC_nested tr.LC_info_row td.LC_right_item,
 table.LC_nested tr.LC_odd_row td.LC_right_item,  table.LC_nested tr.LC_odd_row td.LC_right_item,
Line 5016  table.LC_createuser { Line 5438  table.LC_createuser {
 }  }
   
 table.LC_createuser tr.LC_section_row td {  table.LC_createuser tr.LC_section_row td {
   font-size: smaller;    font-size: small;
 }  }
   
 table.LC_createuser tr.LC_info_row td  {  table.LC_createuser tr.LC_info_row td  {
Line 5028  table.LC_createuser tr.LC_info_row td  { Line 5450  table.LC_createuser tr.LC_info_row td  {
 table.LC_calendar {  table.LC_calendar {
   border: 1px solid #000000;    border: 1px solid #000000;
   border-collapse: collapse;    border-collapse: collapse;
     width: 98%;
 }  }
   
 table.LC_calendar_pickdate {  table.LC_calendar_pickdate {
   font-size: xx-small;    font-size: xx-small;
 }  }
   
 table.LC_calendar tr td {  table.LC_calendar tr td {
   border: 1px solid #000000;    border: 1px solid #000000;
   vertical-align: top;    vertical-align: top;
     width: 14%;
 }  }
   
 table.LC_calendar tr td.LC_calendar_day_empty {  table.LC_calendar tr td.LC_calendar_day_empty {
   background-color: $data_table_dark;    background-color: $data_table_dark;
 }  }
   
 table.LC_calendar tr td.LC_calendar_day_current {  table.LC_calendar tr td.LC_calendar_day_current {
   background-color: $data_table_highlight;    background-color: $data_table_highlight;
 }  }
   
 table.LC_mail_list tr.LC_mail_new {  table.LC_data_table tr td.LC_mail_new {
   background-color: $mail_new;    background-color: $mail_new;
 }  }
 table.LC_mail_list tr.LC_mail_new:hover {  
   table.LC_data_table tr.LC_mail_new:hover {
   background-color: $mail_new_hover;    background-color: $mail_new_hover;
 }  }
 table.LC_mail_list tr.LC_mail_read {  
   table.LC_data_table tr td.LC_mail_read {
   background-color: $mail_read;    background-color: $mail_read;
 }  }
 table.LC_mail_list tr.LC_mail_read:hover {  
   /*
   table.LC_data_table tr.LC_mail_read:hover {
   background-color: $mail_read_hover;    background-color: $mail_read_hover;
 }  }
 table.LC_mail_list tr.LC_mail_replied {  */
   
   table.LC_data_table tr td.LC_mail_replied {
   background-color: $mail_replied;    background-color: $mail_replied;
 }  }
 table.LC_mail_list tr.LC_mail_replied:hover {  
   /*
   table.LC_data_table tr.LC_mail_replied:hover {
   background-color: $mail_replied_hover;    background-color: $mail_replied_hover;
 }  }
 table.LC_mail_list tr.LC_mail_other {  */
   
   table.LC_data_table tr td.LC_mail_other {
   background-color: $mail_other;    background-color: $mail_other;
 }  }
 table.LC_mail_list tr.LC_mail_other:hover {  
   background-color: $mail_other_hover;  
 }  
 table.LC_mail_list tr.LC_mail_even {  
 }  
 table.LC_mail_list tr.LC_mail_odd {  
 }  
   
   /*
 table#LC_portfolio_actions {  table.LC_data_table tr.LC_mail_other:hover {
   width: auto;    background-color: $mail_other_hover;
   background: $pgbg;  
   border: none;  
   border-spacing: 2px 2px;  
   padding: 0;  
   margin: 0;  
   border-collapse: separate;  
 }  
 table#LC_portfolio_actions td.LC_label {  
   background: $tabbg;  
   text-align: right;  
 }  
 table#LC_portfolio_actions td.LC_value {  
   background: $tabbg;  
 }  }
   */
   
 table#LC_cstr_controls {  table.LC_data_table tr > td.LC_browser_file,
   width: 100%;  table.LC_data_table tr > td.LC_browser_file_published {
   border-collapse: collapse;    background: #AAEE77;
 }  
 table#LC_cstr_controls tr td {  
   border: 4px solid $pgbg;  
   padding: 4px;  
   text-align: center;  
   background: $tabbg;  
 }  
 table#LC_cstr_controls tr th {  
   border: 4px solid $pgbg;  
   background: $table_header;  
   text-align: center;  
   font-family: $sans;  
   font-size: smaller;  
 }  }
   
 table#LC_browser {  table.LC_data_table tr > td.LC_browser_file_locked,
    table.LC_data_table tr > td.LC_browser_file_unpublished {
 }  
 table#LC_browser tr th {  
   background: $table_header;  
 }  
 table#LC_browser tr td {  
   padding: 2px;  
 }  
 table#LC_browser tr.LC_browser_file,  
 table#LC_browser tr.LC_browser_file_published {  
   background: #CCFF88;  
 }  
 table#LC_browser tr.LC_browser_file_locked,  
 table#LC_browser tr.LC_browser_file_unpublished {  
   background: #FFAA99;    background: #FFAA99;
 }  }
 table#LC_browser tr.LC_browser_file_obsolete {  
   background: #AAAAAA;  table.LC_data_table tr > td.LC_browser_file_obsolete {
     background: #888888;
 }  }
 table#LC_browser tr.LC_browser_file_modified,  
 table#LC_browser tr.LC_browser_file_metamodified {  table.LC_data_table tr > td.LC_browser_file_modified,
   background: #FFFF77;  table.LC_data_table tr > td.LC_browser_file_metamodified {
     background: #F8F866;
 }  }
 table#LC_browser tr.LC_browser_folder {  
   background: #CCCCFF;  table.LC_data_table tr.LC_browser_folder > td {
     background: #E0E8FF;
 }  }
   
 table.LC_data_table tr > td.LC_roles_is {  table.LC_data_table tr > td.LC_roles_is {
 /*  background: #77FF77; */    /* background: #77FF77; */
 }  }
   
 table.LC_data_table tr > td.LC_roles_future {  table.LC_data_table tr > td.LC_roles_future {
   background: #FFFF77;    border-right: 8px solid #FFFF77;
 }  }
   
 table.LC_data_table tr > td.LC_roles_will {  table.LC_data_table tr > td.LC_roles_will {
   background: #FFAA77;    border-right: 8px solid #FFAA77;
 }  }
   
 table.LC_data_table tr > td.LC_roles_expired {  table.LC_data_table tr > td.LC_roles_expired {
   background: #FF7777;    border-right: 8px solid #FF7777;
 }  }
   
 table.LC_data_table tr > td.LC_roles_will_not {  table.LC_data_table tr > td.LC_roles_will_not {
   background: #AAFF77;    border-right: 8px solid #AAFF77;
 }  }
   
 table.LC_data_table tr > td.LC_roles_selected {  table.LC_data_table tr > td.LC_roles_selected {
   background: #11CC55;    border-right: 8px solid #11CC55;
 }  }
   
 span.LC_current_location {  span.LC_current_location {
   font-size: x-large;    font-size:larger;
   background: $pgbg;    background: $pgbg;
 }  }
   
 span.LC_parm_menu_item {  span.LC_parm_menu_item {
   font-size: larger;    font-size: larger;
   font-family: $sans;  
 }  }
   
 span.LC_parm_scope_all {  span.LC_parm_scope_all {
   color: red;    color: red;
 }  }
   
 span.LC_parm_scope_folder {  span.LC_parm_scope_folder {
   color: green;    color: green;
 }  }
   
 span.LC_parm_scope_resource {  span.LC_parm_scope_resource {
   color: orange;    color: orange;
 }  }
   
 span.LC_parm_part {  span.LC_parm_part {
   color: blue;    color: blue;
 }  }
 span.LC_parm_folder, span.LC_parm_symb {  
   span.LC_parm_folder,
   span.LC_parm_symb {
   font-size: x-small;    font-size: x-small;
   font-family: $mono;    font-family: $mono;
   color: #AAAAAA;    color: #AAAAAA;
 }  }
   
 td.LC_parm_overview_level_menu, td.LC_parm_overview_map_menu,  ul.LC_parm_parmlist li {
 td.LC_parm_overview_parm_selectors, td.LC_parm_overview_parm_restrictions {    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_map_menu,
   td.LC_parm_overview_parm_selectors,
   td.LC_parm_overview_restrictions  {
   border: 1px solid black;    border: 1px solid black;
   border-collapse: collapse;    border-collapse: collapse;
 }  }
   
 table.LC_parm_overview_restrictions td {  table.LC_parm_overview_restrictions td {
   border-width: 1px 4px 1px 4px;    border-width: 1px 4px 1px 4px;
   border-style: solid;    border-style: solid;
   border-color: $pgbg;    border-color: $pgbg;
   text-align: center;    text-align: center;
 }  }
   
 table.LC_parm_overview_restrictions th {  table.LC_parm_overview_restrictions th {
   background: $tabbg;    background: $tabbg;
   border-width: 1px 4px 1px 4px;    border-width: 1px 4px 1px 4px;
   border-style: solid;    border-style: solid;
   border-color: $pgbg;    border-color: $pgbg;
 }  }
   
 table#LC_helpmenu {  table#LC_helpmenu {
   border: none;    border: none;
   height: 55px;    height: 55px;
Line 5207  table#LC_helpmenu { Line 5626  table#LC_helpmenu {
   
 table#LC_helpmenu fieldset legend {  table#LC_helpmenu fieldset legend {
   font-size: larger;    font-size: larger;
   font-weight: bold;  
 }  }
   
 table#LC_helpmenu_links {  table#LC_helpmenu_links {
   width: 100%;    width: 100%;
   border: 1px solid black;    border: 1px solid black;
Line 5216  table#LC_helpmenu_links { Line 5635  table#LC_helpmenu_links {
   padding: 0;    padding: 0;
   border-spacing: 1px;    border-spacing: 1px;
 }  }
   
 table#LC_helpmenu_links tr td {  table#LC_helpmenu_links tr td {
   padding: 1px;    padding: 1px;
   background: $tabbg;    background: $tabbg;
Line 5223  table#LC_helpmenu_links tr td { Line 5643  table#LC_helpmenu_links tr td {
   font-weight: bold;    font-weight: bold;
 }  }
   
 table#LC_helpmenu_links a:link, table#LC_helpmenu_links a:visited,  table#LC_helpmenu_links a:link,
   table#LC_helpmenu_links a:visited,
 table#LC_helpmenu_links a:active {  table#LC_helpmenu_links a:active {
   text-decoration: none;    text-decoration: none;
   color: $font;    color: $font;
 }  }
   
 table#LC_helpmenu_links a:hover {  table#LC_helpmenu_links a:hover {
   text-decoration: underline;    text-decoration: underline;
   color: $vlink;    color: $vlink;
Line 5237  table#LC_helpmenu_links a:hover { Line 5659  table#LC_helpmenu_links a:hover {
   border: 1px solid #339933;    border: 1px solid #339933;
   margin: -1px;    margin: -1px;
 }  }
   
 .LC_chrt_popup_up {  .LC_chrt_popup_up {
   border: 1px solid yellow;    border: 1px solid yellow;
   margin: -1px;    margin: -1px;
 }  }
   
 .LC_chrt_popup {  .LC_chrt_popup {
   border: 1px solid #8888FF;    border: 1px solid #8888FF;
   background: #CCCCFF;    background: #CCCCFF;
 }  }
   
 table.LC_pick_box {  table.LC_pick_box {
   border-collapse: separate;    border-collapse: separate;
   background: white;    background: white;
   border: 1px solid black;    border: 1px solid black;
   border-spacing: 1px;    border-spacing: 1px;
 }  }
   
 table.LC_pick_box td.LC_pick_box_title {  table.LC_pick_box td.LC_pick_box_title {
   background: $sidebg;    background: $sidebg;
   font-weight: bold;    font-weight: bold;
   text-align: right;    text-align: left;
   vertical-align: top;    vertical-align: top;
   width: 184px;    width: 184px;
   padding: 8px;    padding: 8px;
 }  }
 table.LC_pick_box td.LC_selfenroll_pick_box_title {  
   background: $sidebg;  
   font-weight: bold;  
   text-align: right;  
   width: 350px;  
   padding: 8px;  
 }  
   
 table.LC_pick_box td.LC_pick_box_value {  table.LC_pick_box td.LC_pick_box_value {
   text-align: left;    text-align: left;
   padding: 8px;    padding: 8px;
 }  }
   
 table.LC_pick_box td.LC_pick_box_select {  table.LC_pick_box td.LC_pick_box_select {
   text-align: left;    text-align: left;
   padding: 8px;    padding: 8px;
 }  }
   
 table.LC_pick_box td.LC_pick_box_separator {  table.LC_pick_box td.LC_pick_box_separator {
   padding: 0;    padding: 0;
   height: 1px;    height: 1px;
   background: black;    background: black;
 }  }
   
 table.LC_pick_box td.LC_pick_box_submit {  table.LC_pick_box td.LC_pick_box_submit {
   text-align: right;    text-align: right;
 }  }
   
 table.LC_pick_box td.LC_evenrow_value {  table.LC_pick_box td.LC_evenrow_value {
   text-align: left;    text-align: left;
   padding: 8px;    padding: 8px;
   background-color: $data_table_light;    background-color: $data_table_light;
 }  }
   
 table.LC_pick_box td.LC_oddrow_value {  table.LC_pick_box td.LC_oddrow_value {
   text-align: left;    text-align: left;
   padding: 8px;    padding: 8px;
   background-color: $data_table_light;    background-color: $data_table_light;
 }  }
 table.LC_helpform_receipt {  
   width: 620px;  
   border-collapse: separate;  
   background: white;  
   border: 1px solid black;  
   border-spacing: 1px;  
 }  
 table.LC_helpform_receipt td.LC_pick_box_title {  
   background: $tabbg;  
   font-weight: bold;  
   text-align: right;  
   width: 184px;  
   padding: 8px;  
 }  
 table.LC_helpform_receipt td.LC_evenrow_value {  
   text-align: left;  
   padding: 8px;  
   background-color: $data_table_light;  
 }  
 table.LC_helpform_receipt td.LC_oddrow_value {  
   text-align: left;  
   padding: 8px;  
   background-color: $data_table_light;  
 }  
 table.LC_helpform_receipt td.LC_pick_box_separator {  
   padding: 0;  
   height: 1px;  
   background: black;  
 }  
 span.LC_helpform_receipt_cat {  span.LC_helpform_receipt_cat {
   font-weight: bold;    font-weight: bold;
 }  }
   
 table.LC_group_priv_box {  table.LC_group_priv_box {
   background: white;    background: white;
   border: 1px solid black;    border: 1px solid black;
   border-spacing: 1px;    border-spacing: 1px;
 }  }
   
 table.LC_group_priv_box td.LC_pick_box_title {  table.LC_group_priv_box td.LC_pick_box_title {
   background: $tabbg;    background: $tabbg;
   font-weight: bold;    font-weight: bold;
   text-align: right;    text-align: right;
   width: 184px;    width: 184px;
 }  }
   
 table.LC_group_priv_box td.LC_groups_fixed {  table.LC_group_priv_box td.LC_groups_fixed {
   background: $data_table_light;    background: $data_table_light;
   text-align: center;    text-align: center;
 }  }
   
 table.LC_group_priv_box td.LC_groups_optional {  table.LC_group_priv_box td.LC_groups_optional {
   background: $data_table_dark;    background: $data_table_dark;
   text-align: center;    text-align: center;
 }  }
   
 table.LC_group_priv_box td.LC_groups_functionality {  table.LC_group_priv_box td.LC_groups_functionality {
   background: $data_table_darker;    background: $data_table_darker;
   text-align: center;    text-align: center;
   font-weight: bold;    font-weight: bold;
 }  }
   
 table.LC_group_priv td {  table.LC_group_priv td {
   text-align: left;    text-align: left;
   padding: 0;    padding: 0;
 }  }
   
 table.LC_notify_front_page {  
   background: white;  
   border: 1px solid black;  
   padding: 8px;  
 }  
 table.LC_notify_front_page td {  
   padding: 8px;  
 }  
 .LC_navbuttons {  .LC_navbuttons {
   margin: 2ex 0ex 2ex 0ex;    margin: 2ex 0ex 2ex 0ex;
 }  }
   
 .LC_topic_bar {  .LC_topic_bar {
   font-family: $sans;  
   font-weight: bold;    font-weight: bold;
   width: 100%;  
   background: $tabbg;    background: $tabbg;
   vertical-align: middle;    margin: 1em 0em 1em 2em;
   margin: 2ex 0ex 2ex 0ex;  
   padding: 3px;    padding: 3px;
     font-size: 1.2em;
 }  }
   
 .LC_topic_bar span {  .LC_topic_bar span {
     left: 0.5em;
     position: absolute;
   vertical-align: middle;    vertical-align: middle;
     font-size: 1.2em;
 }  }
 .LC_topic_bar img {  
   vertical-align: bottom;  
 }  
 table.LC_course_group_status {  table.LC_course_group_status {
   margin: 20px;    margin: 20px;
 }  }
   
 table.LC_status_selector td {  table.LC_status_selector td {
   vertical-align: top;    vertical-align: top;
   text-align: center;    text-align: center;
   padding: 4px;    padding: 4px;
 }  }
 table.LC_descriptive_input td.LC_description {  
   vertical-align: top;  
   text-align: right;  
   font-weight: bold;  
 }  
 div.LC_feedback_link {  div.LC_feedback_link {
   clear: both;    clear: both;
   background: white;    background: $sidebg;
   width: 100%;      width: 100%;
     padding-bottom: 10px;
     border: 1px $tabbg solid;
     height: 22px;
     line-height: 22px;
     padding-top: 5px;
   }
   
   div.LC_feedback_link img {
     height: 22px;
     vertical-align:middle;
   }
   
   div.LC_feedback_link a {
     text-decoration: none;
   }
   
   div.LC_comblock {
     display:inline;
     color:$font;
     font-size:90%;
   }
   
   div.LC_feedback_link div.LC_comblock {
     padding-left:5px;
   }
   
   div.LC_feedback_link div.LC_comblock a {
     color:$font;
 }  }
   
 span.LC_feedback_link {  span.LC_feedback_link {
   background: $feedback_link_bg;    /* background: $feedback_link_bg; */
   font-size: larger;    font-size: larger;
 }  }
   
 span.LC_message_link {  span.LC_message_link {
   background: $feedback_link_bg;    /* background: $feedback_link_bg; */
   font-size: larger;    font-size: larger;
   position: absolute;    position: absolute;
   right: 1em;    right: 1em;
Line 5420  table.LC_prior_tries td { Line 5842  table.LC_prior_tries td {
 }  }
   
 .LC_answer_correct {  .LC_answer_correct {
   background: #AAFFAA;    background: lightgreen;
   color: black;    color: darkgreen;
     padding: 6px;
 }  }
   
 .LC_answer_charged_try {  .LC_answer_charged_try {
   background: #FFAAAA ! important;    background: #FFAAAA;
   color: black;    color: darkred;
     padding: 6px;
 }  }
 .LC_answer_not_charged_try,   
   .LC_answer_not_charged_try,
 .LC_answer_no_grade,  .LC_answer_no_grade,
 .LC_answer_late {  .LC_answer_late {
   background: #FFFFAA;    background: lightyellow;
   color: black;    color: black;
     padding: 6px;
 }  }
   
 .LC_answer_previous {  .LC_answer_previous {
   background: #AAAAFF;    background: lightblue;
   color: black;    color: darkblue;
     padding: 6px;
 }  }
   
 .LC_answer_no_message {  .LC_answer_no_message {
   background: #FFFFFF;    background: #FFFFFF;
   color: black;    color: black;
     padding: 6px;
 }  }
   
 .LC_answer_unknown {  .LC_answer_unknown {
   background: orange;    background: orange;
   color: black;    color: black;
     padding: 6px;
 }  }
   
   
 span.LC_prior_numerical,  span.LC_prior_numerical,
 span.LC_prior_string,  span.LC_prior_string,
 span.LC_prior_custom,  span.LC_prior_custom,
 span.LC_prior_reaction,  span.LC_prior_reaction,
 span.LC_prior_math {  span.LC_prior_math {
   font-family: monospace;    font-family: $mono;
   white-space: pre;    white-space: pre;
 }  }
   
 span.LC_prior_string {  span.LC_prior_string {
   font-family: monospace;    font-family: $mono;
   white-space: pre;    white-space: pre;
 }  }
   
Line 5465  table.LC_prior_option { Line 5897  table.LC_prior_option {
   width: 100%;    width: 100%;
   border-collapse: collapse;    border-collapse: collapse;
 }  }
 table.LC_prior_rank, table.LC_prior_match {  
   table.LC_prior_rank,
   table.LC_prior_match {
   border-collapse: collapse;    border-collapse: collapse;
 }  }
   
 table.LC_prior_option tr td,  table.LC_prior_option tr td,
 table.LC_prior_rank tr td,  table.LC_prior_rank tr td,
 table.LC_prior_match tr td {  table.LC_prior_match tr td {
   border: 1px solid #000000;    border: 1px solid #000000;
 }  }
   
 span.LC_nobreak {  .LC_nobreak {
   white-space: nowrap;    white-space: nowrap;
 }  }
   
Line 5487  span.LC_cusr_subheading { Line 5922  span.LC_cusr_subheading {
   font-size: 85%;    font-size: 85%;
 }  }
   
 table.LC_docs_documents {  div.LC_docs_entry_move {
   background: #BBBBBB;    border: 1px solid #BBBBBB;
   border-width: 0;  
   border-collapse: collapse;  
 }  
   
 table.LC_docs_documents td.LC_docs_document {  
   border: 2px solid black;  
   padding: 4px;  
 }  
   
 .LC_docs_course_commands div {  
   float: left;  
   border: 4px solid #AAAAAA;  
   padding: 4px;  
   background: #DDDDCC;  
 }  
   
 .LC_docs_entry_move {  
   border: none;  
   border-collapse: collapse;  
 }  
   
 .LC_docs_entry_move td {  
   border: 2px solid #BBBBBB;  
   background: #DDDDDD;    background: #DDDDDD;
     width: 22px;
     padding: 1px;
     margin: 0;
 }  }
   
 .LC_docs_editor td.LC_docs_entry_commands {  table.LC_data_table tr > td.LC_docs_entry_commands,
   table.LC_data_table tr > td.LC_docs_entry_parameter {
   background: #DDDDDD;    background: #DDDDDD;
   font-size: x-small;    font-size: x-small;
 }  }
   
   .LC_docs_entry_parameter {
     white-space: nowrap;
   }
   
 .LC_docs_copy {  .LC_docs_copy {
   color: #000099;    color: #000099;
 }  }
   
 .LC_docs_cut {  .LC_docs_cut {
   color: #550044;    color: #550044;
 }  }
   
 .LC_docs_rename {  .LC_docs_rename {
   color: #009900;    color: #009900;
 }  }
   
 .LC_docs_remove {  .LC_docs_remove {
   color: #990000;    color: #990000;
 }  }
Line 5537  table.LC_docs_documents td.LC_docs_docum Line 5961  table.LC_docs_documents td.LC_docs_docum
   font-size: x-small;    font-size: x-small;
 }  }
   
 .LC_docs_editor td.LC_docs_entry_title,  
 .LC_docs_editor td.LC_docs_entry_icon {  
   background: #FFFFBB;  
 }  
 .LC_docs_editor td.LC_docs_entry_parameter {  
   background: #BBBBFF;  
   font-size: x-small;  
   white-space: nowrap;  
 }  
   
 table.LC_docs_adddocs td,  table.LC_docs_adddocs td,
 table.LC_docs_adddocs th {  table.LC_docs_adddocs th {
   border: 1px solid #BBBBBB;    border: 1px solid #BBBBBB;
Line 5557  table.LC_docs_adddocs th { Line 5971  table.LC_docs_adddocs th {
 table.LC_sty_begin {  table.LC_sty_begin {
   background: #BBFFBB;    background: #BBFFBB;
 }  }
   
 table.LC_sty_end {  table.LC_sty_end {
   background: #FFBBBB;    background: #FFBBBB;
 }  }
Line 5577  table.LC_double_column tr td.LC_left_col Line 5992  table.LC_double_column tr td.LC_left_col
   
 table.LC_double_column tr td.LC_right_col {  table.LC_double_column tr td.LC_right_col {
   top: 2px;    top: 2px;
   right: 2px;     right: 2px;
   width: 47%;    width: 47%;
   vertical-align: top;    vertical-align: top;
 }  }
   
 span.LC_role_level {  
   font-weight: bold;  
 }  
   
 div.LC_left_float {  div.LC_left_float {
   float: left;    float: left;
   padding-right: 5%;    padding-right: 5%;
Line 5601  div.LC_clear_float_footer { Line 6012  div.LC_clear_float_footer {
   clear: both;    clear: both;
 }  }
   
   
 div.LC_grade_select_mode {  
   font-family: $sans;  
 }  
 div.LC_grade_select_mode div div {  
   margin: 5px;  
 }  
 div.LC_grade_select_mode_selector {  
   margin: 5px;  
   float: left;  
 }  
 div.LC_grade_select_mode_selector_header {  
   font: bold medium $sans;  
 }  
 div.LC_grade_select_mode_type {  
   clear: left;  
 }  
   
 div.LC_grade_show_user {  div.LC_grade_show_user {
   margin-top: 20px;  /*  border-left: 5px solid $sidebg; */
   border: 1px solid black;    border-top: 5px solid #000000;
     margin: 50px 0 0 0;
     padding: 15px 0 5px 10px;
 }  }
 div.LC_grade_user_name {  
   background: #DDDDEE;  div.LC_grade_show_user_odd_row {
   border-bottom: 1px solid black;  /*  border-left: 5px solid #000000; */
   font: bold large $sans;  
 }  }
 div.LC_grade_show_user_odd_row div.LC_grade_user_name {  
   background: #DDEEDD;  div.LC_grade_show_user div.LC_Box {
     margin-right: 50px;
 }  }
   
 div.LC_grade_show_problem,  
 div.LC_grade_submissions,  div.LC_grade_submissions,
 div.LC_grade_message_center,  div.LC_grade_message_center,
 div.LC_grade_info_links,  div.LC_grade_info_links {
 div.LC_grade_assign {  
   margin: 5px;    margin: 5px;
   width: 99%;    width: 99%;
   background: #FFFFFF;    background: #FFFFFF;
 }  }
 div.LC_grade_show_problem_header,  
 div.LC_grade_submissions_header,  div.LC_grade_submissions_header,
 div.LC_grade_message_center_header,  div.LC_grade_message_center_header {
 div.LC_grade_assign_header {    font-weight: bold;
   font: bold large $sans;    font-size: large;
 }  }
 div.LC_grade_show_problem_problem,  
 div.LC_grade_submissions_body,  div.LC_grade_submissions_body,
 div.LC_grade_message_center_body,  div.LC_grade_message_center_body {
 div.LC_grade_assign_body {  
   border: 1px solid black;    border: 1px solid black;
   width: 99%;    width: 99%;
   background: #FFFFFF;    background: #FFFFFF;
 }  }
 span.LC_grade_check_note {  
   font: normal medium $sans;  
   display: inline;  
   position: absolute;  
   right: 1em;  
 }  
   
 table.LC_scantron_action {  table.LC_scantron_action {
   width: 100%;    width: 100%;
 }  }
   
 table.LC_scantron_action tr th {  table.LC_scantron_action tr th {
   font: normal bold $sans;    font-weight:bold;
     font-style:normal;
 }  }
   
 div.LC_edit_problem_header,   .LC_edit_problem_header,
 div.LC_edit_problem_footer {  div.LC_edit_problem_footer {
   font: normal medium $sans;    font-weight: normal;
     font-size:  medium;
   margin: 2px;    margin: 2px;
 }  }
   
 div.LC_edit_problem_header,  div.LC_edit_problem_header,
 div.LC_edit_problem_header div,  div.LC_edit_problem_header div,
 div.LC_edit_problem_footer,  div.LC_edit_problem_footer,
Line 5682  div.LC_edit_problem_editxml_header, Line 6072  div.LC_edit_problem_editxml_header,
 div.LC_edit_problem_editxml_header div {  div.LC_edit_problem_editxml_header div {
   margin-top: 5px;    margin-top: 5px;
 }  }
 div.LC_edit_problem_header_edit_row {  
   background: $tabbg;  
   padding: 3px;  
   margin-bottom: 5px;  
 }  
 div.LC_edit_problem_header_title {  div.LC_edit_problem_header_title {
   font: larger bold $sans;    font-weight: bold;
     font-size: larger;
   background: $tabbg;    background: $tabbg;
   padding: 3px;    padding: 3px;
 }  }
   
 table.LC_edit_problem_header_title {  table.LC_edit_problem_header_title {
   font: larger bold $sans;  
   width: 100%;    width: 100%;
   border-color: $pgbg;  
   border-style: solid;  
   border-width: $border;  
   
   background: $tabbg;    background: $tabbg;
   border-collapse: collapse;  
   padding: 0;  
 }  }
   
 div.LC_edit_problem_discards {  div.LC_edit_problem_discards {
   float: left;    float: left;
   padding-bottom: 5px;    padding-bottom: 5px;
 }  }
   
 div.LC_edit_problem_saves {  div.LC_edit_problem_saves {
   float: right;    float: right;
   padding-bottom: 5px;    padding-bottom: 5px;
 }  }
 hr.LC_edit_problem_divide {  
   clear: both;  img.stift {
   color: $tabbg;    border-width: 0;
   background-color: $tabbg;    vertical-align: middle;
   height: 3px;  }
   
   table td.LC_mainmenu_col_fieldset {
     vertical-align: top;
   }
   
   div.LC_createcourse {
     margin: 10px 10px 10px 10px;
   }
   
   .LC_dccid {
     margin: 0.2em 0 0 0;
     padding: 0;
     font-size: 90%;
     display:none;
   }
   
   a:hover,
   ol.LC_primary_menu a:hover,
   ol#LC_MenuBreadcrumbs a:hover,
   ol#LC_PathBreadcrumbs a:hover,
   ul#LC_secondary_menu a:hover,
   .LC_FormSectionClearButton input:hover
   ul.LC_TabContent   li:hover a {
     color:$button_hover;
     text-decoration:none;
   }
   
   h1 {
     padding: 0;
     line-height:130%;
   }
   
   h2,
   h3,
   h4,
   h5,
   h6 {
     margin: 5px 0 5px 0;
     padding: 0;
     line-height:130%;
   }
   
   .LC_hcell {
     padding:3px 15px 3px 15px;
     margin: 0;
     background-color:$tabbg;
     color:$fontmenu;
     border-bottom:solid 1px $lg_border_color;
   }
   
   .LC_Box > .LC_hcell {
     margin: 0 -10px 10px -10px;
   }
   
   .LC_noBorder {
     border: 0;
   }
   
   .LC_FormSectionClearButton input {
     background-color:transparent;
   border: none;    border: none;
     cursor:pointer;
     text-decoration:underline;
 }  }
 img.stift{  
   border-width:0;  .LC_help_open_topic {
   vertical-align:middle;    color: #FFFFFF;
     background-color: #EEEEFF;
     margin: 1px;
     padding: 4px;
     border: 1px solid #000033;
     white-space: nowrap;
     /* vertical-align: middle; */
   }
   
   dl,
   ul,
   div,
   fieldset {
     margin: 10px 10px 10px 0;
     /* overflow: hidden; */
   }
   
   fieldset > legend {
     font-weight: bold;
     padding: 0 5px 0 5px;
   }
   
   #LC_nav_bar {
     float: left;
     background-color: $pgbg_or_bgcolor;
     margin: 0 0 2px 0;
 }  }
   
 table#LC_mainmenu{  #LC_realm {
  margin-top:10px;    margin: 0.2em 0 0 0;
  width:80%;    padding: 0;
     font-weight: bold;
     text-align: center;
     background-color: $pgbg_or_bgcolor;
   }
   
   #LC_nav_bar em {
     font-weight: bold;
     font-style: normal;
 }  }
   
 table#LC_mainmenu td.LC_mainmenu_col_fieldset{  ol.LC_primary_menu {
     float: right;
     margin: 0;
     background-color: $pgbg_or_bgcolor;
   }
   
   ol#LC_PathBreadcrumbs {
     margin: 0;
   }
   
   ol.LC_primary_menu li {
     display: inline;
     padding: 5px 5px 0 10px;
   vertical-align: top;    vertical-align: top;
   width: 45%;  
 }  }
 .LC_mainmenu_fieldset_category {  
   ol.LC_primary_menu li img {
     vertical-align: bottom;
     height: 1.1em;
   }
   
   ol.LC_primary_menu a {
     color: RGB(80, 80, 80);
     text-decoration: none;
   }
   
   ol.LC_primary_menu a.LC_new_message {
     font-weight:bold;
     color: darkred;
   }
   
   ol.LC_docs_parameters {
     margin-left: 0;
     padding: 0;
     list-style: none;
   }
   
   ol.LC_docs_parameters li {
     margin: 0;
     padding-right: 20px;
     display: inline;
   }
   
   ol.LC_docs_parameters li:before {
     content: "\\002022 \\0020";
   }
   
   li.LC_docs_parameters_title {
     font-weight: bold;
   }
   
   ol.LC_docs_parameters li.LC_docs_parameters_title:before {
     content: "";
   }
   
   ul#LC_secondary_menu {
     clear: both;
     color: $fontmenu;
     background: $tabbg;
     list-style: none;
     padding: 0;
     margin: 0;
     width: 100%;
     text-align: left;
   }
   
   ul#LC_secondary_menu li {
     font-weight: bold;
     line-height: 1.8em;
     padding: 0 0.8em;
     border-right: 1px solid black;
     display: inline;
     vertical-align: middle;
   }
   
   ul.LC_TabContent {
     display:block;
     background: $sidebg;
     border-bottom: solid 1px $lg_border_color;
     list-style:none;
     margin: -1px -10px 0 -10px;
     padding: 0;
   }
   
   ul.LC_TabContent li,
   ul.LC_TabContentBigger li {
     float:left;
   }
   
   ul#LC_secondary_menu li a {
     color: $fontmenu;
     text-decoration: none;
   }
   
   ul.LC_TabContent {
     min-height:20px;
   }
   
   ul.LC_TabContent li {
     vertical-align:middle;
     padding: 0 16px 0 10px;
     background-color:$tabbg;
     border-bottom:solid 1px $lg_border_color;
     border-left: solid 1px $font;
   }
   
   ul.LC_TabContent .right {
     float:right;
   }
   
   ul.LC_TabContent li a,
   ul.LC_TabContent li {
     color:rgb(47,47,47);
     text-decoration:none;
     font-size:95%;
     font-weight:bold;
     min-height:20px;
   }
   
   ul.LC_TabContent li a:hover,
   ul.LC_TabContent li a:focus {
     color: $button_hover;
     background:none;
     outline:none;
   }
   
   ul.LC_TabContent li:hover {
     color: $button_hover;
     cursor:pointer;
   }
   
   ul.LC_TabContent li.active {
   color: $font;    color: $font;
   background: $pgbg;    background:#FFFFFF url(/adm/lonIcons/open.gif) no-repeat scroll right center;
   font-family: $sans;    border-bottom:solid 1px #FFFFFF;
   font-size: small;    cursor: default;
   }
   
   ul.LC_TabContent li.active a {
     color:$font;
     background:#FFFFFF;
     outline: none;
   }
   #maincoursedoc {
     clear:both;
   }
   
   ul.LC_TabContentBigger {
     display:block;
     list-style:none;
     padding: 0;
   }
   
   ul.LC_TabContentBigger li {
     vertical-align:bottom;
     height: 30px;
     font-size:110%;
     font-weight:bold;
     color: #737373;
   }
   
   ul.LC_TabContentBigger li.active {
     position: relative;
     top: 1px;
   }
   
   ul.LC_TabContentBigger li a {
     background:url('/adm/lonIcons/tabbgleft.gif') left bottom no-repeat;
     height: 30px;
     line-height: 30px;
     text-align: center;
     display: block;
     text-decoration: none;
     outline: none;  
   }
   
   ul.LC_TabContentBigger li.active a {
     background:url('/adm/lonIcons/tabbgleft.gif') left top no-repeat;
     color:$font;
   }
   
   ul.LC_TabContentBigger li b {
     background: url('/adm/lonIcons/tabbgright.gif') no-repeat right bottom;
     display: block;
     float: left;
     padding: 0 30px;
     border-bottom: 1px solid $lg_border_color;
   }
   
   ul.LC_TabContentBigger li:hover b {
     color:$button_hover;
   }
   
   ul.LC_TabContentBigger li.active b {
     background:url('/adm/lonIcons/tabbgright.gif') right top no-repeat;
     color:$font;
     border: 0;
   }
   
   
   ul.LC_CourseBreadcrumbs {
     background: $sidebg;
     height: 2em;
     padding-left: 10px;
     margin: 0;
     list-style-position: inside;
   }
   
   ol#LC_MenuBreadcrumbs,
   ol#LC_PathBreadcrumbs {
     padding-left: 10px;
     margin: 0;
     height: 2.5em;  /* equal to #LC_breadcrumbs line-height */
   }
   
   ol#LC_MenuBreadcrumbs li,
   ol#LC_PathBreadcrumbs li,
   ul.LC_CourseBreadcrumbs li {
     display: inline;
     white-space: normal;  
   }
   
   ol#LC_MenuBreadcrumbs li a,
   ul.LC_CourseBreadcrumbs li a {
     text-decoration: none;
     font-size:90%;
   }
   
   ol#LC_MenuBreadcrumbs h1 {
     display: inline;
     font-size: 90%;
     line-height: 2.5em;
     margin: 0;
     padding: 0;
   }
   
   ol#LC_PathBreadcrumbs li a {
     text-decoration:none;
     font-size:100%;
     font-weight:bold;
   }
   
   .LC_Box {
     border: solid 1px $lg_border_color;
     padding: 0 10px 10px 10px;
   }
   
   .LC_DocsBox {
     border: solid 1px $lg_border_color;
     padding: 0 0 10px 10px;
   }
   
   .LC_AboutMe_Image {
     float:left;
     margin-right:10px;
   }
   
   .LC_Clear_AboutMe_Image {
     clear:left;
   }
   
   dl.LC_ListStyleClean dt {
     padding-right: 5px;
     display: table-header-group;
   }
   
   dl.LC_ListStyleClean dd {
     display: table-row;
   }
   
   .LC_ListStyleClean,
   .LC_ListStyleSimple,
   .LC_ListStyleNormal,
   .LC_ListStyleSpecial {
     /* display:block; */
     list-style-position: inside;
     list-style-type: none;
     overflow: hidden;
     padding: 0;
   }
   
   .LC_ListStyleSimple li,
   .LC_ListStyleSimple dd,
   .LC_ListStyleNormal li,
   .LC_ListStyleNormal dd,
   .LC_ListStyleSpecial li,
   .LC_ListStyleSpecial dd {
     margin: 0;
     padding: 5px 5px 5px 10px;
     clear: both;
   }
   
   .LC_ListStyleClean li,
   .LC_ListStyleClean dd {
     padding-top: 0;
     padding-bottom: 0;
   }
   
   .LC_ListStyleSimple dd,
   .LC_ListStyleSimple li {
     border-bottom: solid 1px $lg_border_color;
   }
   
   .LC_ListStyleSpecial li,
   .LC_ListStyleSpecial dd {
     list-style-type: none;
     background-color: RGB(220, 220, 220);
     margin-bottom: 4px;
   }
   
   table.LC_SimpleTable {
     margin:5px;
     border:solid 1px $lg_border_color;
   }
   
   table.LC_SimpleTable tr {
     padding: 0;
     border:solid 1px $lg_border_color;
   }
   
   table.LC_SimpleTable thead {
     background:rgb(220,220,220);
   }
   
   div.LC_columnSection {
     display: block;
     clear: both;
     overflow: hidden;
     margin: 0;
   }
   
   div.LC_columnSection>* {
     float: left;
     margin: 10px 20px 10px 0;
     overflow:hidden;
   }
   
   table em {
   font-weight: bold;    font-weight: bold;
     font-style: normal;
 }  }
 fieldset#LC_mainmenu_fieldset {  
   margin:0 10px 10px 0;  
   
   table.LC_tableBrowseRes,
   table.LC_tableOfContent {
     border:none;
     border-spacing: 1px;
     padding: 3px;
     background-color: #FFFFFF;
     font-size: 90%;
 }  }
   
 div.LC_createcourse {  table.LC_tableOfContent {
     margin: 10px 10px 10px 10px;    border-collapse: collapse;
   }
   
   table.LC_tableBrowseRes a,
   table.LC_tableOfContent a {
     background-color: transparent;
     text-decoration: none;
   }
   
   table.LC_tableOfContent img {
     border: none;
     height: 1.3em;
     vertical-align: text-bottom;
     margin-right: 0.3em;
   }
   
   a#LC_content_toolbar_firsthomework {
     background-image:url(/res/adm/pages/open-first-problem.gif);
   }
   
   a#LC_content_toolbar_everything {
     background-image:url(/res/adm/pages/show-all.gif);
   }
   
   a#LC_content_toolbar_uncompleted {
     background-image:url(/res/adm/pages/show-incomplete-problems.gif);
   }
   
   #LC_content_toolbar_clearbubbles {
     background-image:url(/res/adm/pages/mark-discussionentries-read.gif);
   }
   
   a#LC_content_toolbar_changefolder {
     background : url(/res/adm/pages/close-all-folders.gif) top center ;
   }
   
   a#LC_content_toolbar_changefolder_toggled {
     background-image:url(/res/adm/pages/open-all-folders.gif);
   }
   
   ul#LC_toolbar li a:hover {
     background-position: bottom center;
   }
   
   ul#LC_toolbar {
     padding: 0;
     margin: 2px;
     list-style:none;
     position:relative;
     background-color:white;
   }
   
   ul#LC_toolbar li {
     border:1px solid white;
     padding: 0;
     margin: 0;
     float: left;
     display:inline;
     vertical-align:middle;
   }
   
   
   a.LC_toolbarItem {
     display:block;
     padding: 0;
     margin: 0;
     height: 32px;
     width: 32px;
     color:white;
     border: none;
     background-repeat:no-repeat;
     background-color:transparent;
   }
   
   ul.LC_funclist {
       margin: 0;
       padding: 0.5em 1em 0.5em 0;
   }
   
   ul.LC_funclist > li:first-child {
       font-weight:bold; 
       margin-left:0.8em;
   }
   
   ul.LC_funclist + ul.LC_funclist {
       /* 
          left border as a seperator if we have more than
          one list 
       */
       border-left: 1px solid $sidebg;
       /* 
          this hides the left border behind the border of the 
          outer box if element is wrapped to the next 'line' 
       */
       margin-left: -1px;
   }
   
   ul.LC_funclist li {
     display: inline;
     white-space: nowrap;
     margin: 0 0 0 25px;
     line-height: 150%;
   }
   
   .LC_hidden {
     display: none;
 }  }
   
 END  END
Line 5801  sub headtag { Line 6717  sub headtag {
     if (!$args->{'frameset'}) {      if (!$args->{'frameset'}) {
  $result .= &Apache::lonhtmlcommon::htmlareaheaders();   $result .= &Apache::lonhtmlcommon::htmlareaheaders();
     }      }
     if ($args->{'force_register'}) {      if ($args->{'force_register'} && $env{'request.noversionuri'} !~ m{^/res/adm/pages/}) {
  $result .= &Apache::lonmenu::registerurl(1);          $result .= Apache::lonxml::display_title();
     }      }
     if (!$args->{'no_nav_bar'}       if (!$args->{'no_nav_bar'} 
  && !$args->{'only_body'}   && !$args->{'only_body'}
Line 5828  ADDMETA Line 6744  ADDMETA
     $result .= '<title> LON-CAPA '.$title.'</title>'      $result .= '<title> LON-CAPA '.$title.'</title>'
  .'<link rel="stylesheet" type="text/css" href="'.$url.'" />'   .'<link rel="stylesheet" type="text/css" href="'.$url.'" />'
  .$head_extra;   .$head_extra;
     return $result;      return $result.'</head>';
 }  }
   
 =pod  =pod
Line 5863  Inputs: none Line 6779  Inputs: none
 sub xml_begin {  sub xml_begin {
     my $output='';      my $output='';
   
     if ($env{'internal.start_page'}==1) {  
  &Apache::lonhtmlcommon::init_htmlareafields();  
     }  
   
     if ($env{'browser.mathml'}) {      if ($env{'browser.mathml'}) {
  $output='<?xml version="1.0"?>'   $output='<?xml version="1.0"?>'
             #.'<?xml-stylesheet type="text/css" href="/adm/MathML/mathml.css"?>'."\n"              #.'<?xml-stylesheet type="text/css" href="/adm/MathML/mathml.css"?>'."\n"
Line 5877  sub xml_begin { Line 6789  sub xml_begin {
             .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" '               .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" ' 
     .'xmlns="http://www.w3.org/1999/xhtml">';      .'xmlns="http://www.w3.org/1999/xhtml">';
     } else {      } else {
  $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'.   $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
             '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';             .'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
     }      }
     return $output;      return $output;
 }  }
   
 =pod  =pod
   
 =item * &endheadtag()  
   
 Returns a uniform </head> for LON-CAPA web pages.  
   
 Inputs: none  
   
 =cut  
   
 sub endheadtag {  
     return '</head>';  
 }  
   
 =pod  
   
 =item * &head()  
   
 Returns a uniform complete <head>..</head> section for LON-CAPA web pages.  
   
 Inputs:  
   
 =over 4  
   
 $title - optional title for the page  
   
 $head_extra - optional extra HTML to put inside the <head>  
   
 =back  
   
 =cut  
   
 sub head {  
     my ($title,$head_extra,$args) = @_;  
     return &headtag($title,$head_extra,$args).&endheadtag();  
 }  
   
 =pod  
   
 =item * &start_page()  =item * &start_page()
   
 Returns a complete <html> .. <body> section for LON-CAPA web pages.  Returns a complete <html> .. <body> section for LON-CAPA web pages.
Line 5940  $args - additional optional args support Line 6815  $args - additional optional args support
   
              only_body      -> is true will set &bodytag() onlybodytag               only_body      -> is true will set &bodytag() onlybodytag
                                     arg on                                      arg on
              no_nav_bar     -> is true will set &bodytag() notopbar arg on               no_nav_bar     -> is true will set &bodytag() no_nav_bar arg on
              add_entries    -> additional attributes to add to the  <body>               add_entries    -> additional attributes to add to the  <body>
              domain         -> force to color decorate a page for a                domain         -> force to color decorate a page for a 
                                     specific domain                                      specific domain
Line 5954  $args - additional optional args support Line 6829  $args - additional optional args support
                                     a html attribute                                      a html attribute
              force_register -> if is true will turn on the &bodytag()               force_register -> if is true will turn on the &bodytag()
                                     $forcereg arg                                      $forcereg arg
              body_title     -> alternate text to use instead of $title  
                                     in the title box that appears, this text  
                                     is not auto translated like the $title is  
              frameset       -> if true will start with a <frameset>               frameset       -> if true will start with a <frameset>
                                     rather than <body>                                      rather than <body>
              no_title       -> if true the title bar won't be shown  
              skip_phases    -> hash ref of                skip_phases    -> hash ref of 
                                     head -> skip the <html><head> generation                                      head -> skip the <html><head> generation
                                     body -> skip all <body> generation                                      body -> skip all <body> generation
              no_inline_link -> if true and in remote mode, don't show the   
                                     'Switch To Inline Menu' link  
              no_auto_mt_title -> prevent &mt()ing the title arg               no_auto_mt_title -> prevent &mt()ing the title arg
              inherit_jsmath -> when creating popup window in a page,               inherit_jsmath -> when creating popup window in a page,
                                     should it have jsmath forced on by the                                      should it have jsmath forced on by the
                                     current page                                      current page
                bread_crumbs ->             Array containing breadcrumbs
                bread_crumbs_component ->  if exists show it as headline else show only the breadcrumbs
   
 =back  =back
   
Line 5979  $args - additional optional args support Line 6850  $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;      my %head_args;
     foreach my $arg ('redirect','force_register','domain','function',      foreach my $arg ('redirect','force_register','domain','function',
      'bgcolor','frameset','no_nav_bar','only_body',       'bgcolor','frameset','no_nav_bar','only_body',
Line 5987  sub start_page { Line 6866  sub start_page {
     $head_args{$arg} = $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().                    &xml_begin() . &headtag($title,$head_extra,\%head_args);
     &headtag($title,$head_extra,\%head_args).&endheadtag();  #replace prev line by
   #                 &xml_begin() . &headtag($title, $head_extra, $args);
     }      }
           
     if (! exists($args->{'skip_phases'}{'body'}) ) {      if (! exists($args->{'skip_phases'}{'body'}) ) {
Line 6001  sub start_page { Line 6883  sub start_page {
     my $attr_string = &make_attr_string($args->{'force_register'},      my $attr_string = &make_attr_string($args->{'force_register'},
  $args->{'add_entries'});   $args->{'add_entries'});
     $result .= "\n<frameset $attr_string>\n";      $result .= "\n<frameset $attr_string>\n";
  } else {          } else {
     $result .=              $result .=
  &bodytag($title,                   &bodytag($title, 
  $args->{'function'},       $args->{'add_entries'},                           $args->{'function'},       $args->{'add_entries'},
  $args->{'only_body'},      $args->{'domain'},                           $args->{'only_body'},      $args->{'domain'},
  $args->{'force_register'}, $args->{'body_title'},                           $args->{'force_register'}, $args->{'no_nav_bar'},
  $args->{'no_nav_bar'},     $args->{'bgcolor'},                           $args->{'bgcolor'},        $args);
  $args->{'no_title'},       $args->{'no_inline_link'},          }
  $args);  
  }  
     }      }
   
     if ($args->{'js_ready'}) {      if ($args->{'js_ready'}) {
  $result = &js_ready($result);   $result = &js_ready($result);
     }      }
     if ($args->{'html_encode'}) {      if ($args->{'html_encode'}) {
  $result = &html_encode($result);   $result = &html_encode($result);
     }      }
   
       # Preparation for new and consistent functionlist at top of screen
       # if ($args->{'functionlist'}) {
       #            $result .= &build_functionlist();
       #}
   
       # Don't add anything more if only_body wanted or in const space
       return $result if    $args->{'only_body'} 
                         || $env{'request.state'} eq 'construct';
   
     #Breadcrumbs      #Breadcrumbs
     if (exists($args->{'bread_crumbs'}) or exists($args->{'bread_crumbs_component'})) {      if (exists($args->{'bread_crumbs'}) or exists($args->{'bread_crumbs_component'})) {
         &Apache::lonhtmlcommon::clear_breadcrumbs();   &Apache::lonhtmlcommon::clear_breadcrumbs();
         #if any br links exists, add them to the breadcrumbs   #if any br links exists, add them to the breadcrumbs
         if (exists($args->{'bread_crumbs'}) and ref($args->{'bread_crumbs'}) eq 'ARRAY') {   if (exists($args->{'bread_crumbs'}) and ref($args->{'bread_crumbs'}) eq 'ARRAY') {         
             foreach my $crumb (@{$args->{'bread_crumbs'}}){   foreach my $crumb (@{$args->{'bread_crumbs'}}){
                 &Apache::lonhtmlcommon::add_breadcrumb($crumb);   &Apache::lonhtmlcommon::add_breadcrumb($crumb);
             }   }
         }   }
   
         #if bread_crumbs_component exists show it as headline else show only the breadcrumbs   #if bread_crumbs_component exists show it as headline else show only the breadcrumbs
         if (exists($args->{'bread_crumbs_component'})){   if(exists($args->{'bread_crumbs_component'})){
             $result .= &Apache::lonhtmlcommon::breadcrumbs($args->{'bread_crumbs_component'});   $result .= &Apache::lonhtmlcommon::breadcrumbs($args->{'bread_crumbs_component'});
         } else {   }else{
             $result .= &Apache::lonhtmlcommon::breadcrumbs();   $result .= &Apache::lonhtmlcommon::breadcrumbs();
         }   }
     }      }
     return $result;      return $result;
 }  }
   
 =pod  
   
 =item * &head()  
   
 Returns a complete </body></html> section for LON-CAPA web pages.  
   
 Inputs:         $args - additional optional args supported are:  
                  js_ready     -> return a string ready for being used in   
                                  a javascript writeln  
                  html_encode  -> return a string ready for being used in   
                                  a html attribute  
                  frameset     -> if true will start with a <frameset>  
                                  rather than <body>  
                  dicsussion   -> if true will get discussion from  
                                   lonxml::xmlend  
                                  (you can pass the target and parser arguments  
                                   through optional 'target' and 'parser' args  
                                   to this routine)  
   
 =cut  
   
 sub end_page {  sub end_page {
     my ($args) = @_;      my ($args) = @_;
     $env{'internal.end_page'}++;      $env{'internal.end_page'}++;
Line 6134  sub validate_page { Line 7003  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 '</td></tr></table>';
   }
   
 sub simple_error_page {  sub simple_error_page {
     my ($r,$title,$msg) = @_;      my ($r,$title,$msg) = @_;
     my $page =      my $page =
Line 6149  sub simple_error_page { Line 7036  sub simple_error_page {
   
 {  {
     my @row_count;      my @row_count;
   
       sub start_data_table_count {
           unshift(@row_count, 0);
           return;
       }
   
       sub end_data_table_count {
           shift(@row_count);
           return;
       }
   
     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));
  unshift(@row_count,0);          my $table_id;
  return '<table class="'.$css_class.'">'."\n";          if (defined($id)) {
               $table_id = ' id="'.$id.'"';
           }
    &start_data_table_count();
    return '<table class="'.$css_class.'"'.$table_id.'>'."\n";
     }      }
   
     sub end_data_table {      sub end_data_table {
  shift(@row_count);   &end_data_table_count();
  return '</table>'."\n";;   return '</table>'."\n";;
     }      }
   
     sub start_data_table_row {      sub start_data_table_row {
  my ($add_class) = @_;   my ($add_class, $id) = @_;
  $row_count[0]++;   $row_count[0]++;
  my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';   my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
  $css_class = (join(' ',$css_class,$add_class));   $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
  return  '<tr class="'.$css_class.'">'."\n";;          $id = (' id="'.$id.'"') unless ($id eq '');
           return  '<tr class="'.$css_class.'"'.$id.'>'."\n";
     }      }
           
     sub continue_data_table_row {      sub continue_data_table_row {
  my ($add_class) = @_;   my ($add_class, $id) = @_;
  my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';   my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
  $css_class = (join(' ',$css_class,$add_class));   $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
  return  '<tr class="'.$css_class.'">'."\n";;          $id = (' id="'.$id.'"') unless ($id eq '');
           return  '<tr class="'.$css_class.'"'.$id.'>'."\n";
     }      }
   
     sub end_data_table_row {      sub end_data_table_row {
Line 6181  sub simple_error_page { Line 7085  sub simple_error_page {
     }      }
   
     sub start_data_table_empty_row {      sub start_data_table_empty_row {
  $row_count[0]++;  # $row_count[0]++;
  return  '<tr class="LC_empty_row" >'."\n";;   return  '<tr class="LC_empty_row" >'."\n";;
     }      }
   
Line 6196  sub simple_error_page { Line 7100  sub simple_error_page {
     sub end_data_table_header_row {      sub end_data_table_header_row {
  return '</tr>'."\n";;   return '</tr>'."\n";;
     }      }
   
       sub data_table_caption {
           my $caption = shift;
           return "<caption class=\"LC_caption\">$caption</caption>";
       }
 }  }
   
 =pod  =pod
Line 6262  Returns either 'student','coordinator',' Line 7171  Returns either 'student','coordinator','
   
 ###############################################  ###############################################
 sub get_users_function {  sub get_users_function {
     my $function = 'student';      my $function = 'norole';
     if ($env{'request.role'}=~/^(cc|in|ta|ep)/) {      if ($env{'request.role'}=~/^(st)/) {
           $function='student';
       }
       if ($env{'request.role'}=~/^(cc|co|in|ta|ep)/) {
         $function='coordinator';          $function='coordinator';
     }      }
     if ($env{'request.role'}=~/^(su|dc|ad|li)/) {      if ($env{'request.role'}=~/^(su|dc|ad|li)/) {
         $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 6284  sub get_users_function { Line 7196  sub get_users_function {
   
 Used by lonmenu.pm and lonroles.pm to determine whether to use the word  Used by lonmenu.pm and lonroles.pm to determine whether to use the word
 'Courses' or 'Roles' in inline navigation and on screen displaying user's roles.  'Courses' or 'Roles' in inline navigation and on screen displaying user's roles.
   
 Inputs:  Inputs:
 None  None
   
Line 6327  role status: active, previous or future. Line 7240  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';
     my $now = time;      my $now = time;
     if (@uroles > 0) {      if (@uroles > 0) {
         if (($role eq 'cc') || ($sec eq '') || (!defined($sec))) {          if (($role eq 'cc') || ($role eq 'co') || ($sec eq '') || (!defined($sec))) {
             $srchstr = '/'.$cdom.'/'.$crs.'_'.$role;              $srchstr = '/'.$cdom.'/'.$crs.'_'.$role;
         } else {          } else {
             $srchstr = '/'.$cdom.'/'.$crs.'/'.$sec.'_'.$role;              $srchstr = '/'.$cdom.'/'.$crs.'/'.$sec.'_'.$role;
Line 6910  sub get_secgrprole_info { Line 7824  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 6964  sub user_picker { Line 7878  sub user_picker {
         #       loncreateuser::print_user_query_page()          #       loncreateuser::print_user_query_page()
         #       has been completed.          #       has been completed.
         next if ($option eq 'alc');          next if ($option eq 'alc');
         next if (($option eq 'crs') && ($env{'form.form'} eq 'requestcrs'));          next if (($option eq 'crs') && ($env{'form.form'} eq 'requestcrs'));  
         next if ($option eq 'crs' && !$env{'request.course.id'});          next if ($option eq 'crs' && !$env{'request.course.id'});
         if ($curr_selected{'srchin'} eq $option) {          if ($curr_selected{'srchin'} eq $option) {
             $srchinsel .= '               $srchinsel .= ' 
Line 7001  sub user_picker { Line 7915  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 7013  sub user_picker { Line 7932  sub user_picker {
                         official   => 'institutional',                          official   => 'institutional',
                         unofficial => 'non-institutional',                          unofficial => 'non-institutional',
                     );                      );
                     $new_user_create = '<p class="LC_warning">'.                      $new_user_create = '<p class="LC_warning">'
                                        &mt("You are not authorized to create new $usertypetext{$usertype} users in this domain.").' '.                                        .&mt("You are not authorized to create new $usertypetext{$usertype} users in this domain.")
                                        &mt('Please contact the [_1]helpdesk[_2] for assistance.','<a href="'.$helplink.'">','</a>').'</p><br />';                                        .' '
                                         .&mt('Please contact the [_1]helpdesk[_2] for assistance.'
                                             ,'<a href="'.$helplink.'">','</a>')
                                         .'</p><br />';
                 }                  }
             }              }
         }          }
Line 7040  function setSearch(createnew,callingForm Line 7962  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 7134  END_BLOCK Line 8056  END_BLOCK
                &Apache::lonhtmlcommon::row_closure().                 &Apache::lonhtmlcommon::row_closure().
                &Apache::lonhtmlcommon::row_title($lt{'usr'}).                 &Apache::lonhtmlcommon::row_title($lt{'usr'}).
                $srchbysel.                 $srchbysel.
                $srchtypesel.                 $srchtypesel. 
                '<input type="text" size="15" name="srchterm" value="'.$srchterm.'" />'.                 '<input type="text" size="15" name="srchterm" value="'.$srchterm.'" />'.
                $srchinsel.                 $srchinsel.
                &Apache::lonhtmlcommon::row_closure(1).                 &Apache::lonhtmlcommon::row_closure(1)
                &Apache::lonhtmlcommon::end_pick_box().                 &Apache::lonhtmlcommon::end_pick_box().
                '<br />';                 '<br />';
     return $output;      return $output;
Line 7363  sub get_institutional_codes { Line 8285  sub get_institutional_codes {
     return;      return;
 }  }
   
   sub get_standard_codeitems {
       return ('Year','Semester','Department','Number','Section');
   }
   
 =pod  =pod
   
 =head1 Slot Helpers  =head1 Slot Helpers
Line 7371  sub get_institutional_codes { Line 8297  sub get_institutional_codes {
   
 =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 slot start time (earliest first). 
   
 Inputs:  Inputs:
   
Line 7413  sub sorted_slots { Line 8339  sub sorted_slots {
     return @sorted;      return @sorted;
 }  }
   
   
 =pod  =pod
   
 =head1 HTTP Helpers  =head1 HTTP Helpers
Line 7553  sub get_env_multiple { Line 8480  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 7626  sub upload_embedded { Line 8798  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 7645  sub upload_embedded { Line 8817  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 7677  sub upload_embedded { Line 8871  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 7699  sub upload_embedded { Line 8893  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 .= '<font size="+2">'.  
                                    &mt('View embedded file: [_1]','<a href="'.$url.'">'.  
                                    $orig_uploaded_filename.'</a>').'</font><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 7735  sub check_for_existing { Line 9099  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 7768  sub check_for_upload { Line 9183  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;
 }  }
   
   =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 8011  sub csv_print_samples { Line 9573  sub csv_print_samples {
     $r->print(&mt('Samples').'<br />'.&start_data_table().      $r->print(&mt('Samples').'<br />'.&start_data_table().
               &start_data_table_header_row());                &start_data_table_header_row());
     foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {       foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) { 
         $r->print('<th>'.&mt('Column [_1]',($sample+1)).'</th>');          $r->print('<th>'.&mt('Column [_1]',($sample+1)).'</th>'); }
     }  
     $r->print(&end_data_table_header_row());      $r->print(&end_data_table_header_row());
     foreach my $hash (@$samples) {      foreach my $hash (@$samples) {
  $r->print(&start_data_table_row());   $r->print(&start_data_table_row());
Line 8056  sub csv_print_select_table { Line 9617  sub csv_print_select_table {
  my ($value,$display,$defaultcol)=@{ $array_ref };   my ($value,$display,$defaultcol)=@{ $array_ref };
  $r->print(&start_data_table_row().'<td>'.$display.'</td>');   $r->print(&start_data_table_row().'<td>'.$display.'</td>');
   
  $r->print('<td><select name"f'.$i.'"'.   $r->print('<td><select name="f'.$i.'"'.
   ' onchange="javascript:flip(this.form,'.$i.');">');    ' onchange="javascript:flip(this.form,'.$i.');">');
  $r->print('<option value="none"></option>');   $r->print('<option value="none"></option>');
  foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {   foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {
Line 8743  sub build_recipient_list { Line 10304  sub build_recipient_list {
                 my @contacts = ('adminemail','supportemail');                  my @contacts = ('adminemail','supportemail');
                 foreach my $item (@contacts) {                  foreach my $item (@contacts) {
                     if ($domconfig{'contacts'}{$mailing}{$item}) {                      if ($domconfig{'contacts'}{$mailing}{$item}) {
                         my $addr = $domconfig{'contacts'}{$item};                          my $addr = $domconfig{'contacts'}{$item}; 
                         if (!grep(/^\Q$addr\E$/,@recipients)) {                          if (!grep(/^\Q$addr\E$/,@recipients)) {
                             push(@recipients,$addr);                              push(@recipients,$addr);
                         }                          }
Line 8884  sub extract_categories { Line 10445  sub extract_categories {
                 my $trailstr;                  my $trailstr;
                 if ($name eq 'instcode') {                  if ($name eq 'instcode') {
                     $trailstr = &mt('Official courses (with institutional codes)');                      $trailstr = &mt('Official courses (with institutional codes)');
                   } elsif ($name eq 'communities') {
                       $trailstr = &mt('Communities');
                 } else {                  } else {
                     $trailstr = $name;                      $trailstr = $name;
                 }                  }
Line 8996  cathash - reference to hash of categorie Line 10559  cathash - reference to hash of categorie
   
 currcat - scalar with an & separated list of categories assigned to a course.   currcat - scalar with an & separated list of categories assigned to a course. 
   
   type    - scalar contains course type (Course or Community).
   
 Returns: $output (markup to be displayed)   Returns: $output (markup to be displayed) 
   
 =cut  =cut
   
 sub assign_categories_table {  sub assign_categories_table {
     my ($cathash,$currcat) = @_;      my ($cathash,$currcat,$type) = @_;
     my $output;      my $output;
     if (ref($cathash) eq 'HASH') {      if (ref($cathash) eq 'HASH') {
         my (@cats,@trails,%allitems,%idx,@jsarray,@path,$maxdepth);          my (@cats,@trails,%allitems,%idx,@jsarray,@path,$maxdepth);
Line 9010  sub assign_categories_table { Line 10575  sub assign_categories_table {
         if (@cats > 0) {          if (@cats > 0) {
             my $itemcount = 0;              my $itemcount = 0;
             if (ref($cats[0]) eq 'ARRAY') {              if (ref($cats[0]) eq 'ARRAY') {
                 $output = &Apache::loncommon::start_data_table();  
                 my @currcategories;                  my @currcategories;
                 if ($currcat ne '') {                  if ($currcat ne '') {
                     @currcategories = split('&',$currcat);                      @currcategories = split('&',$currcat);
                 }                  }
                   my $table;
                 for (my $i=0; $i<@{$cats[0]}; $i++) {                  for (my $i=0; $i<@{$cats[0]}; $i++) {
                     my $parent = $cats[0][$i];                      my $parent = $cats[0][$i];
                     my $css_class = $itemcount%2?' class="LC_odd_row"':'';  
                     next if ($parent eq 'instcode');                      next if ($parent eq 'instcode');
                       if ($type eq 'Community') {
                           next unless ($parent eq 'communities');
                       } else {
                           next if ($parent eq 'communities');
                       }
                       my $css_class = $itemcount%2?' class="LC_odd_row"':'';
                     my $item = &escape($parent).'::0';                      my $item = &escape($parent).'::0';
                     my $checked = '';                      my $checked = '';
                     if (@currcategories > 0) {                      if (@currcategories > 0) {
                         if (grep(/^\Q$item\E$/,@currcategories)) {                          if (grep(/^\Q$item\E$/,@currcategories)) {
                             $checked = ' checked="checked" ';                              $checked = ' checked="checked"';
                         }                          }
                     }                      }
                     $output .= '<tr '.$css_class.'><td><span class="LC_nobreak">'.                      my $parent_title = $parent;
                                '<input type="checkbox" name="usecategory" value="'.                      if ($parent eq 'communities') {
                                $item.'"'.$checked.' />'.$parent.'</span>'.                          $parent_title = &mt('Communities');
                                '<input type="hidden" name="catname" value="'.$parent.'" /></td>';                      }
                       $table .= '<tr '.$css_class.'><td><span class="LC_nobreak">'.
                                 '<input type="checkbox" name="usecategory" value="'.
                                 $item.'"'.$checked.' />'.$parent_title.'</span>'.
                                 '<input type="hidden" name="catname" value="'.$parent.'" /></td>';
                     my $depth = 1;                      my $depth = 1;
                     push(@path,$parent);                      push(@path,$parent);
                     $output .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories);                      $table .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories);
                     pop(@path);                      pop(@path);
                     $output .= '</tr><tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr>';                      $table .= '</tr><tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr>';
                     $itemcount ++;                      $itemcount ++;
                 }                  }
                 $output .= &Apache::loncommon::end_data_table();                  if ($itemcount) {
                       $output = &Apache::loncommon::start_data_table().
                                 $table.
                                 &Apache::loncommon::end_data_table();
                   }
             }              }
         }          }
     }      }
Line 9089  sub assign_category_rows { Line 10667  sub assign_category_rows {
                     if (ref($currcategories) eq 'ARRAY') {                      if (ref($currcategories) eq 'ARRAY') {
                         if (@{$currcategories} > 0) {                          if (@{$currcategories} > 0) {
                             if (grep(/^\Q$item\E$/,@{$currcategories})) {                              if (grep(/^\Q$item\E$/,@{$currcategories})) {
                                 $checked = ' checked="checked" ';                                  $checked = ' checked="checked"';
                             }                              }
                         }                          }
                     }                      }
Line 9282  sub check_clone { Line 10860  sub check_clone {
     my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);      my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
     my $clonemsg;      my $clonemsg;
     my $can_clone = 0;      my $can_clone = 0;
       my $lctype = lc($args->{'crstype'});
       if ($lctype ne 'community') {
           $lctype = 'course';
       }
     if ($clonehome eq 'no_host') {      if ($clonehome eq 'no_host') {
         $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});               if ($args->{'crstype'} eq 'Community') {
               $clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a non-existent community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
           } else {
               $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
           }     
     } else {      } else {
  my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1});   my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1});
         if (($env{'request.role.domain'} eq $args->{'clonedomain'}) &&           if ($args->{'crstype'} eq 'Community') {
               if ($clonedesc{'type'} ne 'Community') {
                    $clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a course not a community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
                   return ($can_clone, $clonemsg, $cloneid, $clonehome);
               }
           }
    if (($env{'request.role.domain'} eq $args->{'clonedomain'}) && 
             (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'}))) {              (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'}))) {
      $can_clone = 1;      $can_clone = 1;
  } else {   } else {
     my %clonehash = &Apache::lonnet::get('environment',['cloners'],      my %clonehash = &Apache::lonnet::get('environment',['cloners'],
  $args->{'clonedomain'},$args->{'clonecourse'});   $args->{'clonedomain'},$args->{'clonecourse'});
Line 9299  sub check_clone { Line 10890  sub check_clone {
             } elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) {              } elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) {
                 $can_clone = 1;                  $can_clone = 1;
             } else {              } else {
                   my $ccrole = 'cc';
                   if ($args->{'crstype'} eq 'Community') {
                       $ccrole = 'co';
                   }
         my %roleshash =          my %roleshash =
     &Apache::lonnet::get_my_roles($args->{'ccuname'},      &Apache::lonnet::get_my_roles($args->{'ccuname'},
  $args->{'ccdomain'},   $args->{'ccdomain'},
                                          'userroles',['active'],['cc'],                                           'userroles',['active'],[$ccrole],
  [$args->{'clonedomain'}]);   [$args->{'clonedomain'}]);
         if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':cc'}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {          if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':'.$ccrole}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
     $can_clone = 1;                      $can_clone = 1;
         } else {                  } elsif (&Apache::lonnet::is_course_owner($args->{'clonedomain'},$args->{'clonecourse'},$args->{'ccuname'},$args->{'ccdomain'})) {
                     $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});                      $can_clone = 1;
                   } else {
                       if ($args->{'crstype'} eq 'Community') {
                           $clonemsg = &mt('No new community created.').$linefeed.&mt('The new community could not be cloned from the existing community because the new community owner ([_1]) does not have cloning rights in the existing community ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
                       } else {
                           $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
                       }
         }          }
     }      }
         }          }
Line 9357  sub construct_course { Line 10958  sub construct_course {
                                              $args->{'crstype'},                                               $args->{'crstype'},
                                              $cnum,$context,$category);                                               $cnum,$context,$category);
   
   
     # Note: The testing routines depend on this being output; see       # Note: The testing routines depend on this being output; see 
     # Utils::Course. This needs to at least be output as a comment      # Utils::Course. This needs to at least be output as a comment
     # if anyone ever decides to not show this, and Utils::Course::new      # if anyone ever decides to not show this, and Utils::Course::new
     # will need to be suitably modified.      # will need to be suitably modified.
     $outcome .= &mt('New LON-CAPA [_1] ID: [_2]',$crstype,$$courseid).$linefeed;      $outcome .= &mt('New LON-CAPA [_1] ID: [_2]',$crstype,$$courseid).$linefeed;
       if ($$courseid =~ /^error:/) {
           return (0,$outcome);
       }
   
 #  #
 # Check if created correctly  # Check if created correctly
 #  #
     ($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid);      ($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid);
     my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);      my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);
       if ($crsuhome eq 'no_host') {
           $outcome .= &mt('Course creation failed, unrecognized course home server.').$linefeed;
           return (0,$outcome);
       }
     $outcome .= &mt('Created on').': '.$crsuhome.$linefeed;      $outcome .= &mt('Created on').': '.$crsuhome.$linefeed;
   
 #  #
Line 9386  sub construct_course { Line 10994  sub construct_course {
  $cenv{'url'}=$oldcenv{'url'};   $cenv{'url'}=$oldcenv{'url'};
 # Restore title  # Restore title
  $cenv{'description'}=$oldcenv{'description'};   $cenv{'description'}=$oldcenv{'description'};
   # Restore creation date, creator and creation context.
           $cenv{'internal.created'}=$oldcenv{'internal.created'};
           $cenv{'internal.creator'}=$oldcenv{'internal.creator'};
           $cenv{'internal.creationcontext'}=$oldcenv{'internal.creationcontext'};
 # Mark as cloned  # Mark as cloned
  $cenv{'clonedfrom'}=$cloneid;   $cenv{'clonedfrom'}=$cloneid;
 # Need to clone grading mode  # Need to clone grading mode
Line 9632  sub construct_course { Line 11244  sub construct_course {
     $title=&mt('Syllabus');      $title=&mt('Syllabus');
             $url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus';              $url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus';
         } else {          } else {
             $title=&mt('Navigate Contents');              $title=&mt('Table of Contents');
             $url='/adm/navmaps';              $url='/adm/navmaps';
         }          }
   
Line 9649  sub construct_course { Line 11261  sub construct_course {
 ############################################################  ############################################################
 ############################################################  ############################################################
   
   #SD
   # only Community and Course, or anything else?
 sub course_type {  sub course_type {
     my ($cid) = @_;      my ($cid) = @_;
     if (!defined($cid)) {      if (!defined($cid)) {
Line 9664  sub course_type { Line 11278  sub course_type {
 sub group_term {  sub group_term {
     my $crstype = &course_type();      my $crstype = &course_type();
     my %names = (      my %names = (
                   'Course'    => 'group',                    'Course' => 'group',
                   'Community' => 'group',                    'Community' => 'group',
                 );                  );
     return $names{$crstype};      return $names{$crstype};
 }  }
   
   sub course_types {
       my @types = ('official','unofficial','community');
       my %typename = (
                            official   => 'Official course',
                            unofficial => 'Unofficial course',
                            community  => 'Community',
                      );
       return (\@types,\%typename);
   }
   
 sub icon {  sub icon {
     my ($file)=@_;      my ($file)=@_;
     my $curfext = lc((split(/\./,$file))[-1]);      my $curfext = lc((split(/\./,$file))[-1]);
Line 9745  sub compare_arrays { Line 11369  sub compare_arrays {
     return @difference;      return @difference;
 }  }
   
 # -------------------------------------------------------- Initliaze user login  # -------------------------------------------------------- Initialize user login
 sub init_user_environment {  sub init_user_environment {
     my ($r, $username, $domain, $authhost, $form, $args) = @_;      my ($r, $username, $domain, $authhost, $form, $args) = @_;
     my $lonids=$Apache::lonnet::perlvar{'lonIDsDir'};      my $lonids=$Apache::lonnet::perlvar{'lonIDsDir'};
Line 9799  sub init_user_environment { Line 11423  sub init_user_environment {
     my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,      my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
         $clientunicode,$clientos) = &decode_user_agent($r);          $clientunicode,$clientos) = &decode_user_agent($r);
   
 # -------------------------------------- Any accessibility options to remember?  
     if (($form->{'interface'}) && ($form->{'remember'} eq 'true')) {  
  foreach my $option ('imagesuppress','appletsuppress',  
     'embedsuppress','fontenhance','blackwhite') {  
     if ($form->{$option} eq 'true') {  
  &Apache::lonnet::put('environment',{$option => 'on'},  
      $domain,$username);  
     } else {  
  &Apache::lonnet::del('environment',[$option],  
      $domain,$username);  
     }  
  }  
     }  
 # ------------------------------------------------------------- Get environment  # ------------------------------------------------------------- Get environment
   
     my %userenv = &Apache::lonnet::dump('environment',$domain,$username);      my %userenv = &Apache::lonnet::dump('environment',$domain,$username);
     my ($tmp) = keys(%userenv);      my ($tmp) = keys(%userenv);
     if ($tmp !~ /^(con_lost|error|no_such_host)/i) {      if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
  # default remote control to off  
  if ($userenv{'remote'} ne 'on') { $userenv{'remote'} = 'off'; }  
     } else {      } else {
  undef(%userenv);   undef(%userenv);
     }      }
     if (($userenv{'interface'}) && (!$form->{'interface'})) {      if (($userenv{'interface'}) && (!$form->{'interface'})) {
  $form->{'interface'}=$userenv{'interface'};   $form->{'interface'}=$userenv{'interface'};
     }      }
     $env{'environment.remote'}=$userenv{'remote'};  
     if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; }      if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; }
   
 # --------------- Do not trust query string to be put directly into environment  # --------------- Do not trust query string to be put directly into environment
     foreach my $option ('imagesuppress','appletsuppress',      foreach my $option ('interface','localpath','localres') {
  'embedsuppress','fontenhance','blackwhite',          $form->{$option}=~s/[\n\r\=]//gs;
  'interface','localpath','localres') {  
  $form->{$option}=~s/[\n\r\=]//gs;  
     }      }
 # --------------------------------------------------------- Write first profile  # --------------------------------------------------------- Write first profile
   
Line 9859  sub init_user_environment { Line 11465  sub init_user_environment {
     $initial_env{"browser.localres"}   = $form->{'localres'};      $initial_env{"browser.localres"}   = $form->{'localres'};
         }          }
   
  if ($public) {  
     $initial_env{"environment.remote"} = "off";  
  }  
  if ($form->{'interface'}) {   if ($form->{'interface'}) {
     $form->{'interface'}=~s/\W//gs;      $form->{'interface'}=~s/\W//gs;
     $initial_env{"browser.interface"} = $form->{'interface'};      $initial_env{"browser.interface"} = $form->{'interface'};
     $env{'browser.interface'}=$form->{'interface'};      $env{'browser.interface'}=$form->{'interface'};
     foreach my $option ('imagesuppress','appletsuppress',  
  'embedsuppress','fontenhance','blackwhite') {  
  if (($form->{$option} eq 'true') ||  
     ($userenv{$option} eq 'on')) {  
     $initial_env{"browser.$option"} = "on";  
  }  
     }  
  }   }
   
           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 9898  sub init_user_environment { Line 11502  sub init_user_environment {
     }      }
     untie(%disk_env);      untie(%disk_env);
  } else {   } else {
     &Apache::lonnet::logthis("<font color=\"blue\">WARNING: ".      &Apache::lonnet::logthis("<span style=\"color:blue;\">WARNING: ".
    'Could not create environment storage in lonauth: '.$!.'</font>');     'Could not create environment storage in lonauth: '.$!.'</span>');
     return 'error: '.$!;      return 'error: '.$!;
  }   }
     }      }
Line 9962  sub clean_symb { Line 11566  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.692.4.15  
changed lines
  Added in v.1.1028.2.1


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