Diff for /loncom/interface/loncommon.pm between versions 1.1075.2.127.2.7 and 1.1222

version 1.1075.2.127.2.7, 2019/02/06 16:10:34 version 1.1222, 2015/06/09 21:22:56
Line 72  use Apache::lonuserstate(); Line 72  use Apache::lonuserstate();
 use Apache::courseclassifier();  use Apache::courseclassifier();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale;  use DateTime::Locale::Catalog;
 use Encode();  use Encode();
   use Text::Aspell;
 use Authen::Captcha;  use Authen::Captcha;
 use Captcha::reCAPTCHA;  use Captcha::reCAPTCHA;
 use JSON::DWIW;  
 use LWP::UserAgent;  
 use Crypt::DES;  use Crypt::DES;
 use DynaLoader; # for Crypt::DES version  use DynaLoader; # for Crypt::DES version
 use File::Copy();  
 use File::Path();  
 use String::CRC32();  
 use Short::URL();  
   
 # ---------------------------------------------- Designs  # ---------------------------------------------- Designs
 use vars qw(%defaultdesign);  use vars qw(%defaultdesign);
Line 168  sub ssi_with_retries { Line 163  sub ssi_with_retries {
 # ----------------------------------------------- Filetypes/Languages/Copyright  # ----------------------------------------------- Filetypes/Languages/Copyright
 my %language;  my %language;
 my %supported_language;  my %supported_language;
   my %supported_codes;
 my %latex_language; # For choosing hyphenation in <transl..>  my %latex_language; # For choosing hyphenation in <transl..>
 my %latex_language_bykey; # for choosing hyphenation from metadata  my %latex_language_bykey; # for choosing hyphenation from metadata
 my %cprtag;  my %cprtag;
Line 198  BEGIN { Line 194  BEGIN {
     {      {
         my $langtabfile = $Apache::lonnet::perlvar{'lonTabDir'}.          my $langtabfile = $Apache::lonnet::perlvar{'lonTabDir'}.
                                    '/language.tab';                                     '/language.tab';
         if ( open(my $fh,'<',$langtabfile) ) {          if ( open(my $fh,"<$langtabfile") ) {
             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,$latex)=(split(/\t/,$line));                  my ($key,$code,$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;
       $supported_codes{$key}   = $code;
                 }                  }
  if ($latex) {   if ($latex) {
     $latex_language_bykey{$key} = $latex;      $latex_language_bykey{$key} = $latex;
     $latex_language{$two} = $latex;      $latex_language{$code} = $latex;
  }   }
             }              }
             close($fh);              close($fh);
Line 219  BEGIN { Line 216  BEGIN {
     {      {
         my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.          my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
                                   '/copyright.tab';                                    '/copyright.tab';
         if ( open (my $fh,'<',$copyrightfile) ) {          if ( open (my $fh,"<$copyrightfile") ) {
             while (my $line = <$fh>) {              while (my $line = <$fh>) {
                 next if ($line=~/^\#/);                  next if ($line=~/^\#/);
                 chomp($line);                  chomp($line);
Line 233  BEGIN { Line 230  BEGIN {
     {      {
         my $sourcecopyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.          my $sourcecopyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
                                   '/source_copyright.tab';                                    '/source_copyright.tab';
         if ( open (my $fh,'<',$sourcecopyrightfile) ) {          if ( open (my $fh,"<$sourcecopyrightfile") ) {
             while (my $line = <$fh>) {              while (my $line = <$fh>) {
                 next if ($line =~ /^\#/);                  next if ($line =~ /^\#/);
                 chomp($line);                  chomp($line);
Line 247  BEGIN { Line 244  BEGIN {
 # -------------------------------------------------------------- default domain designs  # -------------------------------------------------------------- default domain designs
     my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';      my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
     my $designfile = $designdir.'/default.tab';      my $designfile = $designdir.'/default.tab';
     if ( open (my $fh,'<',$designfile) ) {      if ( open (my $fh,"<$designfile") ) {
         while (my $line = <$fh>) {          while (my $line = <$fh>) {
             next if ($line =~ /^\#/);              next if ($line =~ /^\#/);
             chomp($line);              chomp($line);
Line 261  BEGIN { Line 258  BEGIN {
     {      {
         my $categoryfile = $Apache::lonnet::perlvar{'lonTabDir'}.          my $categoryfile = $Apache::lonnet::perlvar{'lonTabDir'}.
                                   '/filecategories.tab';                                    '/filecategories.tab';
         if ( open (my $fh,'<',$categoryfile) ) {          if ( open (my $fh,"<$categoryfile") ) {
     while (my $line = <$fh>) {      while (my $line = <$fh>) {
  next if ($line =~ /^\#/);   next if ($line =~ /^\#/);
  chomp($line);   chomp($line);
                 my ($extension,$category)=(split(/\s+/,$line,2));                  my ($extension,$category)=(split(/\s+/,$line,2));
                 push(@{$category_extensions{lc($category)}},$extension);                  push @{$category_extensions{lc($category)}},$extension;
             }              }
             close($fh);              close($fh);
         }          }
Line 276  BEGIN { Line 273  BEGIN {
     {      {
         my $typesfile = $Apache::lonnet::perlvar{'lonTabDir'}.          my $typesfile = $Apache::lonnet::perlvar{'lonTabDir'}.
                '/filetypes.tab';                 '/filetypes.tab';
         if ( open (my $fh,'<',$typesfile) ) {          if ( open (my $fh,"<$typesfile") ) {
             while (my $line = <$fh>) {              while (my $line = <$fh>) {
  next if ($line =~ /^\#/);   next if ($line =~ /^\#/);
  chomp($line);   chomp($line);
Line 589  sub coursebrowser_javascript { Line 586  sub coursebrowser_javascript {
         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;
             url += '&cloner='+ownername+':'+ownerdom;              url += '&cloner='+ownername+':'+ownerdom+'&crscode='+document.forms[formid].crscode.value;
             if (type == 'Course') {  
                 url += '&crscode='+document.forms[formid].crscode.value;  
             }  
         }          }
         if (formname == 'requestcrs') {          if (formname == 'requestcrs') {
             url += '&crsdom=$domainfilter&crscode=$instcode';              url += '&crsdom=$domainfilter&crscode=$instcode';
Line 679  if (!Array.prototype.indexOf) { Line 673  if (!Array.prototype.indexOf) {
         var n = 0;          var n = 0;
         if (arguments.length > 0) {          if (arguments.length > 0) {
             n = Number(arguments[1]);              n = Number(arguments[1]);
             if (n !== n) { // shortcut for verifying if it's NaN              if (n !== n) { // shortcut for verifying if it is NaN
                 n = 0;                  n = 0;
             } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {              } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
                 n = (n > 0 || -1) * Math.floor(Math.abs(n));                  n = (n > 0 || -1) * Math.floor(Math.abs(n));
Line 915  sub check_uncheck_jscript { Line 909  sub check_uncheck_jscript {
 function checkAll(field) {  function checkAll(field) {
     if (field.length > 0) {      if (field.length > 0) {
         for (i = 0; i < field.length; i++) {          for (i = 0; i < field.length; i++) {
             if (!field[i].disabled) {              if (!field[i].disabled) { 
                 field[i].checked = true;                  field[i].checked = true;
             }              }
         }          }
     } else {      } else {
         if (!field.disabled) {          if (!field.disabled) { 
             field.checked = true;              field.checked = true;
         }          }
     }      }
Line 940  ENDSCRT Line 934  ENDSCRT
 }  }
   
 sub select_timezone {  sub select_timezone {
    my ($name,$selected,$onchange,$includeempty,$disabled)=@_;     my ($name,$selected,$onchange,$includeempty)=@_;
    my $output='<select name="'.$name.'" '.$onchange.$disabled.'>'."\n";     my $output='<select name="'.$name.'" '.$onchange.'>'."\n";
    if ($includeempty) {     if ($includeempty) {
        $output .= '<option value=""';         $output .= '<option value=""';
        if (($selected eq '') || ($selected eq 'local')) {         if (($selected eq '') || ($selected eq 'local')) {
Line 962  sub select_timezone { Line 956  sub select_timezone {
 }  }
   
 sub select_datelocale {  sub select_datelocale {
     my ($name,$selected,$onchange,$includeempty,$disabled)=@_;      my ($name,$selected,$onchange,$includeempty)=@_;
     my $output='<select name="'.$name.'" '.$onchange.$disabled.'>'."\n";      my $output='<select name="'.$name.'" '.$onchange.'>'."\n";
     if ($includeempty) {      if ($includeempty) {
         $output .= '<option value=""';          $output .= '<option value=""';
         if ($selected eq '') {          if ($selected eq '') {
Line 971  sub select_datelocale { Line 965  sub select_datelocale {
         }          }
         $output .= '> </option>';          $output .= '> </option>';
     }      }
     my @languages = &Apache::lonlocal::preferred_languages();  
     my (@possibles,%locale_names);      my (@possibles,%locale_names);
     my @locales = DateTime::Locale->ids();      my @locales = DateTime::Locale::Catalog::Locales;
     foreach my $id (@locales) {      foreach my $locale (@locales) {
         if ($id ne '') {          if (ref($locale) eq 'HASH') {
             my ($en_terr,$native_terr);              my $id = $locale->{'id'};
             my $loc = DateTime::Locale->load($id);              if ($id ne '') {
             if (ref($loc)) {                  my $en_terr = $locale->{'en_territory'};
                 $en_terr = $loc->name();                  my $native_terr = $locale->{'native_territory'};
                 $native_terr = $loc->native_name();                  my @languages = &Apache::lonlocal::preferred_languages();
                 if (grep(/^en$/,@languages) || !@languages) {                  if (grep(/^en$/,@languages) || !@languages) {
                     if ($en_terr ne '') {                      if ($en_terr ne '') {
                         $locale_names{$id} = '('.$en_terr.')';                          $locale_names{$id} = '('.$en_terr.')';
Line 995  sub select_datelocale { Line 988  sub select_datelocale {
                     }                      }
                 }                  }
                 $locale_names{$id} = Encode::encode('UTF-8',$locale_names{$id});                  $locale_names{$id} = Encode::encode('UTF-8',$locale_names{$id});
                 push(@possibles,$id);                  push (@possibles,$id);
             }              }
         }          }
     }      }
Line 1015  sub select_datelocale { Line 1008  sub select_datelocale {
 }  }
   
 sub select_language {  sub select_language {
     my ($name,$selected,$includeempty,$noedit) = @_;      my ($name,$selected,$includeempty) = @_;
     my %langchoices;      my %langchoices;
     if ($includeempty) {      if ($includeempty) {
         %langchoices = ('' => 'No language preference');          %langchoices = ('' => 'No language preference');
Line 1027  sub select_language { Line 1020  sub select_language {
         }          }
     }      }
     %langchoices = &Apache::lonlocal::texthash(%langchoices);      %langchoices = &Apache::lonlocal::texthash(%langchoices);
     return &select_form($selected,$name,\%langchoices,undef,$noedit);      return &select_form($selected,$name,\%langchoices);
   }
   
   =pod
   
   
   =item * &list_languages()
   
   Returns an array reference that is suitable for use in language prompters.
   Each array element is itself a two element array.  The first element
   is the language code.  The second element a descsriptiuon of the 
   language itself.  This is suitable for use in e.g.
   &Apache::edit::select_arg (once dereferenced that is).
   
   =cut 
   
   sub list_languages {
       my @lang_choices;
   
       foreach my $id (&languageids()) {
    my $code = &supportedlanguagecode($id);
    if ($code) {
       my $selector    = $supported_codes{$id};
       my $description = &plainlanguagedescription($id);
       push (@lang_choices, [$selector, $description]);
    }
       }
       return \@lang_choices;
 }  }
   
 =pod  =pod
Line 1142  sub linked_select_forms { Line 1162  sub linked_select_forms {
         $result.="select2data.d_$s1.texts = new Array(";                  $result.="select2data.d_$s1.texts = new Array(";        
         my @s2texts;          my @s2texts;
         foreach my $value (@s2values) {          foreach my $value (@s2values) {
             push(@s2texts, $hashref->{$s1}->{'select2'}->{$value});              push @s2texts, $hashref->{$s1}->{'select2'}->{$value};
         }          }
         $result.="\"@s2texts\");\n";          $result.="\"@s2texts\");\n";
     }      }
Line 1252  sub help_open_topic { Line 1272  sub help_open_topic {
     $topic=~s/\W/\_/g;      $topic=~s/\W/\_/g;
   
     if (!$stayOnPage) {      if (!$stayOnPage) {
         if ($env{'browser.mobile'}) {   $link = "javascript:openMyModal('/adm/help/${filename}.hlp',$width,$height,'yes');";
     $link = "javascript:openMyModal('/adm/help/${filename}.hlp',$width,$height,'yes');";  
         } else {  
             $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";  
         }  
     } elsif ($stayOnPage eq 'popup') {      } elsif ($stayOnPage eq 'popup') {
         $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";          $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
     } else {      } else {
Line 1305  sub helpLatexCheatsheet { Line 1321  sub helpLatexCheatsheet {
   .&help_open_topic('Other_Symbols',&mt('Other Symbols'),$stayOnPage,undef,600)    .&help_open_topic('Other_Symbols',&mt('Other Symbols'),$stayOnPage,undef,600)
   .'</span>';    .'</span>';
     unless ($not_author) {      unless ($not_author) {
         $out .= ' <span>'          $out .= '<span>'
        .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600)                 .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600)
        .'</span> <span>'                 .'</span> <span>'
                .&help_open_topic('Authoring_Multilingual_Problems',&mt('Languages'),$stayOnPage,undef,600)                 .&help_open_topic('Authoring_Multilingual_Problems',&mt('How to create problems in different languages'),$stayOnPage,undef,600)
                .'</span>';         .'</span>';
     }      }
     $out .= '</span>'; # End cheatsheet      $out .= '</span>'; # End cheatsheet
     return $out;      return $out;
Line 1372  sub help_open_menu { Line 1388  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;
     unless ($env{'environment.remote'} eq 'on') {  
         $stay_on_page = 1;  
     }  
     my ($link,$banner_link);      my ($link,$banner_link);
     unless ($env{'request.noversionuri'} =~ m{^/adm/helpmenu}) {      unless ($env{'request.noversionuri'} =~ m{^/adm/helpmenu}) {
         $link = ($stay_on_page) ? "javascript:helpMenu('display')"          $link = ($stay_on_page) ? "javascript:helpMenu('display')"
Line 1405  sub help_menu_js { Line 1419  sub help_menu_js {
         &Apache::loncommon::start_page('Help Menu', undef,          &Apache::loncommon::start_page('Help Menu', undef,
        {'frameset'    => 1,         {'frameset'    => 1,
  'js_ready'    => 1,   'js_ready'    => 1,
                                         'use_absolute' => $httphost,                                           'use_absolute' => $httphost,
  'add_entries' => {   'add_entries' => {
     'border' => '0',      'border' => '0', 
     'rows'   => "110,*",},});      'rows'   => "110,*",},});
     my $end_page =      my $end_page =
         &Apache::loncommon::end_page({'frameset' => 1,          &Apache::loncommon::end_page({'frameset' => 1,
Line 1794  sub colorfuleditor_js { Line 1808  sub colorfuleditor_js {
             }              }
   
             // only iterate whole storage if nothing to override              // only iterate whole storage if nothing to override
             if(localStorage.getItem(key) == null){              if(localStorage.getItem(key) == null){        
   
                 // prevent storage from growing large                  // prevent storage from growing large
                 if(localStorage.length > 50){                  if(localStorage.length > 50){
                     var regex_getTimestamp = /^(?:\d)+;/;                      var regex_getTimestamp = /^(?:\d)+;/;
                     var oldest_timestamp = regex_getTimestamp.exec(localStorage.key(0));                      var oldest_timestamp = regex_getTimestamp.exec(localStorage.key(0));
                     var oldest_key;                      var oldest_key;
                       
                     for(var i = 1; i < localStorage.length; i++){                      for(var i = 1; i < localStorage.length; i++){
                         if (regex_getTimestamp.exec(localStorage.key(i)) < oldest_timestamp) {                          if (regex_getTimestamp.exec(localStorage.key(i)) < oldest_timestamp) {
                             oldest_key = localStorage.key(i);                              oldest_key = localStorage.key(i);
Line 1831  sub colorfuleditor_js { Line 1845  sub colorfuleditor_js {
                 pairs = valueArr[i].split(',');                  pairs = valueArr[i].split(',');
                 elements = document.getElementsByName(pairs[0]);                  elements = document.getElementsByName(pairs[0]);
   
                 for (var j = 0; j < elements.length; j++){                  for (var j = 0; j < elements.length; j++){  
                     elements[j].style.display = pairs[1];                      elements[j].style.display = pairs[1];
                     if (pairs[1] == "none"){                      if (pairs[1] == "none"){
                         var regex_id = /([_\\d]+)\$/;                          var regex_id = /([_\\d]+)\$/;
Line 1844  sub colorfuleditor_js { Line 1858  sub colorfuleditor_js {
     }      }
   
     function getTagList () {      function getTagList () {
           
         var stringToSearch = document.lonhomework.innerHTML;          var stringToSearch = document.lonhomework.innerHTML;
   
         var ret = new Array();          var ret = new Array();
Line 1852  sub colorfuleditor_js { Line 1866  sub colorfuleditor_js {
         var tag_list = stringToSearch.match(regex_findBlock);          var tag_list = stringToSearch.match(regex_findBlock);
   
         if(tag_list != null){          if(tag_list != null){
             for(var i = 0; i < tag_list.length; i++){              for(var i = 0; i < tag_list.length; i++){            
                 ret.push(tag_list[i].replace(/"/, ''));                  ret.push(tag_list[i].replace(/"/, ''));
             }              }
         }          }
Line 1889  sub colorfuleditor_js { Line 1903  sub colorfuleditor_js {
   
             for(var i = 0; i < tag_list.length; i++){              for(var i = 0; i < tag_list.length; i++){
                 elem_list = document.getElementsByName(tag_list[i]);                  elem_list = document.getElementsByName(tag_list[i]);
                   
                 if(elem_list.length > 0){                  if(elem_list.length > 0){
                     elem = elem_list[0];                      elem = elem_list[0];
                     break;                      break;
Line 1912  sub colorfuleditor_js { Line 1926  sub colorfuleditor_js {
             rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */              rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
         );          );
     }      }
       
     function autosize(depth){      function autosize(depth){
         var cmInst = window['cm'+depth];          var cmInst = window['cm'+depth];
         var fitsizeButton = document.getElementById('fitsize'+depth);          var fitsizeButton = document.getElementById('fitsize'+depth);
Line 1979  sub insert_folding_button { Line 1993  sub insert_folding_button {
     my $curDepth = $Apache::lonxml::curdepth;      my $curDepth = $Apache::lonxml::curdepth;
     my $lastresource = $env{'request.ambiguous'};      my $lastresource = $env{'request.ambiguous'};
   
     return "<input type=\"button\" id=\"folding_btn_$curDepth\"      return "<input type=\"button\" id=\"folding_btn_$curDepth\" 
             value=\"".&mt('Hide')."\" onclick=\"fold_box('$curDepth','$lastresource')\">";              value=\"".&mt('Hide')."\" onclick=\"fold_box('$curDepth','$lastresource')\">";
 }  }
   
   
 =pod  =pod
   
 =head1 Excel and CSV file utility routines  =head1 Excel and CSV file utility routines
Line 2243  sub multiple_select_form { Line 2256  sub multiple_select_form {
   
 =pod  =pod
   
 =item * &select_form($defdom,$name,$hashref,$onchange,$readonly)  =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 ref to a hash containing:  allow a user to select options from a ref to a hash containing:
 option_name => displayed text. An optional $onchange can include  option_name => displayed text. An optional $onchange can include
 a javascript onchange item, e.g., onchange="this.form.submit();".  a javascript onchange item, e.g., onchange="this.form.submit();"  
 An optional arg -- $readonly -- if true will cause the select form  
 to be disabled, e.g., for the case where an instructor has a section-  
 specific role, and is viewing/modifying parameters.    
   
 See lonrights.pm for an example invocation and use.  See lonrights.pm for an example invocation and use.
   
Line 2259  See lonrights.pm for an example invocati Line 2269  See lonrights.pm for an example invocati
   
 #-------------------------------------------  #-------------------------------------------
 sub select_form {  sub select_form {
     my ($def,$name,$hashref,$onchange,$readonly) = @_;      my ($def,$name,$hashref,$onchange) = @_;
     return unless (ref($hashref) eq 'HASH');      return unless (ref($hashref) eq 'HASH');
     if ($onchange) {      if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';          $onchange = ' onchange="'.$onchange.'"';
Line 2433  sub select_level_form { Line 2443  sub select_level_form {
   
 =pod  =pod
   
 =item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms,$disabled)  =item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms)
   
 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 2450  The optional $incdoms is a reference to Line 2460  The optional $incdoms is a reference to
   
 The optional $excdoms is a reference to an array of domains which will be excluded from the available options.  The optional $excdoms is a reference to an array of domains which will be excluded from the available options.
   
 The optional $disabled argument, if true, adds the disabled attribute to the select tag.   
   
 =cut  =cut
   
 #-------------------------------------------  #-------------------------------------------
 sub select_dom_form {  sub select_dom_form {
     my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms,$disabled) = @_;      my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms) = @_;
     if ($onchange) {      if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';          $onchange = ' onchange="'.$onchange.'"';
     }      }
     if ($disabled) {  
         $disabled = ' disabled="disabled"';  
     }  
     my (@domains,%exclude);      my (@domains,%exclude);
     if (ref($incdoms) eq 'ARRAY') {      if (ref($incdoms) eq 'ARRAY') {
         @domains = sort {lc($a) cmp lc($b)} (@{$incdoms});          @domains = sort {lc($a) cmp lc($b)} (@{$incdoms});
Line 2471  sub select_dom_form { Line 2476  sub select_dom_form {
     }      }
     if ($includeempty) { @domains=('',@domains); }      if ($includeempty) { @domains=('',@domains); }
     if (ref($excdoms) eq 'ARRAY') {      if (ref($excdoms) eq 'ARRAY') {
         map { $exclude{$_} = 1; } @{$excdoms};          map { $exclude{$_} = 1; } @{$excdoms}; 
     }      }
     my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange$disabled>\n";      my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange>\n";
     foreach my $dom (@domains) {      foreach my $dom (@domains) {
         next if ($exclude{$dom});          next if ($exclude{$dom});
         $selectdomain.="<option value=\"$dom\" ".          $selectdomain.="<option value=\"$dom\" ".
Line 2827  sub authform_nochange { Line 2832  sub authform_nochange {
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
           );            );
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});       my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
     my $result;      my $result;
     if (!$authnum) {      if (!$authnum) {
         $result = &mt('Under your current role you are not permitted to change login settings for this user');          $result = &mt('Under your current role you are not permitted to change login settings for this user');
Line 2849  sub authform_kerberos { Line 2854  sub authform_kerberos {
               @_,                @_,
               );                );
     my ($check4,$check5,$krbcheck,$krbarg,$krbver,$result,$authtype,      my ($check4,$check5,$krbcheck,$krbarg,$krbver,$result,$authtype,
         $autharg,$jscall,$disabled);          $autharg,$jscall);
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});      my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
     if ($in{'kerb_def_auth'} eq 'krb5') {      if ($in{'kerb_def_auth'} eq 'krb5') {
        $check5 = ' checked="checked"';         $check5 = ' checked="checked"';
     } else {      } else {
        $check4 = ' checked="checked"';         $check4 = ' checked="checked"';
     }      }
     if ($in{'readonly'}) {  
         $disabled = ' disabled="disabled"';  
     }  
     $krbarg = $in{'kerb_def_dom'};      $krbarg = $in{'kerb_def_dom'};
     if (defined($in{'curr_authtype'})) {      if (defined($in{'curr_authtype'})) {
         if ($in{'curr_authtype'} eq 'krb') {          if ($in{'curr_authtype'} eq 'krb') {
Line 2903  sub authform_kerberos { Line 2905  sub authform_kerberos {
         if (defined($in{'mode'})) {          if (defined($in{'mode'})) {
             if ($in{'mode'} eq 'modifycourse') {              if ($in{'mode'} eq 'modifycourse') {
                 if ($authnum == 1) {                  if ($authnum == 1) {
                     $authtype = '<input type="radio" name="login" value="krb"'.$disabled.' />';                      $authtype = '<input type="radio" name="login" value="krb" />';
                 }                  }
             }              }
         }          }
Line 2912  sub authform_kerberos { Line 2914  sub authform_kerberos {
     if ($authtype eq '') {      if ($authtype eq '') {
         $authtype = '<input type="radio" name="login" value="krb" '.          $authtype = '<input type="radio" name="login" value="krb" '.
                     'onclick="'.$jscall.'" onchange="'.$jscall.'"'.                      'onclick="'.$jscall.'" onchange="'.$jscall.'"'.
                     $krbcheck.$disabled.' />';                      $krbcheck.' />';
     }      }
     if (($can_assign{'krb4'} && $can_assign{'krb5'}) ||      if (($can_assign{'krb4'} && $can_assign{'krb5'}) ||
         ($can_assign{'krb4'} && !$can_assign{'krb5'} &&          ($can_assign{'krb4'} && !$can_assign{'krb5'} &&
Line 2925  sub authform_kerberos { Line 2927  sub authform_kerberos {
          '<label>'.$authtype,           '<label>'.$authtype,
          '</label><input type="text" size="10" name="krbarg" '.           '</label><input type="text" size="10" name="krbarg" '.
              'value="'.$krbarg.'" '.               'value="'.$krbarg.'" '.
              'onchange="'.$jscall.'"'.$disabled.' />',               'onchange="'.$jscall.'" />',
          '<label><input type="radio" name="krbver" value="4" '.$check4.$disabled.' />',           '<label><input type="radio" name="krbver" value="4" '.$check4.' />',
          '</label><label><input type="radio" name="krbver" value="5" '.$check5.$disabled.' />',           '</label><label><input type="radio" name="krbver" value="5" '.$check5.' />',
  '</label>');   '</label>');
     } elsif ($can_assign{'krb4'}) {      } elsif ($can_assign{'krb4'}) {
         $result .= &mt          $result .= &mt
Line 2936  sub authform_kerberos { Line 2938  sub authform_kerberos {
          '<label>'.$authtype,           '<label>'.$authtype,
          '</label><input type="text" size="10" name="krbarg" '.           '</label><input type="text" size="10" name="krbarg" '.
              'value="'.$krbarg.'" '.               'value="'.$krbarg.'" '.
              'onchange="'.$jscall.'"'.$disabled.' />',               'onchange="'.$jscall.'" />',
          '<label><input type="hidden" name="krbver" value="4" />',           '<label><input type="hidden" name="krbver" value="4" />',
          '</label>');           '</label>');
     } elsif ($can_assign{'krb5'}) {      } elsif ($can_assign{'krb5'}) {
Line 2946  sub authform_kerberos { Line 2948  sub authform_kerberos {
          '<label>'.$authtype,           '<label>'.$authtype,
          '</label><input type="text" size="10" name="krbarg" '.           '</label><input type="text" size="10" name="krbarg" '.
              'value="'.$krbarg.'" '.               'value="'.$krbarg.'" '.
              'onchange="'.$jscall.'"'.$disabled.' />',               'onchange="'.$jscall.'" />',
          '<label><input type="hidden" name="krbver" value="5" />',           '<label><input type="hidden" name="krbver" value="5" />',
          '</label>');           '</label>');
     }      }
Line 2959  sub authform_internal { Line 2961  sub authform_internal {
                 kerb_def_dom => 'MSU.EDU',                  kerb_def_dom => 'MSU.EDU',
                 @_,                  @_,
                 );                  );
     my ($intcheck,$intarg,$result,$authtype,$autharg,$jscall,$disabled);      my ($intcheck,$intarg,$result,$authtype,$autharg,$jscall);
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});      my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
     if ($in{'readonly'}) {  
         $disabled = ' disabled="disabled"';  
     }  
     if (defined($in{'curr_authtype'})) {      if (defined($in{'curr_authtype'})) {
         if ($in{'curr_authtype'} eq 'int') {          if ($in{'curr_authtype'} eq 'int') {
             if ($can_assign{'int'}) {              if ($can_assign{'int'}) {
Line 2992  sub authform_internal { Line 2991  sub authform_internal {
         if (defined($in{'mode'})) {          if (defined($in{'mode'})) {
             if ($in{'mode'} eq 'modifycourse') {              if ($in{'mode'} eq 'modifycourse') {
                 if ($authnum == 1) {                  if ($authnum == 1) {
                     $authtype = '<input type="radio" name="login" value="int"'.$disabled.' />';                      $authtype = '<input type="radio" name="login" value="int" />';
                 }                  }
             }              }
         }          }
Line 3000  sub authform_internal { Line 2999  sub authform_internal {
     $jscall = "javascript:changed_radio('int',$in{'formname'});";      $jscall = "javascript:changed_radio('int',$in{'formname'});";
     if ($authtype eq '') {      if ($authtype eq '') {
         $authtype = '<input type="radio" name="login" value="int" '.$intcheck.          $authtype = '<input type="radio" name="login" value="int" '.$intcheck.
                     ' onchange="'.$jscall.'" onclick="'.$jscall.'"'.$disabled.' />';                      ' onchange="'.$jscall.'" onclick="'.$jscall.'" />';
     }      }
     $autharg = '<input type="password" size="10" name="intarg" value="'.      $autharg = '<input type="password" size="10" name="intarg" value="'.
                $intarg.'" onchange="'.$jscall.'"'.$disabled.' />';                 $intarg.'" onchange="'.$jscall.'" />';
     $result = &mt      $result = &mt
         ('[_1] Internally authenticated (with initial password [_2])',          ('[_1] Internally authenticated (with initial password [_2])',
          '<label>'.$authtype,'</label>'.$autharg);           '<label>'.$authtype,'</label>'.$autharg);
     $result.='<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.intarg.type='."'text'".' } else { this.form.intarg.type='."'password'".' }"'.$disabled.' />'.&mt('Visible input').'</label>';      $result.="<label><input type=\"checkbox\" name=\"visible\" onclick='if (this.checked) { this.form.intarg.type=\"text\" } else { this.form.intarg.type=\"password\" }' />".&mt('Visible input').'</label>';
     return $result;      return $result;
 }  }
   
Line 3017  sub authform_local { Line 3016  sub authform_local {
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
               );                );
     my ($loccheck,$locarg,$result,$authtype,$autharg,$jscall,$disabled);      my ($loccheck,$locarg,$result,$authtype,$autharg,$jscall);
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});      my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
     if ($in{'readonly'}) {  
         $disabled = ' disabled="disabled"';  
     }  
     if (defined($in{'curr_authtype'})) {      if (defined($in{'curr_authtype'})) {
         if ($in{'curr_authtype'} eq 'loc') {          if ($in{'curr_authtype'} eq 'loc') {
             if ($can_assign{'loc'}) {              if ($can_assign{'loc'}) {
Line 3050  sub authform_local { Line 3046  sub authform_local {
         if (defined($in{'mode'})) {          if (defined($in{'mode'})) {
             if ($in{'mode'} eq 'modifycourse') {              if ($in{'mode'} eq 'modifycourse') {
                 if ($authnum == 1) {                  if ($authnum == 1) {
                     $authtype = '<input type="radio" name="login" value="loc"'.$disabled.' />';                      $authtype = '<input type="radio" name="login" value="loc" />';
                 }                  }
             }              }
         }          }
Line 3059  sub authform_local { Line 3055  sub authform_local {
     if ($authtype eq '') {      if ($authtype eq '') {
         $authtype = '<input type="radio" name="login" value="loc" '.          $authtype = '<input type="radio" name="login" value="loc" '.
                     $loccheck.' onchange="'.$jscall.'" onclick="'.                      $loccheck.' onchange="'.$jscall.'" onclick="'.
                     $jscall.'"'.$disabled.' />';                      $jscall.'" />';
     }      }
     $autharg = '<input type="text" size="10" name="locarg" value="'.      $autharg = '<input type="text" size="10" name="locarg" value="'.
                $locarg.'" onchange="'.$jscall.'"'.$disabled.' />';                 $locarg.'" onchange="'.$jscall.'" />';
     $result = &mt('[_1] Local Authentication with argument [_2]',      $result = &mt('[_1] Local Authentication with argument [_2]',
                   '<label>'.$authtype,'</label>'.$autharg);                    '<label>'.$authtype,'</label>'.$autharg);
     return $result;      return $result;
Line 3074  sub authform_filesystem { Line 3070  sub authform_filesystem {
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
               );                );
     my ($fsyscheck,$result,$authtype,$autharg,$jscall,$disabled);      my ($fsyscheck,$result,$authtype,$autharg,$jscall);
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});      my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
     if ($in{'readonly'}) {  
         $disabled = ' disabled="disabled"';  
     }  
     if (defined($in{'curr_authtype'})) {      if (defined($in{'curr_authtype'})) {
         if ($in{'curr_authtype'} eq 'fsys') {          if ($in{'curr_authtype'} eq 'fsys') {
             if ($can_assign{'fsys'}) {              if ($can_assign{'fsys'}) {
Line 3104  sub authform_filesystem { Line 3097  sub authform_filesystem {
         if (defined($in{'mode'})) {          if (defined($in{'mode'})) {
             if ($in{'mode'} eq 'modifycourse') {              if ($in{'mode'} eq 'modifycourse') {
                 if ($authnum == 1) {                  if ($authnum == 1) {
                     $authtype = '<input type="radio" name="login" value="fsys"'.$disabled.' />';                      $authtype = '<input type="radio" name="login" value="fsys" />';
                 }                  }
             }              }
         }          }
Line 3113  sub authform_filesystem { Line 3106  sub authform_filesystem {
     if ($authtype eq '') {      if ($authtype eq '') {
         $authtype = '<input type="radio" name="login" value="fsys" '.          $authtype = '<input type="radio" name="login" value="fsys" '.
                     $fsyscheck.' onchange="'.$jscall.'" onclick="'.                      $fsyscheck.' onchange="'.$jscall.'" onclick="'.
                     $jscall.'"'.$disabled.' />';                      $jscall.'" />';
     }      }
     $autharg = '<input type="text" size="10" name="fsysarg" value=""'.      $autharg = '<input type="text" size="10" name="fsysarg" value=""'.
                ' onchange="'.$jscall.'"'.$disabled.' />';                 ' onchange="'.$jscall.'" />';
     $result = &mt      $result = &mt
         ('[_1] Filesystem Authenticated (with initial password [_2])',          ('[_1] Filesystem Authenticated (with initial password [_2])',
          '<label><input type="radio" name="login" value="fsys" '.           '<label><input type="radio" name="login" value="fsys" '.
          $fsyscheck.'onchange="'.$jscall.'" onclick="'.$jscall.'"'.$disabled.' />',           $fsyscheck.'onchange="'.$jscall.'" onclick="'.$jscall.'" />',
          '</label><input type="password" size="10" name="fsysarg" value="" '.           '</label><input type="password" size="10" name="fsysarg" value="" '.
                   'onchange="'.$jscall.'"'.$disabled.' />');                    'onchange="'.$jscall.'" />');
     return $result;      return $result;
 }  }
   
Line 3144  sub get_assignable_auth { Line 3137  sub get_assignable_auth {
             my $context;              my $context;
             if ($env{'request.role'} =~ /^au/) {              if ($env{'request.role'} =~ /^au/) {
                 $context = 'author';                  $context = 'author';
             } elsif ($env{'request.role'} =~ /^(dc|dh)/) {              } elsif ($env{'request.role'} =~ /^dc/) {
                 $context = 'domain';                  $context = 'domain';
             } elsif ($env{'request.course.id'}) {              } elsif ($env{'request.course.id'}) {
                 $context = 'course';                  $context = 'course';
Line 3335  sub get_related_words { Line 3328  sub get_related_words {
     untie %thesaurus_db;      untie %thesaurus_db;
     return @Words;      return @Words;
 }  }
   ###############################################################
   #
   #  Spell checking
   #
   
 =pod  =pod
   
 =back  =back
   
   =head1 Spell checking
   
   =over 4
   
   =item * &check_spelling($wordlist $language)
   
   Takes a string containing words and feeds it to an external
   spellcheck program via a pipeline. Returns a string containing
   them mis-spelled words.
   
   Parameters:
   
   =over 4
   
   =item - $wordlist
   
   String that will be fed into the spellcheck program.
   
   =item - $language
   
   Language string that specifies the language for which the spell
   check will be performed.
   
   =back
   
   =back
   
   Note: This sub assumes that aspell is installed.
   
   
 =cut  =cut
   
   
   sub check_spelling {
       my ($wordlist, $language) = @_;
       my @misspellings;
       
       # Generate the speller and set the langauge.
       # if explicitly selected:
   
       my $speller = Text::Aspell->new;
       if ($language) {
    $speller->set_option('lang', $language);
       }
   
       # Turn the word list into an array of words by splittingon whitespace
   
       my @words = split(/\s+/, $wordlist);
   
       foreach my $word (@words) {
    if(! $speller->check($word)) {
       push(@misspellings, $word);
    }
       }
       return join(' ', @misspellings);
       
   }
   
 # -------------------------------------------------------------- Plaintext name  # -------------------------------------------------------------- Plaintext name
 =pod  =pod
   
Line 3972  Return string with previous attempt on p Line 4025  Return string with previous attempt on p
   
 =item * $usec: section of the desired student  =item * $usec: section of the desired student
   
 =item * $identifier: counter for student (multiple students one problem) or  =item * $identifier: counter for student (multiple students one problem) or 
     problem (one student; whole sequence).      problem (one student; whole sequence).
   
 =back  =back
Line 4059  sub get_previous_attempt { Line 4112  sub get_previous_attempt {
             my (@hidden,@unsolved);              my (@hidden,@unsolved);
             if (%typeparts) {              if (%typeparts) {
                 foreach my $id (keys(%typeparts)) {                  foreach my $id (keys(%typeparts)) {
                     if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') ||                      if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') || 
                         ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {                          ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {
                         push(@hidden,$id);                          push(@hidden,$id);
                     } elsif ($identifier ne '') {                      } elsif ($identifier ne '') {
Line 4120  sub get_previous_attempt { Line 4173  sub get_previous_attempt {
                         if ($key =~ /\./) {                          if ($key =~ /\./) {
                             my $value = $returnhash{$version.':'.$key};                              my $value = $returnhash{$version.':'.$key};
                             if ($key =~ /\.rndseed$/) {                              if ($key =~ /\.rndseed$/) {
                                 my ($id) = ($key =~ /^(.+)\.rndseed$/);                                  my ($id) = ($key =~ /^(.+)\.[^.]+$/);
                                 if (exists($returnhash{$version.':'.$id.'.rawrndseed'})) {                                  if (exists($returnhash{$version.':'.$id.'.rawrndseed'})) {
                                     $value = $returnhash{$version.':'.$id.'.rawrndseed'};                                      $value = $returnhash{$version.':'.$id.'.rawrndseed'};
                                 }                                  }
Line 4137  sub get_previous_attempt { Line 4190  sub get_previous_attempt {
                     next if ($key =~ /\.foilorder$/);                      next if ($key =~ /\.foilorder$/);
                     my $value = $returnhash{$version.':'.$key};                      my $value = $returnhash{$version.':'.$key};
                     if ($key =~ /\.rndseed$/) {                      if ($key =~ /\.rndseed$/) {
                         my ($id) = ($key =~ /^(.+)\.rndseed$/);                          my ($id) = ($key =~ /^(.+)\.[^.]+$/);
                         if (exists($returnhash{$version.':'.$id.'.rawrndseed'})) {                          if (exists($returnhash{$version.':'.$id.'.rawrndseed'})) {
                             $value = $returnhash{$version.':'.$id.'.rawrndseed'};                              $value = $returnhash{$version.':'.$id.'.rawrndseed'};
                         }                          }
Line 4168  sub get_previous_attempt { Line 4221  sub get_previous_attempt {
                       if ($key =~/$regexp$/ && (defined &$gradesub)) {                        if ($key =~/$regexp$/ && (defined &$gradesub)) {
                           $value = &$gradesub($value);                            $value = &$gradesub($value);
                       }                        }
                       $prevattempts.='<td>'.$value.'&nbsp;</td>';                        $prevattempts.='<td>'. $value.'&nbsp;</td>';
                   } else {                    } else {
                       $prevattempts.='<td>&nbsp;</td>';                        $prevattempts.='<td>&nbsp;</td>';
                   }                    }
Line 4184  sub get_previous_attempt { Line 4237  sub get_previous_attempt {
       if ($key =~/$regexp$/ && (defined &$gradesub)) {        if ($key =~/$regexp$/ && (defined &$gradesub)) {
                   $value = &$gradesub($value);                    $value = &$gradesub($value);
               }                }
       $prevattempts.='<td>'.$value.'&nbsp;</td>';       $prevattempts.='<td>'.$value.'&nbsp;</td>';
           }            }
       }        }
       $prevattempts.= &end_data_table_row().&end_data_table();        $prevattempts.= &end_data_table_row().&end_data_table();
Line 4205  sub get_previous_attempt { Line 4258  sub get_previous_attempt {
 sub format_previous_attempt_value {  sub format_previous_attempt_value {
     my ($key,$value) = @_;      my ($key,$value) = @_;
     if (($key =~ /timestamp/) || ($key=~/duedate/)) {      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 = &HTML::Entities::encode('('.join(', ', @{ $value }).')','"<>&');
     } elsif ($key =~ /answerstring$/) {      } elsif ($key =~ /answerstring$/) {
         my %answers = &Apache::lonnet::str2hash($value);          my %answers = &Apache::lonnet::str2hash($value);
           my @answer = %answers;
           %answers = map {&HTML::Entities::encode($_, '"<>&')} @answer;
         my @anskeys = sort(keys(%answers));          my @anskeys = sort(keys(%answers));
         if (@anskeys == 1) {          if (@anskeys == 1) {
             my $answer = $answers{$anskeys[0]};              my $answer = $answers{$anskeys[0]};
Line 4232  sub format_previous_attempt_value { Line 4287  sub format_previous_attempt_value {
             }               } 
         }          }
     } else {      } else {
  $value = &unescape($value);          $value = &HTML::Entities::encode(&unescape($value), '"<>&');
     }      }
     return $value;      return $value;
 }  }
Line 4700  sub blockcheck { Line 4755  sub blockcheck {
                                                                 $tdom,$spec,$trest,$area);                                                                  $tdom,$spec,$trest,$area);
                         }                          }
                     }                      }
                     my ($author,$adv,$rar) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles);                      my ($author,$adv) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles);
                     if ($userroles{'user.priv.'.$checkrole} =~ /evb\&([^\:]*)/) {                      if ($userroles{'user.priv.'.$checkrole} =~ /evb\&([^\:]*)/) {
                         if ($1) {                          if ($1) {
                             $no_userblock = 1;                              $no_userblock = 1;
Line 4898  sub blocking_status { Line 4953  sub blocking_status {
 # build a link to a popup window containing the details  # build a link to a popup window containing the details
     my $querystring  = "?activity=$activity";      my $querystring  = "?activity=$activity";
 # $uname and $udom decide whose portfolio the user is trying to look at  # $uname and $udom decide whose portfolio the user is trying to look at
     if (($activity eq 'port') || ($activity eq 'passwd')) {      if ($activity eq 'port') {
         $querystring .= "&amp;udom=$udom"      if ($udom =~ /^$match_domain$/);          $querystring .= "&amp;udom=$udom"      if $udom;
         $querystring .= "&amp;uname=$uname"    if ($uname =~ /^$match_username$/);          $querystring .= "&amp;uname=$uname"    if $uname;
     } elsif ($activity eq 'docs') {      } elsif ($activity eq 'docs') {
         $querystring .= '&amp;url='.&HTML::Entities::encode($url,'&"');          $querystring .= '&amp;url='.&HTML::Entities::encode($url,'&"');
     }      }
Line 4925  END_MYBLOCK Line 4980  END_MYBLOCK
         $class = '';          $class = '';
     } elsif ($activity eq 'printout') {      } elsif ($activity eq 'printout') {
         $text = &mt('Printing Blocked');          $text = &mt('Printing Blocked');
     } elsif ($activity eq 'passwd') {  
         $text = &mt('Password Changing Blocked');  
     }      }
     $output .= <<"END_BLOCK";      $output .= <<"END_BLOCK";
 <div class='$class'>  <div class='$class'>
Line 4950  sub check_ip_acc { Line 5003  sub check_ip_acc {
     if (!defined($acc) || $acc =~ /^\s*$/ || $acc =~/^\s*no\s*$/i) {      if (!defined($acc) || $acc =~ /^\s*$/ || $acc =~/^\s*no\s*$/i) {
         return 1;          return 1;
     }      }
     my $allowed=0;  
     my $ip=$ENV{'REMOTE_ADDR'} || $clientip || $env{'request.host'};  
   
     my $name;  
     foreach my $pattern (split(',',$acc)) {  
         $pattern =~ s/^\s*//;  
         $pattern =~ s/\s*$//;  
         if ($pattern =~ /\*$/) {  
             #35.8.*  
             $pattern=~s/\*//;  
             if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }  
         } elsif ($pattern =~ /(\d+\.\d+\.\d+)\.\[(\d+)-(\d+)\]$/) {  
             #35.8.3.[34-56]  
             my $low=$2;  
             my $high=$3;  
             $pattern=$1;  
             if ($ip =~ /^\Q$pattern\E/) {  
                 my $last=(split(/\./,$ip))[3];  
                 if ($last <=$high && $last >=$low) { $allowed=1; }  
             }  
         } elsif ($pattern =~ /^\*/) {  
             #*.msu.edu  
             $pattern=~s/\*//;  
             if (!defined($name)) {  
                 use Socket;  
                 my $netaddr=inet_aton($ip);  
                 ($name)=gethostbyaddr($netaddr,AF_INET);  
             }  
             if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }  
         } elsif ($pattern =~ /\d+\.\d+\.\d+\.\d+/) {  
             #127.0.0.1  
             if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }  
         } else {  
             #some.name.com  
             if (!defined($name)) {  
                 use Socket;  
                 my $netaddr=inet_aton($ip);  
                 ($name)=gethostbyaddr($netaddr,AF_INET);  
             }  
             if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }  
         }  
         if ($allowed) { last; }  
     }  
     return $allowed;  
 }  
   
 sub check_slotip_acc {  
     my ($acc,$clientip)=@_;  
     &Apache::lonxml::debug("acc is $acc");  
     if (!defined($acc) || $acc =~ /^\s*$/ || $acc =~/^\s*no\s*$/i) {  
         return 1;  
     }  
     my $allowed;      my $allowed;
     my $ip=$ENV{'REMOTE_ADDR'} || $clientip || $env{'request.host'};      my $ip=$env{'request.host'} || $ENV{'REMOTE_ADDR'} || $clientip;
   
     my $name;      my $name;
     my %access = (      my %access = (
Line 5026  sub check_slotip_acc { Line 5027  sub check_slotip_acc {
    my $numallows = scalar(@allows);     my $numallows = scalar(@allows);
    my $count = 0;     my $count = 0;
    foreach my $pattern (@denies,@allows) {     foreach my $pattern (@denies,@allows) {
         $count ++;          $count ++; 
         my $acctype = 'allowfrom';          my $acctype = 'allowfrom';
         if ($count <= $numdenies) {          if ($count <= $numdenies) {
             $acctype = 'denyfrom';              $acctype = 'denyfrom';
Line 5137  sub get_domainconf { Line 5138  sub get_domainconf {
                                                 my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};                                                  my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};
                                                 $designhash{$udom.'.login.loginvia'} = $server;                                                  $designhash{$udom.'.login.loginvia'} = $server;
                                                 if ($domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'} eq 'custom') {                                                  if ($domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'} eq 'custom') {
   
                                                     $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};                                                      $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};
                                                 } else {                                                  } else {
                                                     $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};                                                      $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};
Line 5217  sub get_legacy_domconf { Line 5219  sub get_legacy_domconf {
     my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';      my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
     my $designfile =  $designdir.'/'.$udom.'.tab';      my $designfile =  $designdir.'/'.$udom.'.tab';
     if (-e $designfile) {      if (-e $designfile) {
         if ( open (my $fh,'<',$designfile) ) {          if ( open (my $fh,"<$designfile") ) {
             while (my $line = <$fh>) {              while (my $line = <$fh>) {
                 next if ($line =~ /^\#/);                  next if ($line =~ /^\#/);
                 chomp($line);                  chomp($line);
Line 5468  Inputs: Line 5470  Inputs:
   
 =item * $bgcolor, used to override the bgcolor on a webpage to a specific value  =item * $bgcolor, used to override the bgcolor on a webpage to a specific value
   
 =item * $no_inline_link, if true and in remote mode, don't show the  
          'Switch To Inline Menu' link  
   
 =item * $args, optional argument valid values are  =item * $args, optional argument valid values are
             no_auto_mt_title -> prevents &mt()ing the title arg              no_auto_mt_title -> prevents &mt()ing the title arg
               inherit_jsmath -> when creating popup window in a page,
                                 should it have jsmath forced on by the
                                 current page
   
 =item * $advtoolsref, optional argument, ref to an array containing  =item * $advtoolsref, optional argument, ref to an array containing
             inlineremote items to be added in "Functions" menu below              inlineremote items to be added in "Functions" menu below
Line 5489  other decorations will be returned. Line 5491  other decorations will be returned.
   
 sub bodytag {  sub bodytag {
     my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,      my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,
         $no_nav_bar,$bgcolor,$no_inline_link,$args,$advtoolsref)=@_;          $no_nav_bar,$bgcolor,$args,$advtoolsref)=@_;
   
     my $public;      my $public;
     if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))      if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
Line 5525  sub bodytag { Line 5527  sub bodytag {
     if ($env{'request.course.id'}) {      if ($env{'request.course.id'}) {
         if ($env{'request.role'} !~ /^cr/) {          if ($env{'request.role'} !~ /^cr/) {
             $role = &Apache::lonnet::plaintext($role,&course_type());              $role = &Apache::lonnet::plaintext($role,&course_type());
         } elsif ($role =~ m{^cr/($match_domain)/\1-domainconfig/(\w+)$}) {  
             if ($env{'request.role.desc'}) {  
                 $role = $env{'request.role.desc'};  
             } else {  
                 $role = &mt('Helpdesk[_1]','&nbsp;'.$2);  
             }  
         } else {  
             $role = (split(/\//,$role,4))[-1];  
         }          }
         if ($env{'request.course.sec'}) {          if ($env{'request.course.sec'}) {
             $role .= ('&nbsp;'x2).'-&nbsp;'.&mt('section:').'&nbsp;'.$env{'request.course.sec'};              $role .= ('&nbsp;'x2).'-&nbsp;'.&mt('section:').'&nbsp;'.$env{'request.course.sec'};
Line 5548  sub bodytag { Line 5542  sub bodytag {
   
 # construct main body tag  # construct main body tag
     my $bodytag = "<body $extra_body_attr>".      my $bodytag = "<body $extra_body_attr>".
  &Apache::lontexconvert::init_math_support();   &Apache::lontexconvert::init_math_support($args->{'inherit_jsmath'});
   
     &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);      &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
   
Line 5572  sub bodytag { Line 5566  sub bodytag {
         $dc_info =~ s/\s+$//;          $dc_info =~ s/\s+$//;
     }      }
   
     $role = '<span class="LC_nobreak">('.$role.')</span>' if ($role && !$env{'browser.mobile'});      $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;
   
     if ($env{'request.state'} eq 'construct') { $forcereg=1; }  
   
   
           if ($env{'request.state'} eq 'construct') { $forcereg=1; }
     my $funclist;  
     if (($env{'environment.remote'} eq 'on') && ($env{'request.state'} ne 'construct')) {  
         $bodytag .= Apache::lonhtmlcommon::scripttag(Apache::lonmenu::utilityfunctions($httphost), 'start')."\n".  
                     Apache::lonmenu::serverform();  
         my $forbodytag;  
         &Apache::lonmenu::prepare_functions($env{'request.noversionuri'},  
                                             $forcereg,$args->{'group'},  
                                             $args->{'bread_crumbs'},  
                                             $advtoolsref,'',\$forbodytag);  
         unless (ref($args->{'bread_crumbs'}) eq 'ARRAY') {  
             $funclist = $forbodytag;  
         }  
     } else {  
   
         #    if ($env{'request.state'} eq 'construct') {          #    if ($env{'request.state'} eq 'construct') {
         #        $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls          #        $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls
Line 5602  sub bodytag { Line 5580  sub bodytag {
         my ($left,$right) = Apache::lonmenu::primary_menu();          my ($left,$right) = Apache::lonmenu::primary_menu();
   
         if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {          if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
             if ($dc_info) {               if ($dc_info) {
                  $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;                   $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;
             }               }
             $bodytag .= qq|<div id="LC_nav_bar">$left $role<br />               $bodytag .= qq|<div id="LC_nav_bar">$left $role<br />
                            <em>$realm</em> $dc_info</div>|;                  <em>$realm</em> $dc_info</div>|;
             return $bodytag;              return $bodytag;
         }          }
   
Line 5621  sub bodytag { Line 5599  sub bodytag {
         }          }
         $bodytag .= qq|<div id="LC_realm">$realm $dc_info</div>|;          $bodytag .= qq|<div id="LC_realm">$realm $dc_info</div>|;
   
         #if directed to not display the secondary menu, don't.          #if directed to not display the secondary menu, don't.  
         if ($args->{'no_secondary_menu'}) {          if ($args->{'no_secondary_menu'}) {
             return $bodytag;              return $bodytag;
         }          }
Line 5635  sub bodytag { Line 5613  sub bodytag {
                                 $args->{'bread_crumbs'});                                  $args->{'bread_crumbs'});
             } elsif ($forcereg) {              } elsif ($forcereg) {
                 $bodytag .= &Apache::lonmenu::innerregister($forcereg,undef,                  $bodytag .= &Apache::lonmenu::innerregister($forcereg,undef,
                                                             $args->{'group'},                                                              $args->{'group'});
                                                             $args->{'hide_buttons'});  
             } else {              } else {
                 my $forbodytag;                  $bodytag .= 
                 &Apache::lonmenu::prepare_functions($env{'request.noversionuri'},                      &Apache::lonmenu::prepare_functions($env{'request.noversionuri'},
                                                     $forcereg,$args->{'group'},                                                          $forcereg,$args->{'group'},
                                                     $args->{'bread_crumbs'},                                                          $args->{'bread_crumbs'},
                                                     $advtoolsref,'',\$forbodytag);                                                          $advtoolsref);
                 unless (ref($args->{'bread_crumbs'}) eq 'ARRAY') {  
                     $bodytag .= $forbodytag;  
                 }  
             }              }
         }else{          }else{
             # this is to seperate menu from content when there's no secondary              # this is to seperate menu from content when there's no secondary
Line 5655  sub bodytag { Line 5629  sub bodytag {
         }          }
   
         return $bodytag;          return $bodytag;
     }  
   
 #  
 # Top frame rendering, Remote is up  
 #  
   
     my $imgsrc = $img;  
     if ($img =~ /^\/adm/) {  
         $imgsrc = &lonhttpdurl($img);  
     }  
     my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />';  
   
     my $help=($no_inline_link?''  
               :&Apache::loncommon::top_nav_help('Help'));  
   
     # Explicit link to get inline menu  
     my $menu= ($no_inline_link?''  
                :'<a href="/adm/remote?action=collapse" target="_top">'.&mt('Switch to Inline Menu Mode').'</a>');  
   
     if ($dc_info) {  
         $dc_info = qq|<span class="LC_cusr_subheading">($dc_info)</span>|;  
     }  
   
     my $name = &plainname($env{'user.name'},$env{'user.domain'});  
     unless ($public) {  
         $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'},  
                                 undef,'LC_menubuttons_link');  
     }  
   
     unless ($env{'form.inhibitmenu'}) {  
         $bodytag .= qq|<div id="LC_nav_bar">$name $role</div>  
                        <ol class="LC_primary_menu LC_floatright LC_right">  
                        <li>$help</li>  
                        <li>$menu</li>  
                        </ol><div id="LC_realm"> $realm $dc_info</div>|;  
     }  
     if ($env{'request.state'} eq 'construct') {  
         if (!$public){  
             if ($env{'request.state'} eq 'construct') {  
                 $funclist = &Apache::lonhtmlcommon::scripttag(  
                                 &Apache::lonmenu::utilityfunctions($httphost), 'start').  
                             &Apache::lonhtmlcommon::scripttag('','end').  
                             &Apache::lonmenu::innerregister($forcereg,  
                                                             $args->{'bread_crumbs'});  
             }  
         }  
     }  
     return $bodytag."\n".$funclist;  
 }  }
   
 sub dc_courseid_toggle {  sub dc_courseid_toggle {
Line 5734  sub make_attr_string { Line 5660  sub make_attr_string {
  delete($attr_ref->{$key});   delete($attr_ref->{$key});
     }      }
  }   }
         if ($env{'environment.remote'} eq 'on') {   $attr_ref->{'onload'}  = $on_load;
             $attr_ref->{'onload'}  =   $attr_ref->{'onunload'}= $on_unload;
                 &Apache::lonmenu::loadevents().  $on_load;  
             $attr_ref->{'onunload'}=  
                 &Apache::lonmenu::unloadevents().$on_unload;  
         } else {    
     $attr_ref->{'onload'}  = $on_load;  
     $attr_ref->{'onunload'}= $on_unload;  
         }  
     }      }
   
     my $attr_string;      my $attr_string;
Line 5776  sub endbodytag { Line 5695  sub endbodytag {
     unless ((ref($args) eq 'HASH') && ($args->{'notbody'})) {      unless ((ref($args) eq 'HASH') && ($args->{'notbody'})) {
         $endbodytag='</body>';          $endbodytag='</body>';
     }      }
       $endbodytag=&Apache::lontexconvert::jsMath_process()."\n".$endbodytag;
     if ( exists( $env{'internal.head.redirect'} ) ) {      if ( exists( $env{'internal.head.redirect'} ) ) {
         if (!(ref($args) eq 'HASH' && $args->{'noredirectlink'})) {          if (!(ref($args) eq 'HASH' && $args->{'noredirectlink'})) {
     $endbodytag=      $endbodytag=
Line 5950  div.LC_confirm_box .LC_success img { Line 5870  div.LC_confirm_box .LC_success img {
   vertical-align: middle;    vertical-align: middle;
 }  }
   
 .LC_maxwidth {  
   max-width: 100%;  
   height: auto;  
 }  
   
 .LC_textsize_mobile {  
   \@media only screen and (max-device-width: 480px) {  
       -webkit-text-size-adjust:100%; -moz-text-size-adjust:100%; -ms-text-size-adjust:100%;  
   }  
 }  
   
 .LC_icon {  .LC_icon {
   border: none;    border: none;
   vertical-align: middle;    vertical-align: middle;
Line 6082  table#LC_menubuttons img { Line 5991  table#LC_menubuttons img {
   vertical-align: middle;    vertical-align: middle;
 }  }
   
 .LC_breadcrumbs_hoverable {  
   background: $sidebg;  
 }  
   
 td.LC_table_cell_checkbox {  td.LC_table_cell_checkbox {
   text-align: center;    text-align: center;
 }  }
Line 7124  ol.LC_primary_menu li { Line 7029  ol.LC_primary_menu li {
   line-height: 1.5em;    line-height: 1.5em;
 }  }
   
 ol.LC_primary_menu li a,   ol.LC_primary_menu li a,
 ol.LC_primary_menu li p {  ol.LC_primary_menu li p {
   display: block;    display: block;
   margin: 0;    margin: 0;
Line 7139  ol.LC_primary_menu li p span.LC_primary_ Line 7044  ol.LC_primary_menu li p span.LC_primary_
 }  }
   
 ol.LC_primary_menu li p span.LC_primary_menu_innerarrow {  ol.LC_primary_menu li p span.LC_primary_menu_innerarrow {
   display: inline-block;    display: inline-block;
   width: 5%;    width: 5%;
   float: right;    float: right;
   text-align: right;    text-align: right;
Line 7174  ol.LC_primary_menu li:hover li, ol.LC_pr Line 7079  ol.LC_primary_menu li:hover li, ol.LC_pr
   float: none;    float: none;
   border-left: 1px solid black;    border-left: 1px solid black;
   border-right: 1px solid black;    border-right: 1px solid black;
 /* A dark bottom border to visualize different menu options;  /* A dark bottom border to visualize different menu options; 
 overwritten in the create_submenu routine for the last border-bottom of the menu */  overwritten in the create_submenu routine for the last border-bottom of the menu */
   border-bottom: 1px solid $data_table_dark;    border-bottom: 1px solid $data_table_dark; 
 }  }
   
 ol.LC_primary_menu li li p:hover {  ol.LC_primary_menu li li p:hover {
Line 7757  span.roman {font-family: serif; font-sty Line 7662  span.roman {font-family: serif; font-sty
 span.overacc2 {position: relative;  left: .8em; top: -1.2ex;}  span.overacc2 {position: relative;  left: .8em; top: -1.2ex;}
 span.overacc1 {position: relative;  left: .6em; top: -1.2ex;}  span.overacc1 {position: relative;  left: .6em; top: -1.2ex;}
   
 #LC_minitab_header {  
   float:left;  
   width:100%;  
   background:#DAE0D2 url("/res/adm/pages/minitabmenu_bg.gif") repeat-x bottom;  
   font-size:93%;  
   line-height:normal;  
   margin: 0.5em 0 0.5em 0;  
 }  
 #LC_minitab_header ul {  
   margin:0;  
   padding:10px 10px 0;  
   list-style:none;  
 }  
 #LC_minitab_header li {  
   float:left;  
   background:url("/res/adm/pages/minitabmenu_left.gif") no-repeat left top;  
   margin:0;  
   padding:0 0 0 9px;  
 }  
 #LC_minitab_header a {  
   display:block;  
   background:url("/res/adm/pages/minitabmenu_right.gif") no-repeat right top;  
   padding:5px 15px 4px 6px;  
 }  
 #LC_minitab_header #LC_current_minitab {  
   background-image:url("/res/adm/pages/minitabmenu_left_on.gif");  
 }  
 #LC_minitab_header #LC_current_minitab a {  
   background-image:url("/res/adm/pages/minitabmenu_right_on.gif");  
   padding-bottom:5px;  
 }  
   
   
 END  END
 }  }
   
Line 7847  sub headtag { Line 7719  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 7968  OFFLOAD Line 7840  OFFLOAD
     if (!$args->{'frameset'}) {      if (!$args->{'frameset'}) {
         $result .= ' /';          $result .= ' /';
     }      }
     $result .= '>'      $result .= '>' 
         .$inhibitprint          .$inhibitprint
  .$head_extra;   .$head_extra;
     my $clientmobile;      if ($env{'browser.mobile'}) {
     if (($env{'user.name'} eq '') && ($env{'user.domain'} eq '')) {  
         (undef,undef,undef,undef,undef,undef,$clientmobile) = &decode_user_agent();  
     } else {  
         $clientmobile = $env{'browser.mobile'};  
     }  
     if ($clientmobile) {  
         $result .= '          $result .= '
 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
 <meta name="apple-mobile-web-app-capable" content="yes" />';  <meta name="apple-mobile-web-app-capable" content="yes" />';
     }      }
     $result .= '<meta name="google" content="notranslate" />'."\n";  
     return $result.'</head>';      return $result.'</head>';
 }  }
   
Line 8001  sub font_settings { Line 7866  sub font_settings {
     my $headerstring='';      my $headerstring='';
     if ((!$env{'browser.mathml'} && $env{'browser.unicode'}) ||      if ((!$env{'browser.mathml'} && $env{'browser.unicode'}) ||
         ((ref($args) eq 'HASH') && ($args->{'browser.unicode'}))) {          ((ref($args) eq 'HASH') && ($args->{'browser.unicode'}))) {
  $headerstring.=          $headerstring.=
     '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"';              '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"';
         if (!$args->{'frameset'}) {          if (!$args->{'frameset'}) {
             $headerstring.= ' /';      $headerstring.= ' /';
         }          }
         $headerstring .= '>'."\n";   $headerstring .= '>'."\n";
     }      }
     return $headerstring;      return $headerstring;
 }  }
Line 8159  $args - additional optional args support Line 8024  $args - additional optional args support
              skip_phases    -> hash ref of                skip_phases    -> hash ref of 
                                     head -> skip the <html><head> generation                                      head -> skip the <html><head> generation
                                     body -> skip all <body> generation                                      body -> skip all <body> generation
              no_inline_link -> if true and in remote mode, don't show the  
                                     'Switch To Inline Menu' link  
              no_auto_mt_title -> prevent &mt()ing the title arg               no_auto_mt_title -> prevent &mt()ing the title arg
                inherit_jsmath -> when creating popup window in a page,
                                       should it have jsmath forced on by the
                                       current page
              bread_crumbs ->             Array containing breadcrumbs               bread_crumbs ->             Array containing breadcrumbs
              bread_crumbs_component ->  if exists show it as headline else show only the breadcrumbs               bread_crumbs_component ->  if exists show it as headline else show only the breadcrumbs
              bread_crumbs_nomenu -> if true will pass false as the value of $menulink               group          -> includes the current group, if page is for a 
                                     to lonhtmlcommon::breadcrumbs                                 specific group  
              group          -> includes the current group, if page is for a  
                                specific group  
   
 =back  =back
   
Line 8197  sub start_page { Line 8061  sub start_page {
                          $args->{'function'},       $args->{'add_entries'},                           $args->{'function'},       $args->{'add_entries'},
                          $args->{'only_body'},      $args->{'domain'},                           $args->{'only_body'},      $args->{'domain'},
                          $args->{'force_register'}, $args->{'no_nav_bar'},                           $args->{'force_register'}, $args->{'no_nav_bar'},
                          $args->{'bgcolor'},        $args->{'no_inline_link'},                           $args->{'bgcolor'},        $args,
                          $args,                     \@advtools);                           \@advtools);
         }          }
     }      }
   
Line 8231  sub start_page { Line 8095  sub start_page {
                 if (@advtools > 0) {                  if (@advtools > 0) {
                     &Apache::lonmenu::advtools_crumbs(@advtools);                      &Apache::lonmenu::advtools_crumbs(@advtools);
                 }                  }
                 my $menulink;  
                 # if arg: bread_crumbs_nomenu is true pass 0 as $menulink item.  
                 if (exists($args->{'bread_crumbs_nomenu'})) {  
                     $menulink = 0;  
                 } else {  
                     undef($menulink);  
                 }  
  #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'},'',$menulink);   $result .= &Apache::lonhtmlcommon::breadcrumbs($args->{'bread_crumbs_component'});
  }else{   }else{
  $result .= &Apache::lonhtmlcommon::breadcrumbs('','',$menulink);   $result .= &Apache::lonhtmlcommon::breadcrumbs();
  }   }
     } elsif (($env{'environment.remote'} eq 'on') &&  
              ($env{'form.inhibitmenu'} ne 'yes') &&  
              ($env{'request.noversionuri'} =~ m{^/res/}) &&  
              ($env{'request.noversionuri'} !~ m{^/res/adm/pages/})) {  
         $result .= '<div style="padding:0;margin:0;clear:both"><hr /></div>';  
     }      }
     return $result;      return $result;
 }  }
Line 8344  var modalWindow = { Line 8197  var modalWindow = {
 };  };
  var openMyModal = function(source,width,height,scrolling,transparency,style)   var openMyModal = function(source,width,height,scrolling,transparency,style)
  {   {
                 source = source.replace(/'/g,"&#39;");                  source = source.replace("'","&#39;");
  modalWindow.windowId = "myModal";   modalWindow.windowId = "myModal";
  modalWindow.width = width;   modalWindow.width = width;
  modalWindow.height = height;   modalWindow.height = height;
Line 8396  sub modal_adhoc_inner { Line 8249  sub modal_adhoc_inner {
     my ($funcname,$width,$height,$content)=@_;      my ($funcname,$width,$height,$content)=@_;
     my $innerwidth=$width-20;      my $innerwidth=$width-20;
     $content=&js_ready(      $content=&js_ready(
                &start_page('Dialog',undef,{'only_body'=>1,'bgcolor'=>'#FFFFFF'}).                   &start_page('Dialog',undef,{'only_body'=>1,'bgcolor'=>'#FFFFFF'}).
                  &start_scrollbox($width.'px',$innerwidth.'px',$height.'px','myModal','#FFFFFF',undef,1).                   &start_scrollbox($width.'px',$innerwidth.'px',$height.'px','myModal','#FFFFFF',undef,1).
                  $content.                   $content.
                  &end_scrollbox().                   &end_scrollbox().
Line 9041  sub get_sections { Line 8894  sub get_sections {
         }          }
     }      }
   
     if ($check_students) {      if ($check_students) { 
  my ($classlist) = &Apache::loncoursedata::get_classlist($cdom,$cnum);   my ($classlist) = &Apache::loncoursedata::get_classlist($cdom,$cnum);
  my $sec_index = &Apache::loncoursedata::CL_SECTION();   my $sec_index = &Apache::loncoursedata::CL_SECTION();
  my $status_index = &Apache::loncoursedata::CL_STATUS();   my $status_index = &Apache::loncoursedata::CL_STATUS();
Line 9437  sub get_user_quota { Line 9290  sub get_user_quota {
         if ($quota eq '' || wantarray) {          if ($quota eq '' || wantarray) {
             if ($quotaname eq 'course') {              if ($quotaname eq 'course') {
                 my %domdefs = &Apache::lonnet::get_domain_defaults($udom);                  my %domdefs = &Apache::lonnet::get_domain_defaults($udom);
                 if (($crstype eq 'official') || ($crstype eq 'unofficial') ||                  if (($crstype eq 'official') || ($crstype eq 'unofficial') || 
                     ($crstype eq 'community') || ($crstype eq 'textbook')) {                      ($crstype eq 'community') || ($crstype eq 'textbook')) { 
                     $defquota = $domdefs{$crstype.'quota'};                      $defquota = $domdefs{$crstype.'quota'};
                 }                  }
                 if ($defquota eq '') {                  if ($defquota eq '') {
Line 9622  sub excess_filesize_warning { Line 9475  sub excess_filesize_warning {
 ###############################################  ###############################################
   
   
   
   
 sub get_secgrprole_info {  sub get_secgrprole_info {
     my ($cdom,$cnum,$needroles,$type)  = @_;      my ($cdom,$cnum,$needroles,$type)  = @_;
     my %sections_count = &get_sections($cdom,$cnum);      my %sections_count = &get_sections($cdom,$cnum);
Line 9660  sub get_secgrprole_info { Line 9515  sub get_secgrprole_info {
 }  }
   
 sub user_picker {  sub user_picker {
     my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype,$context,$fixeddom,$noinstd) = @_;      my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype,$context) = @_;
     my $currdom = $dom;      my $currdom = $dom;
     my @alldoms = &Apache::lonnet::all_domains();  
     if (@alldoms == 1) {  
         my %domsrch = &Apache::lonnet::get_dom('configuration',  
                                                ['directorysrch'],$alldoms[0]);  
         my $domdesc = &Apache::lonnet::domain($alldoms[0],'description');  
         my $showdom = $domdesc;  
         if ($showdom eq '') {  
             $showdom = $dom;  
         }  
         if (ref($domsrch{'directorysrch'}) eq 'HASH') {  
             if ((!$domsrch{'directorysrch'}{'available'}) &&  
                 ($domsrch{'directorysrch'}{'lcavailable'} eq '0')) {  
                 return (&mt('LON-CAPA directory search is not available in domain: [_1]',$showdom),0);  
             }  
         }  
     }  
     my %curr_selected = (      my %curr_selected = (
                         srchin => 'dom',                          srchin => 'dom',
                         srchby => 'lastname',                          srchby => 'lastname',
Line 9724  sub user_picker { Line 9563  sub user_picker {
                                        );                                         );
     &html_escape(\%html_lt);      &html_escape(\%html_lt);
     &js_escape(\%js_lt);      &js_escape(\%js_lt);
     my $domform;      my $domform = &select_dom_form($currdom,'srchdomain',1,1);
     my $allow_blank = 1;  
     if ($fixeddom) {  
         $allow_blank = 0;  
         $domform = &select_dom_form($currdom,'srchdomain',$allow_blank,1,undef,[$currdom]);  
     } else {  
         $domform = &select_dom_form($currdom,'srchdomain',$allow_blank,1);  
     }  
     my $srchinsel = ' <select name="srchin">';      my $srchinsel = ' <select name="srchin">';
   
     my @srchins = ('crs','dom','alc','instd');      my @srchins = ('crs','dom','alc','instd');
Line 9743  sub user_picker { Line 9575  sub user_picker {
         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'});
         next if (($option eq 'instd') && ($noinstd));  
         if ($curr_selected{'srchin'} eq $option) {          if ($curr_selected{'srchin'} eq $option) {
             $srchinsel .= '               $srchinsel .= ' 
    <option value="'.$option.'" selected="selected">'.$html_lt{$option}.'</option>';     <option value="'.$option.'" selected="selected">'.$html_lt{$option}.'</option>';
Line 9926  END_BLOCK Line 9757  END_BLOCK
                &Apache::lonhtmlcommon::row_closure(1)                 &Apache::lonhtmlcommon::row_closure(1)
                &Apache::lonhtmlcommon::end_pick_box().                 &Apache::lonhtmlcommon::end_pick_box().
                '<br />';                 '<br />';
     return ($output,1);      return $output;
 }  }
   
 sub user_rule_check {  sub user_rule_check {
     my ($usershash,$checks,$alerts,$rulematch,$inst_results,$curr_rules,$got_rules) = @_;      my ($usershash,$checks,$alerts,$rulematch,$inst_results,$curr_rules,$got_rules) = @_;
     my ($response,%inst_response);      my $response;
     if (ref($usershash) eq 'HASH') {      if (ref($usershash) eq 'HASH') {
         if (keys(%{$usershash}) > 1) {          foreach my $user (keys(%{$usershash})) {
             my (%by_username,%by_id,%userdoms);              my ($uname,$udom) = split(/:/,$user);
             my $checkid;              next if ($udom eq '' || $uname eq '');
             if (ref($checks) eq 'HASH') {              my ($id,$newuser);
                 if ((!defined($checks->{'username'})) && (defined($checks->{'id'}))) {              if (ref($usershash->{$user}) eq 'HASH') {
                     $checkid = 1;                  $newuser = $usershash->{$user}->{'newuser'};
                 }                  $id = $usershash->{$user}->{'id'};
             }  
             foreach my $user (keys(%{$usershash})) {  
                 my ($uname,$udom) = split(/:/,$user);  
                 if ($checkid) {  
                     if (ref($usershash->{$user}) eq 'HASH') {  
                         if ($usershash->{$user}->{'id'} ne '') {  
                             $by_id{$udom}{$usershash->{$user}->{'id'}} = $uname;  
                             $userdoms{$udom} = 1;  
                             if (ref($inst_results) eq 'HASH') {  
                                 $inst_results->{$uname.':'.$udom} = {};  
                             }  
                         }  
                     }  
                 } else {  
                     $by_username{$udom}{$uname} = 1;  
                     $userdoms{$udom} = 1;  
                     if (ref($inst_results) eq 'HASH') {  
                         $inst_results->{$uname.':'.$udom} = {};  
                     }  
                 }  
             }  
             foreach my $udom (keys(%userdoms)) {  
                 if (!$got_rules->{$udom}) {  
                     my %domconfig = &Apache::lonnet::get_dom('configuration',  
                                                              ['usercreation'],$udom);  
                     if (ref($domconfig{'usercreation'}) eq 'HASH') {  
                         foreach my $item ('username','id') {  
                             if (ref($domconfig{'usercreation'}{$item.'_rule'}) eq 'ARRAY') {  
                                 $$curr_rules{$udom}{$item} =  
                                     $domconfig{'usercreation'}{$item.'_rule'};  
                             }  
                         }  
                     }  
                     $got_rules->{$udom} = 1;  
                 }  
             }              }
             if ($checkid) {              my $inst_response;
                 foreach my $udom (keys(%by_id)) {              if (ref($checks) eq 'HASH') {
                     my ($outcome,$results) = &Apache::lonnet::get_multiple_instusers($udom,$by_id{$udom},'id');                  if (defined($checks->{'username'})) {
                     if ($outcome eq 'ok') {                      ($inst_response,%{$inst_results->{$user}}) = 
                         foreach my $id (keys(%{$by_id{$udom}})) {                          &Apache::lonnet::get_instuser($udom,$uname);
                             my $uname = $by_id{$udom}{$id};                  } elsif (defined($checks->{'id'})) {
                             $inst_response{$uname.':'.$udom} = $outcome;                      ($inst_response,%{$inst_results->{$user}}) =
                         }                          &Apache::lonnet::get_instuser($udom,undef,$id);
                         if (ref($results) eq 'HASH') {  
                             foreach my $uname (keys(%{$results})) {  
                                 if (exists($inst_response{$uname.':'.$udom})) {  
                                     $inst_response{$uname.':'.$udom} = $outcome;  
                                     $inst_results->{$uname.':'.$udom} = $results->{$uname};  
                                 }  
                             }  
                         }  
                     }  
                 }                  }
             } else {              } else {
                 foreach my $udom (keys(%by_username)) {                  ($inst_response,%{$inst_results->{$user}}) =
                     my ($outcome,$results) = &Apache::lonnet::get_multiple_instusers($udom,$by_username{$udom});                      &Apache::lonnet::get_instuser($udom,$uname);
                     if ($outcome eq 'ok') {                  return;
                         foreach my $uname (keys(%{$by_username{$udom}})) {  
                             $inst_response{$uname.':'.$udom} = $outcome;  
                         }  
                         if (ref($results) eq 'HASH') {  
                             foreach my $uname (keys(%{$results})) {  
                                 $inst_results->{$uname.':'.$udom} = $results->{$uname};  
                             }  
                         }  
                     }  
                 }  
             }              }
         } elsif (keys(%{$usershash}) == 1) {              if (!$got_rules->{$udom}) {
             my $user = (keys(%{$usershash}))[0];                  my %domconfig = &Apache::lonnet::get_dom('configuration',
             my ($uname,$udom) = split(/:/,$user);                                                    ['usercreation'],$udom);
             if (($udom ne '') && ($uname ne '')) {                  if (ref($domconfig{'usercreation'}) eq 'HASH') {
                 if (ref($usershash->{$user}) eq 'HASH') {                      foreach my $item ('username','id') {
                     if (ref($checks) eq 'HASH') {                          if (ref($domconfig{'usercreation'}{$item.'_rule'}) eq 'ARRAY') {
                         if (defined($checks->{'username'})) {                              $$curr_rules{$udom}{$item} = 
                             ($inst_response{$user},%{$inst_results->{$user}}) =                                  $domconfig{'usercreation'}{$item.'_rule'};
                                 &Apache::lonnet::get_instuser($udom,$uname);  
                         } elsif (defined($checks->{'id'})) {  
                             if ($usershash->{$user}->{'id'} ne '') {  
                                 ($inst_response{$user},%{$inst_results->{$user}}) =  
                                     &Apache::lonnet::get_instuser($udom,undef,  
                                                                   $usershash->{$user}->{'id'});  
                             } else {  
                                 ($inst_response{$user},%{$inst_results->{$user}}) =  
                                     &Apache::lonnet::get_instuser($udom,$uname);  
                             }  
                         }                          }
                     } else {  
                        ($inst_response{$user},%{$inst_results->{$user}}) =  
                             &Apache::lonnet::get_instuser($udom,$uname);  
                        return;  
                     }  
                     if (!$got_rules->{$udom}) {  
                         my %domconfig = &Apache::lonnet::get_dom('configuration',  
                                                                  ['usercreation'],$udom);  
                         if (ref($domconfig{'usercreation'}) eq 'HASH') {  
                             foreach my $item ('username','id') {  
                                 if (ref($domconfig{'usercreation'}{$item.'_rule'}) eq 'ARRAY') {  
                                    $$curr_rules{$udom}{$item} =  
                                        $domconfig{'usercreation'}{$item.'_rule'};  
                                 }  
                             }  
                         }  
                         $got_rules->{$udom} = 1;  
                     }                      }
                 }                  }
             } else {                  $got_rules->{$udom} = 1;  
                 return;  
             }  
         } else {  
             return;  
         }  
         foreach my $user (keys(%{$usershash})) {  
             my ($uname,$udom) = split(/:/,$user);  
             next if (($udom eq '') || ($uname eq ''));  
             my $id;  
             if (ref($inst_results) eq 'HASH') {  
                 if (ref($inst_results->{$user}) eq 'HASH') {  
                     $id = $inst_results->{$user}->{'id'};  
                 }  
             }  
             if ($id eq '') {  
                 if (ref($usershash->{$user})) {  
                     $id = $usershash->{$user}->{'id'};  
                 }  
             }              }
             foreach my $item (keys(%{$checks})) {              foreach my $item (keys(%{$checks})) {
                 if (ref($$curr_rules{$udom}) eq 'HASH') {                  if (ref($$curr_rules{$udom}) eq 'HASH') {
                     if (ref($$curr_rules{$udom}{$item}) eq 'ARRAY') {                      if (ref($$curr_rules{$udom}{$item}) eq 'ARRAY') {
                         if (@{$$curr_rules{$udom}{$item}} > 0) {                          if (@{$$curr_rules{$udom}{$item}} > 0) {
                             my %rule_check = &Apache::lonnet::inst_rulecheck($udom,$uname,$id,$item,                              my %rule_check = &Apache::lonnet::inst_rulecheck($udom,$uname,$id,$item,$$curr_rules{$udom}{$item});
                                                                              $$curr_rules{$udom}{$item});  
                             foreach my $rule (@{$$curr_rules{$udom}{$item}}) {                              foreach my $rule (@{$$curr_rules{$udom}{$item}}) {
                                 if ($rule_check{$rule}) {                                  if ($rule_check{$rule}) {
                                     $$rulematch{$user}{$item} = $rule;                                      $$rulematch{$user}{$item} = $rule;
                                     if ($inst_response{$user} eq 'ok') {                                      if ($inst_response eq 'ok') {
                                         if (ref($inst_results) eq 'HASH') {                                          if (ref($inst_results) eq 'HASH') {
                                             if (ref($inst_results->{$user}) eq 'HASH') {                                              if (ref($inst_results->{$user}) eq 'HASH') {
                                                 if (keys(%{$inst_results->{$user}}) == 0) {                                                  if (keys(%{$inst_results->{$user}}) == 0) {
                                                     $$alerts{$item}{$udom}{$uname} = 1;                                                      $$alerts{$item}{$udom}{$uname} = 1;
                                                 } elsif ($item eq 'id') {  
                                                     if ($inst_results->{$user}->{'id'} eq '') {  
                                                         $$alerts{$item}{$udom}{$uname} = 1;  
                                                     }  
                                                 }                                                  }
                                             }                                              }
                                         }                                          }
Line 10241  sub get_institutional_codes { Line 9968  sub get_institutional_codes {
         foreach (@currxlists) {          foreach (@currxlists) {
             if (m/^([^:]+):(\w*)$/) {              if (m/^([^:]+):(\w*)$/) {
                 unless (grep/^$1$/,@{$allcourses}) {                  unless (grep/^$1$/,@{$allcourses}) {
                     push(@{$allcourses},$1);                      push @{$allcourses},$1;
                     $$LC_code{$1} = $2;                      $$LC_code{$1} = $2;
                 }                  }
             }              }
Line 10254  sub get_institutional_codes { Line 9981  sub get_institutional_codes {
                 my $sec = $coursecode.$1;                  my $sec = $coursecode.$1;
                 my $lc_sec = $2;                  my $lc_sec = $2;
                 unless (grep/^$sec$/,@{$allcourses}) {                  unless (grep/^$sec$/,@{$allcourses}) {
                     push(@{$allcourses},$sec);                      push @{$allcourses},$sec;
                     $$LC_code{$sec} = $lc_sec;                      $$LC_code{$sec} = $lc_sec;
                 }                  }
             }              }
Line 10352  reservable_now - ref to hash of student_ Line 10079  reservable_now - ref to hash of student_
   
     Keys in inner hash are:      Keys in inner hash are:
     (a) symb: either blank or symb to which slot use is restricted.      (a) symb: either blank or symb to which slot use is restricted.
     (b) endreserve: end date of reservation period.      (b) endreserve: end date of reservation period. 
     (c) uniqueperiod: start,end dates when slot is to be uniquely  
         selected.  
   
 sorted_future - ref to array of student_schedulable slots reservable in  sorted_future - ref to array of student_schedulable slots reservable in
                 the future, ordered by start date of reservation period.                  the future, ordered by start date of reservation period.
Line 10365  future_reservable - ref to hash of stude Line 10090  future_reservable - ref to hash of stude
     Keys in inner hash are:      Keys in inner hash are:
     (a) symb: either blank or symb to which slot use is restricted.      (a) symb: either blank or symb to which slot use is restricted.
     (b) startreserve:  start date of reservation period.      (b) startreserve:  start date of reservation period.
     (c) uniqueperiod: start,end dates when slot is to be uniquely  
         selected.  
   
 =back  =back
   
Line 10420  sub get_future_slots { Line 10143  sub get_future_slots {
             my $startreserve = $slots{$slot}->{'startreserve'};              my $startreserve = $slots{$slot}->{'startreserve'};
             my $endreserve = $slots{$slot}->{'endreserve'};              my $endreserve = $slots{$slot}->{'endreserve'};
             my $symb = $slots{$slot}->{'symb'};              my $symb = $slots{$slot}->{'symb'};
             my $uniqueperiod;  
             if (ref($slots{$slot}->{'uniqueperiod'}) eq 'ARRAY') {  
                 $uniqueperiod = join(',',@{$slots{$slot}->{'uniqueperiod'}});  
             }  
             if (($startreserve < $now) &&              if (($startreserve < $now) &&
                 (!$endreserve || $endreserve > $now)) {                  (!$endreserve || $endreserve > $now)) {
                 my $lastres = $endreserve;                  my $lastres = $endreserve;
Line 10432  sub get_future_slots { Line 10151  sub get_future_slots {
                 }                  }
                 $reservable_now{$slot} = {                  $reservable_now{$slot} = {
                                            symb       => $symb,                                             symb       => $symb,
                                            endreserve => $lastres,                                             endreserve => $lastres
                                            uniqueperiod => $uniqueperiod,     
                                          };                                           };
             } elsif (($startreserve > $now) &&              } elsif (($startreserve > $now) &&
                      (!$endreserve || $endreserve > $startreserve)) {                       (!$endreserve || $endreserve > $startreserve)) {
                 $future_reservable{$slot} = {                  $future_reservable{$slot} = {
                                               symb         => $symb,                                                symb         => $symb,
                                               startreserve => $startreserve,                                                startreserve => $startreserve
                                               uniqueperiod => $uniqueperiod,  
                                             };                                              };
             }              }
         }          }
Line 10621  sub ask_for_embedded_content { Line 10338  sub ask_for_embedded_content {
         $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};          $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};          $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
     }      }
     if (($actionurl eq '/adm/portfolio') ||      if (($actionurl eq '/adm/portfolio') || 
         ($actionurl eq '/adm/coursegrp_portfolio')) {          ($actionurl eq '/adm/coursegrp_portfolio')) {
         my $current_path='/';          my $current_path='/';
         if ($env{'form.currentpath'}) {          if ($env{'form.currentpath'}) {
Line 10653  sub ask_for_embedded_content { Line 10370  sub ask_for_embedded_content {
             $toplevel = $url;              $toplevel = $url;
             if ($args->{'context'} eq 'paste') {              if ($args->{'context'} eq 'paste') {
                 ($cdom,$cnum) = ($url =~ m{^\Q/uploaded/\E($match_domain)/($match_courseid)/});                  ($cdom,$cnum) = ($url =~ m{^\Q/uploaded/\E($match_domain)/($match_courseid)/});
                 ($path) =                  ($path) = 
                     ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});                      ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});
                 $fileloc = &Apache::lonnet::filelocation('',$toplevel);                  $fileloc = &Apache::lonnet::filelocation('',$toplevel);
                 $fileloc =~ s{^/}{};                  $fileloc =~ s{^/}{};
             }              }
         }          }
     } elsif ($actionurl eq '/adm/dependencies') {      } elsif ($actionurl eq '/adm/dependencies')  {
         if ($env{'request.course.id'} ne '') {          if ($env{'request.course.id'} ne '') {
             if (ref($args) eq 'HASH') {              if (ref($args) eq 'HASH') {
                 $url = $args->{'docs_url'};                  $url = $args->{'docs_url'};
                 $title = $args->{'docs_title'};                  $title = $args->{'docs_title'};
                 $toplevel = $url;                  $toplevel = $url; 
                 unless ($toplevel =~ m{^/}) {                  unless ($toplevel =~ m{^/}) {
                     $toplevel = "/$url";                      $toplevel = "/$url";
                 }                  }
Line 10743  sub ask_for_embedded_content { Line 10460  sub ask_for_embedded_content {
     my $dirptr = 16384;      my $dirptr = 16384;
     foreach my $path (keys(%subdependencies)) {      foreach my $path (keys(%subdependencies)) {
         $currsubfile{$path} = {};          $currsubfile{$path} = {};
         if (($actionurl eq '/adm/portfolio') ||          if (($actionurl eq '/adm/portfolio') || 
             ($actionurl eq '/adm/coursegrp_portfolio')) {               ($actionurl eq '/adm/coursegrp_portfolio')) {
             my ($sublistref,$listerror) =              my ($sublistref,$listerror) =
                 &Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);                  &Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);
             if (ref($sublistref) eq 'ARRAY') {              if (ref($sublistref) eq 'ARRAY') {
Line 10886  sub ask_for_embedded_content { Line 10603  sub ask_for_embedded_content {
         $counter = scalar(keys(%existing));          $counter = scalar(keys(%existing));
         $numpathchg = scalar(keys(%pathchanges));          $numpathchg = scalar(keys(%pathchanges));
         return ($output,$counter,$numpathchg,\%existing);          return ($output,$counter,$numpathchg,\%existing);
     } elsif (($actionurl eq "/public/$cdom/$cnum/syllabus") &&      } elsif (($actionurl eq "/public/$cdom/$cnum/syllabus") && 
              (ref($args) eq 'HASH') && ($args->{'context'} eq 'rewrites')) {               (ref($args) eq 'HASH') && ($args->{'context'} eq 'rewrites')) {
         $counter = scalar(keys(%existing));          $counter = scalar(keys(%existing));
         $numpathchg = scalar(keys(%pathchanges));          $numpathchg = scalar(keys(%pathchanges));
Line 11115  sub ask_for_embedded_content { Line 10832  sub ask_for_embedded_content {
   
 Performs clean-up of directories, subdirectories and filename in an  Performs clean-up of directories, subdirectories and filename in an
 embedded object, referenced in an HTML file which is being uploaded  embedded object, referenced in an HTML file which is being uploaded
 to a course or portfolio, where  to a course or portfolio, where 
 "Upload embedded images/multimedia files if HTML file" checkbox was  "Upload embedded images/multimedia files if HTML file" checkbox was
 checked.  checked.
   
Line 11134  sub clean_path { Line 10851  sub clean_path {
         @contents = ($embed_file);          @contents = ($embed_file);
     }      }
     my $lastidx = scalar(@contents)-1;      my $lastidx = scalar(@contents)-1;
     for (my $i=0; $i<=$lastidx; $i++) {      for (my $i=0; $i<=$lastidx; $i++) { 
         $contents[$i]=~s{\\}{/}g;          $contents[$i]=~s{\\}{/}g;
         $contents[$i]=~s/\s+/\_/g;          $contents[$i]=~s/\s+/\_/g;
         $contents[$i]=~s{[^/\w\.\-]}{}g;          $contents[$i]=~s{[^/\w\.\-]}{}g;
Line 11473  sub modify_html_refs { Line 11190  sub modify_html_refs {
     }      }
     my (%allfiles,%codebase,$output,$content);      my (%allfiles,%codebase,$output,$content);
     my @changes = &get_env_multiple('form.namechange');      my @changes = &get_env_multiple('form.namechange');
     unless ((@changes > 0)  || ($context eq 'syllabus')) {      unless ((@changes > 0) || ($context eq 'syllabus')) {
         if (wantarray) {          if (wantarray) {
             return ('',0,0);               return ('',0,0); 
         } else {          } else {
Line 11505  sub modify_html_refs { Line 11222  sub modify_html_refs {
                 return;                  return;
             }              }
         }           } 
         if (open(my $fh,'<',$container)) {          if (open(my $fh,"<$container")) {
             $content = join('', <$fh>);              $content = join('', <$fh>);
             close($fh);              close($fh);
         } else {          } else {
Line 11570  sub modify_html_refs { Line 11287  sub modify_html_refs {
                         }                          }
                     }                      }
                 } else {                  } else {
                     if (open(my $fh,'>',$container)) {                      if (open(my $fh,">$container")) {
                         print $fh $content;                          print $fh $content;
                         close($fh);                          close($fh);
                         $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',                          $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',
Line 11608  sub modify_html_refs { Line 11325  sub modify_html_refs {
                         }                          }
                     }                      }
                     if ($rewrites) {                      if ($rewrites) {
                         my $saveresult;                          my $saveresult; 
                         my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);                          my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
                         if ($url eq $container) {                          if ($url eq $container) {
                             my ($fname) = ($container =~ m{/([^/]+)$});                              my ($fname) = ($container =~ m{/([^/]+)$});
Line 12087  sub decompress_uploaded_file { Line 11804  sub decompress_uploaded_file {
   
 sub process_decompression {  sub process_decompression {
     my ($docudom,$docuname,$file,$destination,$dir_root,$hiddenelem) = @_;      my ($docudom,$docuname,$file,$destination,$dir_root,$hiddenelem) = @_;
     unless (($dir_root eq '/userfiles') && ($destination =~ m{^(docs|supplemental)/(default|\d+)/\d+$})) {  
         return '<p class="LC_error">'.&mt('Not extracted.').'<br />'.  
                &mt('Unexpected file path.').'</p>'."\n";  
     }  
     unless (($docudom =~ /^$match_domain$/) && ($docuname =~ /^$match_courseid$/)) {  
         return '<p class="LC_error">'.&mt('Not extracted.').'<br />'.  
                &mt('Unexpected course context.').'</p>'."\n";  
     }  
     unless ($file eq &Apache::lonnet::clean_filename($file)) {  
         return '<p class="LC_error">'.&mt('Not extracted.').'<br />'.  
                &mt('Filename contained unexpected characters.').'</p>'."\n";  
     }  
     my ($dir,$error,$warning,$output);      my ($dir,$error,$warning,$output);
     if ($file !~ /\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/i) {      if ($file !~ /\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/i) {
         $error = &mt('Filename not a supported archive file type.').          $error = &mt('Filename not a supported archive file type.').
Line 12133  sub process_decompression { Line 11838  sub process_decompression {
                 }                  }
             }              }
             my $numskip = scalar(@to_skip);              my $numskip = scalar(@to_skip);
             my $numoverwrite = scalar(@to_overwrite);              if (($numskip > 0) && 
             if (($numskip) && (!$numoverwrite)) {                  ($numskip == $env{'form.archive_itemcount'})) {
                 $warning = &mt('All items in the archive file already exist, and no overwriting of existing files has been requested.');                           $warning = &mt('All items in the archive file already exist, and no overwriting of existing files has been requested.');         
             } elsif ($dir eq '') {              } elsif ($dir eq '') {
                 $error = &mt('Directory containing archive file unavailable.');                  $error = &mt('Directory containing archive file unavailable.');
             } elsif (!$error) {              } elsif (!$error) {
                 my ($decompressed,$display);                  my ($decompressed,$display);
                 if (($numskip) || ($numoverwrite)) {                  if ($numskip > 0) {
                     my $tempdir = time.'_'.$$.int(rand(10000));                      my $tempdir = time.'_'.$$.int(rand(10000));
                     mkdir("$dir/$tempdir",0755);                      mkdir("$dir/$tempdir",0755);
                     if (&File::Copy::move("$dir/$file","$dir/$tempdir/$file")) {                      system("mv $dir/$file $dir/$tempdir/$file");
                         ($decompressed,$display) =                      ($decompressed,$display) = 
                             &decompress_uploaded_file($file,"$dir/$tempdir");                          &decompress_uploaded_file($file,"$dir/$tempdir");
                         foreach my $item (@to_skip) {                      foreach my $item (@to_skip) {
                             if (($item ne '') && ($item !~ /\.\./)) {                          if (($item ne '') && ($item !~ /\.\./)) {
                                 if (-f "$dir/$tempdir/$item") {                              if (-f "$dir/$tempdir/$item") { 
                                     unlink("$dir/$tempdir/$item");                                  unlink("$dir/$tempdir/$item");
                                 } elsif (-d "$dir/$tempdir/$item") {                              } elsif (-d "$dir/$tempdir/$item") {
                                     &File::Path::remove_tree("$dir/$tempdir/$item",{ safe => 1 });                                  system("rm -rf $dir/$tempdir/$item");
                                 }  
                             }  
                         }  
                         foreach my $item (@to_overwrite) {  
                             if ((-e "$dir/$tempdir/$item") && (-e "$dir/$item")) {  
                                 if (($item ne '') && ($item !~ /\.\./)) {  
                                     if (-f "$dir/$item") {  
                                         unlink("$dir/$item");  
                                     } elsif (-d "$dir/$item") {  
                                         &File::Path::remove_tree("$dir/$item",{ safe => 1 });  
                                     }  
                                     &File::Copy::move("$dir/$tempdir/$item","$dir/$item");  
                                 }  
                             }                              }
                         }                          }
                         if (&File::Copy::move("$dir/$tempdir/$file","$dir/$file")) {  
                             &File::Path::remove_tree("$dir/$tempdir",{ safe => 1 });  
                         }  
                     }                      }
                       system("mv $dir/$tempdir/* $dir");
                       rmdir("$dir/$tempdir");   
                 } else {                  } else {
                     ($decompressed,$display) =                       ($decompressed,$display) = 
                         &decompress_uploaded_file($file,$dir);                          &decompress_uploaded_file($file,$dir);
Line 12244  sub process_decompression { Line 11935  sub process_decompression {
                                     $env{'form.archive_title_'.$i} = $env{'form.camtasia_foldername'};                                      $env{'form.archive_title_'.$i} = $env{'form.camtasia_foldername'};
                                     $displayed{'folder'} = $i;                                      $displayed{'folder'} = $i;
                                 } elsif ((($item eq "$contents[0]/index.html") && ($version == 6)) ||                                  } elsif ((($item eq "$contents[0]/index.html") && ($version == 6)) ||
                                          (($item eq "$contents[0]/$contents[0]".'.html') && ($version == 8))) {                                           (($item eq "$contents[0]/$contents[0]".'.html') && ($version == 8))) { 
                                     $env{'form.archive_'.$i} = 'display';                                      $env{'form.archive_'.$i} = 'display';
                                     $env{'form.archive_title_'.$i} = $env{'form.camtasia_moviename'};                                      $env{'form.archive_title_'.$i} = $env{'form.camtasia_moviename'};
                                     $displayed{'web'} = $i;                                      $displayed{'web'} = $i;
Line 12674  END Line 12365  END
 sub process_extracted_files {  sub process_extracted_files {
     my ($context,$docudom,$docuname,$destination,$dir_root,$hiddenelem) = @_;      my ($context,$docudom,$docuname,$destination,$dir_root,$hiddenelem) = @_;
     my $numitems = $env{'form.archive_count'};      my $numitems = $env{'form.archive_count'};
     return if ((!$numitems) || ($numitems =~ /\D/));      return unless ($numitems);
     my @ids=&Apache::lonnet::current_machine_ids();      my @ids=&Apache::lonnet::current_machine_ids();
     my ($prefix,$pathtocheck,$dir,$ishome,$error,$warning,%toplevelitems,%is_dir,      my ($prefix,$pathtocheck,$dir,$ishome,$error,$warning,%toplevelitems,%is_dir,
         %folders,%containers,%mapinner,%prompttofetch);          %folders,%containers,%mapinner,%prompttofetch);
Line 12687  sub process_extracted_files { Line 12378  sub process_extracted_files {
     } else {      } else {
         $prefix = $Apache::lonnet::perlvar{'lonDocRoot'};          $prefix = $Apache::lonnet::perlvar{'lonDocRoot'};
         $pathtocheck = "$dir_root/$docudom/$docuname/$destination";          $pathtocheck = "$dir_root/$docudom/$docuname/$destination";
         $dir = "$dir_root/$docudom/$docuname";          $dir = "$dir_root/$docudom/$docuname";    
     }      }
     my $currdir = "$dir_root/$destination";      my $currdir = "$dir_root/$destination";
     (my $docstype,$mapinner{'0'}) = ($destination =~ m{^(docs|supplemental)/(\w+)/});      (my $docstype,$mapinner{'0'}) = ($destination =~ m{^(docs|supplemental)/(\w+)/});
Line 12696  sub process_extracted_files { Line 12387  sub process_extracted_files {
         $folders{'0'} = $items[-2];          $folders{'0'} = $items[-2];
         if ($env{'form.folderpath'} =~ /\:1$/) {          if ($env{'form.folderpath'} =~ /\:1$/) {
             $containers{'0'}='page';              $containers{'0'}='page';
         } else {          } else {  
             $containers{'0'}='sequence';              $containers{'0'}='sequence';
         }          }
     }      }
Line 12776  sub process_extracted_files { Line 12467  sub process_extracted_files {
                                                         '.'.$containers{$outer},1,1);                                                          '.'.$containers{$outer},1,1);
                             $newseqid{$i} = $newidx;                              $newseqid{$i} = $newidx;
                             unless ($errtext) {                              unless ($errtext) {
                                 $result .=  '<li>'.&mt('Folder: [_1] added to course',                                  $result .=  '<li>'.&mt('Folder: [_1] added to course',$docstitle).'</li>'."\n";
                                                        &HTML::Entities::encode($docstitle,'<>&"')).  
                                             '</li>'."\n";  
                             }                              }
                         }                          }
                     } else {                      } else {
Line 12787  sub process_extracted_files { Line 12476  sub process_extracted_files {
                             my $url = '/uploaded/'.$docudom.'/'.$docuname.'/'.                              my $url = '/uploaded/'.$docudom.'/'.$docuname.'/'.
                                       $docstype.'/'.$mapinner{$outer}.'/'.$newidx.'/'.                                        $docstype.'/'.$mapinner{$outer}.'/'.$newidx.'/'.
                                       $title;                                        $title;
                             if (($outer !~ /\D/) && ($mapinner{$outer} !~ /\D/) && ($newidx !~ /\D/)) {                              if (!-e "$prefix$dir/$docstype/$mapinner{$outer}") {
                                 if (!-e "$prefix$dir/$docstype/$mapinner{$outer}") {                                  mkdir("$prefix$dir/$docstype/$mapinner{$outer}",0755);
                                     mkdir("$prefix$dir/$docstype/$mapinner{$outer}",0755);                              }
                                 }                              if (!-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx") {
                                 if (!-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx") {                                  mkdir("$prefix$dir/$docstype/$mapinner{$outer}/$newidx");
                                     mkdir("$prefix$dir/$docstype/$mapinner{$outer}/$newidx");                              }
                                 }                              if (-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx") {
                                 if (-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx") {                                  system("mv $prefix$path $prefix$dir/$docstype/$mapinner{$outer}/$newidx/$title");
                                     if (rename("$prefix$path","$prefix$dir/$docstype/$mapinner{$outer}/$newidx/$title")) {                                  $newdest{$i} = "$prefix$dir/$docstype/$mapinner{$outer}/$newidx";
                                         $newdest{$i} = "$prefix$dir/$docstype/$mapinner{$outer}/$newidx";                                  unless ($ishome) {
                                         unless ($ishome) {                                      my $fetch = "$newdest{$i}/$title";
                                             my $fetch = "$newdest{$i}/$title";                                      $fetch =~ s/^\Q$prefix$dir\E//;
                                             $fetch =~ s/^\Q$prefix$dir\E//;                                      $prompttofetch{$fetch} = 1;
                                             $prompttofetch{$fetch} = 1;  
                                         }  
                                     }  
                                 }                                  }
                                 $LONCAPA::map::resources[$newidx]=                              }
                                     $docstitle.':'.$url.':false:normal:res';                              $LONCAPA::map::resources[$newidx]=
                                 push(@LONCAPA::map::order, $newidx);                                  $docstitle.':'.$url.':false:normal:res';
                                 my ($outtext,$errtext)=                              push(@LONCAPA::map::order, $newidx);
                                     &LONCAPA::map::storemap('/uploaded/'.$docudom.'/'.                              my ($outtext,$errtext)=
                                                             $docuname.'/'.$folders{$outer}.                                  &LONCAPA::map::storemap('/uploaded/'.$docudom.'/'.
                                                             '.'.$containers{$outer},1,1);                                                          $docuname.'/'.$folders{$outer}.
                                 unless ($errtext) {                                                          '.'.$containers{$outer},1,1);
                                     if (-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx/$title") {                              unless ($errtext) {
                                         $result .= '<li>'.&mt('File: [_1] added to course',                                  if (-e "$prefix$dir/$docstype/$mapinner{$outer}/$newidx/$title") {
                                                               &HTML::Entities::encode($docstitle,'<>&"')).                                      $result .= '<li>'.&mt('File: [_1] added to course',$docstitle).'</li>'."\n";
                                                    '</li>'."\n";  
                                     }  
                                 }                                  }
                             } else {  
                                 $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',  
                                                 &HTML::Entities::encode($path,'<>&"')).'<br />';  
                             }                              }
                         }                          }
                     }                      }
                 }                  }
             } else {              } else {
                 $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',                  $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).'<br />'; 
                                 &HTML::Entities::encode($path,'<>&"')).'<br />';  
             }              }
         }          }
         for (my $i=1; $i<=$numitems; $i++) {          for (my $i=1; $i<=$numitems; $i++) {
Line 12849  sub process_extracted_files { Line 12529  sub process_extracted_files {
                         }                          }
                         if ($itemidx eq '') {                          if ($itemidx eq '') {
                             $itemidx =  0;                              $itemidx =  0;
                         }                          } 
                         if (grep(/^\Q$referrer{$i}\E$/,@archdirs)) {                          if (grep(/^\Q$referrer{$i}\E$/,@archdirs)) {
                             if ($mapinner{$referrer{$i}}) {                              if ($mapinner{$referrer{$i}}) {
                                 $fullpath = "$prefix$dir/$docstype/$mapinner{$referrer{$i}}";                                  $fullpath = "$prefix$dir/$docstype/$mapinner{$referrer{$i}}";
Line 12888  sub process_extracted_files { Line 12568  sub process_extracted_files {
                         }                          }
                         if ($fullpath ne '') {                          if ($fullpath ne '') {
                             if (-e "$prefix$path") {                              if (-e "$prefix$path") {
                                 unless (rename("$prefix$path","$fullpath/$title")) {                                  system("mv $prefix$path $fullpath/$title");
                                      $warning .= &mt('Failed to rename dependency').'<br />';  
                                 }  
                             }                              }
                             if (-e "$fullpath/$title") {                              if (-e "$fullpath/$title") {
                                 my $showpath;                                  my $showpath;
Line 12898  sub process_extracted_files { Line 12576  sub process_extracted_files {
                                     $showpath = "$relpath/$title";                                      $showpath = "$relpath/$title";
                                 } else {                                  } else {
                                     $showpath = "/$title";                                      $showpath = "/$title";
                                 }                                  } 
                                 $result .= '<li>'.&mt('[_1] included as a dependency',                                  $result .= '<li>'.&mt('[_1] included as a dependency',$showpath).'</li>'."\n";
                                                       &HTML::Entities::encode($showpath,'<>&"')).                              } 
                                            '</li>'."\n";  
                             }  
                             unless ($ishome) {                              unless ($ishome) {
                                 my $fetch = "$fullpath/$title";                                  my $fetch = "$fullpath/$title";
                                 $fetch =~ s/^\Q$prefix$dir\E//;                                  $fetch =~ s/^\Q$prefix$dir\E//; 
                                 $prompttofetch{$fetch} = 1;                                  $prompttofetch{$fetch} = 1;
                             }                              }
                         }                          }
                     }                      }
                 } elsif ($env{'form.archive_'.$referrer{$i}} eq 'discard') {                  } elsif ($env{'form.archive_'.$referrer{$i}} eq 'discard') {
                     $warning .= &mt('[_1] is a dependency of [_2], which was discarded.',                      $warning .= &mt('[_1] is a dependency of [_2], which was discarded.',
                                     &HTML::Entities::encode($path,'<>&"'),                                      $path,$env{'form.archive_content_'.$referrer{$i}}).'<br />';
                                     &HTML::Entities::encode($env{'form.archive_content_'.$referrer{$i}},'<>&"')).  
                                 '<br />';  
                 }                  }
             } else {              } else {
                 $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',                  $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).'<br />'; 
                                 &HTML::Entities::encode($path)).'<br />';  
             }              }
         }          }
         if (keys(%todelete)) {          if (keys(%todelete)) {
Line 13192  sub upfile_store { Line 12865  sub upfile_store {
     $env{'form.upfile'}=~s/\n+/\n/gs;      $env{'form.upfile'}=~s/\n+/\n/gs;
     $env{'form.upfile'}=~s/\n+$//gs;      $env{'form.upfile'}=~s/\n+$//gs;
   
     my $datatoken = &valid_datatoken($env{'user.name'}.'_'.$env{'user.domain'}.      my $datatoken=$env{'user.name'}.'_'.$env{'user.domain'}.
                              '_enroll_'.$env{'request.course.id'}.'_'.   '_enroll_'.$env{'request.course.id'}.'_'.time.'_'.$$;
                                      time.'_'.$$);  
     return if ($datatoken eq '');  
     {      {
         my $datafile = $r->dir_config('lonDaemons').          my $datafile = $r->dir_config('lonDaemons').
                            '/tmp/'.$datatoken.'.tmp';                             '/tmp/'.$datatoken.'.tmp';
         if ( open(my $fh,'>',$datafile) ) {          if ( open(my $fh,">$datafile") ) {
             print $fh $env{'form.upfile'};              print $fh $env{'form.upfile'};
             close($fh);              close($fh);
         }          }
Line 13209  sub upfile_store { Line 12880  sub upfile_store {
   
 =pod  =pod
   
 =item * &load_tmp_file($r,$datatoken)  =item * &load_tmp_file($r)
   
 Load uploaded file from tmp, $r should be the HTTP Request object,  Load uploaded file from tmp, $r should be the HTTP Request object,
 $datatoken is the name to assign to the temporary file.  needs $env{'form.datatoken'},
 sets $env{'form.upfile'} to the contents of the file  sets $env{'form.upfile'} to the contents of the file
   
 =cut  =cut
   
 sub load_tmp_file {  sub load_tmp_file {
     my ($r,$datatoken) = @_;      my $r=shift;
     return if ($datatoken eq '');  
     my @studentdata=();      my @studentdata=();
     {      {
         my $studentfile = $r->dir_config('lonDaemons').          my $studentfile = $r->dir_config('lonDaemons').
                               '/tmp/'.$datatoken.'.tmp';                                '/tmp/'.$env{'form.datatoken'}.'.tmp';
         if ( open(my $fh,'<',$studentfile) ) {          if ( open(my $fh,"<$studentfile") ) {
             @studentdata=<$fh>;              @studentdata=<$fh>;
             close($fh);              close($fh);
         }          }
Line 13232  sub load_tmp_file { Line 12902  sub load_tmp_file {
     $env{'form.upfile'}=join('',@studentdata);      $env{'form.upfile'}=join('',@studentdata);
 }  }
   
 sub valid_datatoken {  
     my ($datatoken) = @_;  
     if ($datatoken =~ /^$match_username\_$match_domain\_enroll_(|$match_domain\_$match_courseid)\_\d+_\d+$/) {  
         return $datatoken;  
     }  
     return;  
 }  
   
 =pod  =pod
   
 =item * &upfile_record_sep()  =item * &upfile_record_sep()
Line 13680  sub DrawBarGraph { Line 13342  sub DrawBarGraph {
         @Labels = @$labels;          @Labels = @$labels;
     } else {      } else {
         for (my $i=0;$i<@{$Values[0]};$i++) {          for (my $i=0;$i<@{$Values[0]};$i++) {
             push(@Labels,$i+1);              push (@Labels,$i+1);
         }          }
     }      }
     #      #
Line 14119  generated by lonerrorhandler.pm, CHECKRP Line 13781  generated by lonerrorhandler.pm, CHECKRP
 lonsupportreq.pm, loncoursequeueadmin.pm, searchcat.pl respectively.  lonsupportreq.pm, loncoursequeueadmin.pm, searchcat.pl respectively.
   
 Inputs:  Inputs:
 defmail (scalar - email address of default recipient),  defmail (scalar - email address of default recipient), 
 mailing type (scalar: errormail, packagesmail, helpdeskmail,  mailing type (scalar: errormail, packagesmail, helpdeskmail,
 requestsmail, updatesmail, or idconflictsmail).  requestsmail, updatesmail, or idconflictsmail).
   
 defdom (domain for which to retrieve configuration settings),  defdom (domain for which to retrieve configuration settings),
   
 origmail (scalar - email address of recipient from loncapa.conf,  origmail (scalar - email address of recipient from loncapa.conf, 
 i.e., predates configuration by DC via domainprefs.pm  i.e., predates configuration by DC via domainprefs.pm 
   
 $requname username of requester (if mailing type is helpdeskmail)  
   
 $requdom domain of requester (if mailing type is helpdeskmail)  
   
 $reqemail e-mail address of requester (if mailing type is helpdeskmail)  
   
   
 Returns: comma separated list of addresses to which to send e-mail.  Returns: comma separated list of addresses to which to send e-mail.
   
Line 14144  Returns: comma separated list of address Line 13799  Returns: comma separated list of address
 ############################################################  ############################################################
 ############################################################  ############################################################
 sub build_recipient_list {  sub build_recipient_list {
     my ($defmail,$mailing,$defdom,$origmail,$requname,$requdom,$reqemail) = @_;      my ($defmail,$mailing,$defdom,$origmail) = @_;
     my @recipients;      my @recipients;
     my ($otheremails,$lastresort,$allbcc,$addtext);      my $otheremails;
     my %domconfig =      my %domconfig =
         &Apache::lonnet::get_dom('configuration',['contacts'],$defdom);           &Apache::lonnet::get_dom('configuration',['contacts'],$defdom);
     if (ref($domconfig{'contacts'}) eq 'HASH') {      if (ref($domconfig{'contacts'}) eq 'HASH') {
         if (exists($domconfig{'contacts'}{$mailing})) {          if (exists($domconfig{'contacts'}{$mailing})) {
             if (ref($domconfig{'contacts'}{$mailing}) eq 'HASH') {              if (ref($domconfig{'contacts'}{$mailing}) eq 'HASH') {
Line 14160  sub build_recipient_list { Line 13815  sub build_recipient_list {
                             push(@recipients,$addr);                              push(@recipients,$addr);
                         }                          }
                     }                      }
                 }                      $otheremails = $domconfig{'contacts'}{$mailing}{'others'};
                 $otheremails = $domconfig{'contacts'}{$mailing}{'others'};  
                 if ($mailing eq 'helpdeskmail') {  
                     if ($domconfig{'contacts'}{$mailing}{'bcc'}) {  
                         my @bccs = split(/,/,$domconfig{'contacts'}{$mailing}{'bcc'});  
                         my @ok_bccs;  
                         foreach my $bcc (@bccs) {  
                             $bcc =~ s/^\s+//g;  
                             $bcc =~ s/\s+$//g;  
                             if ($bcc =~ m/^[^\@]+\@[^\@]+$/) {  
                                 if (!(grep(/^\Q$bcc\E$/,@ok_bccs))) {  
                                     push(@ok_bccs,$bcc);  
                                 }  
                             }  
                         }  
                         if (@ok_bccs > 0) {  
                             $allbcc = join(', ',@ok_bccs);  
                         }  
                     }  
                     $addtext = $domconfig{'contacts'}{$mailing}{'include'};  
                 }                  }
             }              }
         } elsif ($origmail ne '') {          } elsif ($origmail ne '') {
             $lastresort = $origmail;              push(@recipients,$origmail);
         }  
         if ($mailing eq 'helpdeskmail') {  
             if ((ref($domconfig{'contacts'}{'overrides'}) eq 'HASH') &&  
                 (keys(%{$domconfig{'contacts'}{'overrides'}}))) {  
                 my ($inststatus,$inststatus_checked);  
                 if (($env{'user.name'} ne '') && ($env{'user.domain'} ne '') &&  
                     ($env{'user.domain'} ne 'public')) {  
                     $inststatus_checked = 1;  
                     $inststatus = $env{'environment.inststatus'};  
                 }  
                 unless ($inststatus_checked) {  
                     if (($requname ne '') && ($requdom ne '')) {  
                         if (($requname =~ /^$match_username$/) &&  
                             ($requdom =~ /^$match_domain$/) &&  
                             (&Apache::lonnet::domain($requdom))) {  
                             my $requhome = &Apache::lonnet::homeserver($requname,  
                                                                       $requdom);  
                             unless ($requhome eq 'no_host') {  
                                 my %userenv = &Apache::lonnet::userenvironment($requdom,$requname,'inststatus');  
                                 $inststatus = $userenv{'inststatus'};  
                                 $inststatus_checked = 1;  
                             }  
                         }  
                     }  
                 }  
                 unless ($inststatus_checked) {  
                     if ($reqemail =~ /^[^\@]+\@[^\@]+$/) {  
                         my %srch = (srchby     => 'email',  
                                     srchdomain => $defdom,  
                                     srchterm   => $reqemail,  
                                     srchtype   => 'exact');  
                         my %srch_results = &Apache::lonnet::usersearch(\%srch);  
                         foreach my $uname (keys(%srch_results)) {  
                             if (ref($srch_results{$uname}{'inststatus'}) eq 'ARRAY') {  
                                 $inststatus = join(',',@{$srch_results{$uname}{'inststatus'}});  
                                 $inststatus_checked = 1;  
                                 last;  
                             }  
                         }  
                         unless ($inststatus_checked) {  
                             my ($dirsrchres,%srch_results) = &Apache::lonnet::inst_directory_query(\%srch);  
                             if ($dirsrchres eq 'ok') {  
                                 foreach my $uname (keys(%srch_results)) {  
                                     if (ref($srch_results{$uname}{'inststatus'}) eq 'ARRAY') {  
                                         $inststatus = join(',',@{$srch_results{$uname}{'inststatus'}});  
                                         $inststatus_checked = 1;  
                                         last;  
                                     }  
                                 }  
                             }  
                         }  
                     }  
                 }  
                 if ($inststatus ne '') {  
                     foreach my $status (split(/\:/,$inststatus)) {  
                         if (ref($domconfig{'contacts'}{'overrides'}{$status}) eq 'HASH') {  
                             my @contacts = ('adminemail','supportemail');  
                             foreach my $item (@contacts) {  
                                 if ($domconfig{'contacts'}{'overrides'}{$status}{$item}) {  
                                     my $addr = $domconfig{'contacts'}{'overrides'}{$status};  
                                     if (!grep(/^\Q$addr\E$/,@recipients)) {  
                                         push(@recipients,$addr);  
                                     }  
                                 }  
                             }  
                             $otheremails = $domconfig{'contacts'}{'overrides'}{$status}{'others'};  
                             if ($domconfig{'contacts'}{'overrides'}{$status}{'bcc'}) {  
                                 my @bccs = split(/,/,$domconfig{'contacts'}{'overrides'}{$status}{'bcc'});  
                                 my @ok_bccs;  
                                 foreach my $bcc (@bccs) {  
                                     $bcc =~ s/^\s+//g;  
                                     $bcc =~ s/\s+$//g;  
                                     if ($bcc =~ m/^[^\@]+\@[^\@]+$/) {  
                                         if (!(grep(/^\Q$bcc\E$/,@ok_bccs))) {  
                                             push(@ok_bccs,$bcc);  
                                         }  
                                     }  
                                 }  
                                 if (@ok_bccs > 0) {  
                                     $allbcc = join(', ',@ok_bccs);  
                                 }  
                             }  
                             $addtext = $domconfig{'contacts'}{'overrides'}{$status}{'include'};  
                             last;  
                         }  
                     }  
                 }  
             }  
         }          }
     } elsif ($origmail ne '') {      } elsif ($origmail ne '') {
         $lastresort = $origmail;          push(@recipients,$origmail);
     }  
   
     if (($mailing eq 'helpdeskmail') && ($lastresort ne '')) {  
         unless (grep(/^\Q$defdom\E$/,&Apache::lonnet::current_machine_domains())) {  
             my $lonhost = $Apache::lonnet::perlvar{'lonHostID'};  
             my $machinedom = $Apache::lonnet::perlvar{'lonDefDomain'};  
             my %what = (  
                           perlvar => 1,  
                        );  
             my $primary = &Apache::lonnet::domain($defdom,'primary');  
             if ($primary) {  
                 my $gotaddr;  
                 my ($result,$returnhash) =  
                     &Apache::lonnet::get_remote_globals($primary,{ perlvar => 1 });  
                 if (($result eq 'ok') && (ref($returnhash) eq 'HASH')) {  
                     if ($returnhash->{'lonSupportEMail'} =~ /^[^\@]+\@[^\@]+$/) {  
                         $lastresort = $returnhash->{'lonSupportEMail'};  
                         $gotaddr = 1;  
                     }  
                 }  
                 unless ($gotaddr) {  
                     my $uintdom = &Apache::lonnet::internet_dom($primary);  
                     my $intdom = &Apache::lonnet::internet_dom($lonhost);  
                     unless ($uintdom eq $intdom) {  
                         my %domconfig =  
                             &Apache::lonnet::get_dom('configuration',['contacts'],$machinedom);  
                         if (ref($domconfig{'contacts'}) eq 'HASH') {  
                             if (ref($domconfig{'contacts'}{'otherdomsmail'}) eq 'HASH') {  
                                 my @contacts = ('adminemail','supportemail');  
                                 foreach my $item (@contacts) {  
                                     if ($domconfig{'contacts'}{'otherdomsmail'}{$item}) {  
                                         my $addr = $domconfig{'contacts'}{$item};  
                                         if (!grep(/^\Q$addr\E$/,@recipients)) {  
                                             push(@recipients,$addr);  
                                         }  
                                     }  
                                 }  
                                 if ($domconfig{'contacts'}{'otherdomsmail'}{'others'}) {  
                                     $otheremails = $domconfig{'contacts'}{'otherdomsmail'}{'others'};  
                                 }  
                                 if ($domconfig{'contacts'}{'otherdomsmail'}{'bcc'}) {  
                                     my @bccs = split(/,/,$domconfig{'contacts'}{'otherdomsmail'}{'bcc'});  
                                     my @ok_bccs;  
                                     foreach my $bcc (@bccs) {  
                                         $bcc =~ s/^\s+//g;  
                                         $bcc =~ s/\s+$//g;  
                                         if ($bcc =~ m/^[^\@]+\@[^\@]+$/) {  
                                             if (!(grep(/^\Q$bcc\E$/,@ok_bccs))) {  
                                                 push(@ok_bccs,$bcc);  
                                             }  
                                         }  
                                     }  
                                     if (@ok_bccs > 0) {  
                                         $allbcc = join(', ',@ok_bccs);  
                                     }  
                                 }  
                                 $addtext = $domconfig{'contacts'}{'otherdomsmail'}{'include'};  
                             }  
                         }  
                     }  
                 }  
             }  
         }  
     }      }
     if (defined($defmail)) {      if (defined($defmail)) {
         if ($defmail ne '') {          if ($defmail ne '') {
Line 14357  sub build_recipient_list { Line 13842  sub build_recipient_list {
             }              }
         }          }
     }      }
     if ($mailing eq 'helpdeskmail') {      my $recipientlist = join(',',@recipients); 
         if ((!@recipients) && ($lastresort ne '')) {      return $recipientlist;
             push(@recipients,$lastresort);  
         }  
     } elsif ($lastresort ne '') {  
         if (!grep(/^\Q$lastresort\E$/,@recipients)) {  
             push(@recipients,$lastresort);  
         }  
     }  
     my $recipientlist = join(',',@recipients);  
     if (wantarray) {  
         return ($recipientlist,$allbcc,$addtext);  
     } else {  
         return $recipientlist;  
     }  
 }  }
   
 ############################################################  ############################################################
Line 14595  currcat - scalar with an & separated lis Line 14067  currcat - scalar with an & separated lis
   
 type    - scalar contains course type (Course or Community).  type    - scalar contains course type (Course or Community).
   
 disabled - scalar (optional) contains disabled="disabled" if input elements are  
            to be readonly (e.g., Domain Helpdesk role viewing course settings).  
   
 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,$type,$disabled) = @_;      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 14639  sub assign_categories_table { Line 14108  sub assign_categories_table {
                     }                      }
                     $table .= '<tr '.$css_class.'><td><span class="LC_nobreak">'.                      $table .= '<tr '.$css_class.'><td><span class="LC_nobreak">'.
                               '<input type="checkbox" name="usecategory" value="'.                                '<input type="checkbox" name="usecategory" value="'.
                               $item.'"'.$checked.$disabled.' />'.$parent_title.'</span>'.                                $item.'"'.$checked.' />'.$parent_title.'</span>'.
                               '<input type="hidden" name="catname" value="'.$parent.'" /></td>';                                '<input type="hidden" name="catname" value="'.$parent.'" /></td>';
                     my $depth = 1;                      my $depth = 1;
                     push(@path,$parent);                      push(@path,$parent);
                     $table .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories,$disabled);                      $table .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories);
                     pop(@path);                      pop(@path);
                     $table .= '</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 ++;
Line 14682  path - Array containing all categories b Line 14151  path - Array containing all categories b
   
 currcategories - reference to array of current categories assigned to the course  currcategories - reference to array of current categories assigned to the course
   
 disabled - scalar (optional) contains disabled="disabled" if input elements are  
            to be readonly (e.g., Domain Helpdesk role viewing course settings).  
   
 Returns: $output (markup to be displayed).  Returns: $output (markup to be displayed).
   
 =cut  =cut
   
 sub assign_category_rows {  sub assign_category_rows {
     my ($itemcount,$cats,$depth,$parent,$path,$currcategories,$disabled) = @_;      my ($itemcount,$cats,$depth,$parent,$path,$currcategories) = @_;
     my ($text,$name,$item,$chgstr);      my ($text,$name,$item,$chgstr);
     if (ref($cats) eq 'ARRAY') {      if (ref($cats) eq 'ARRAY') {
         my $maxdepth = scalar(@{$cats});          my $maxdepth = scalar(@{$cats});
Line 14713  sub assign_category_rows { Line 14179  sub assign_category_rows {
                     }                      }
                     $text .= '<tr><td><span class="LC_nobreak"><label>'.                      $text .= '<tr><td><span class="LC_nobreak"><label>'.
                              '<input type="checkbox" name="usecategory" value="'.                               '<input type="checkbox" name="usecategory" value="'.
                              $item.'"'.$checked.$disabled.' />'.$name.'</label></span>'.                               $item.'"'.$checked.' />'.$name.'</label></span>'.
                              '<input type="hidden" name="catname" value="'.$name.'" />'.                               '<input type="hidden" name="catname" value="'.$name.'" />'.
                              '</td><td>';                               '</td><td>';
                     if (ref($path) eq 'ARRAY') {                      if (ref($path) eq 'ARRAY') {
                         push(@{$path},$name);                          push(@{$path},$name);
                         $text .= &assign_category_rows($itemcount,$cats,$deeper,$name,$path,$currcategories,$disabled);                          $text .= &assign_category_rows($itemcount,$cats,$deeper,$name,$path,$currcategories);
                         pop(@{$path});                          pop(@{$path});
                     }                      }
                     $text .= '</td></tr>';                      $text .= '</td></tr>';
Line 14866  sub commit_studentrole { Line 14332  sub commit_studentrole {
                     }                      }
                 }                  }
             } else {              } else {
                 if ($secchange) {                         if ($secchange) { 
                     $$logmsg .= &mt('Error when attempting section change for [_1] from old section "[_2]" to new section: "[_3]" in course [_4] -error:',$uname,$oldsec,$sec,$cid).' '.$modify_section_result.$linefeed;                      $$logmsg .= &mt('Error when attempting section change for [_1] from old section "[_2]" to new section: "[_3]" in course [_4] -error:',$uname,$oldsec,$sec,$cid).' '.$modify_section_result.$linefeed;
                 } else {                  } else {
                     $$logmsg .= &mt('Error when attempting to modify role for [_1] for section: "[_2]" in course [_3] -error:',$uname,$sec,$cid).' '.$modify_section_result.$linefeed;                      $$logmsg .= &mt('Error when attempting to modify role for [_1] for section: "[_2]" in course [_3] -error:',$uname,$sec,$cid).' '.$modify_section_result.$linefeed;
Line 14949  sub check_clone { Line 14415  sub check_clone {
                 return ($can_clone, $clonemsg, $cloneid, $clonehome);                  return ($can_clone, $clonemsg, $cloneid, $clonehome);
             }              }
         }          }
  if (($env{'request.role.domain'} eq $args->{'clonedomain'}) &&   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 {
Line 14963  sub check_clone { Line 14429  sub check_clone {
                             if ($args->{'ccdomain'} eq $args->{'clonedomain'}) {                              if ($args->{'ccdomain'} eq $args->{'clonedomain'}) {
                                 $can_clone = 1;                                  $can_clone = 1;
                             }                              }
                         } elsif (($clonehash{'internal.coursecode'}) && ($args->{'crscode'}) &&                          } elsif (($clonehash{'internal.coursecode'}) && ($args->{'crscode'}) && 
                                  ($args->{'clonedomain'} eq  $args->{'course_domain'})) {                                   ($args->{'clonedomain'} eq  $args->{'course_domain'})) {
                             if (&Apache::lonnet::default_instcode_cloning($args->{'clonedomain'},$domdefs{'canclone'},                              if (&Apache::lonnet::default_instcode_cloning($args->{'clonedomain'},$domdefs{'canclone'},
                                                                           $clonehash{'internal.coursecode'},$args->{'crscode'})) {                                                                            $clonehash{'internal.coursecode'},$args->{'crscode'})) {
Line 14978  sub check_clone { Line 14444  sub check_clone {
                     $can_clone = 1;                      $can_clone = 1;
                 } elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) {                  } elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) {
                     $can_clone = 1;                      $can_clone = 1;
                 } elsif (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners)) {  
                     $can_clone = 1;  
                 }                  }
                 unless ($can_clone) {                  unless ($can_clone) {
                     if (($clonehash{'internal.coursecode'}) && ($args->{'crscode'}) &&                      if (($clonehash{'internal.coursecode'}) && ($args->{'crscode'}) && ($args->{'clonedomain'} eq  $args->{'course_domain'})) {
                         ($args->{'clonedomain'} eq  $args->{'course_domain'})) {  
                         my (%gotdomdefaults,%gotcodedefaults);                          my (%gotdomdefaults,%gotcodedefaults);
                         foreach my $cloner (@cloners) {                          foreach my $cloner (@cloners) {
                             if (($cloner ne '*') && ($cloner !~ /^\*\:$match_domain$/) &&                              if (($cloner ne '*') && ($cloner !~ /^\*\:$match_domain$/) &&
Line 15014  sub check_clone { Line 14477  sub check_clone {
                             }                              }
                         }                          }
                     }                      }
                 }                      unless ($can_clone) {
             }                          my $ccrole = 'cc';
             unless ($can_clone) {                          if ($args->{'crstype'} eq 'Community') {
                 my $ccrole = 'cc';                              $ccrole = 'co';
                 if ($args->{'crstype'} eq 'Community') {                          }
                     $ccrole = 'co';                  my %roleshash =
                 }              &Apache::lonnet::get_my_roles($args->{'ccuname'},
                 my %roleshash =                    $args->{'ccdomain'},
                     &Apache::lonnet::get_my_roles($args->{'ccuname'},                                                            'userroles',['active'],[$ccrole],
                                                   $args->{'ccdomain'},                    [$args->{'clonedomain'}]);
                                                   'userroles',['active'],[$ccrole],                  if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':'.$ccrole}) || 
                                                   [$args->{'clonedomain'}]);                              (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
                 if ($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':'.$ccrole}) {                              $can_clone = 1;
                     $can_clone = 1;                          } elsif (&Apache::lonnet::is_course_owner($args->{'clonedomain'},$args->{'clonecourse'},
                 } elsif (&Apache::lonnet::is_course_owner($args->{'clonedomain'},$args->{'clonecourse'},                                                                    $args->{'ccuname'},$args->{'ccdomain'})) {
                                                           $args->{'ccuname'},$args->{'ccdomain'})) {                              $can_clone = 1;
                     $can_clone = 1;                          }
                       }
                 }                  }
             }              }
             unless ($can_clone) {              unless ($can_clone) {
Line 15038  sub check_clone { Line 14502  sub check_clone {
                     $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'});                      $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 {                  } 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'});                      $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 15046  sub check_clone { Line 14510  sub check_clone {
 }  }
   
 sub construct_course {  sub construct_course {
     my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context,      my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context,$cnum,$category,$coderef) = @_;
         $cnum,$category,$coderef) = @_;  
     my $outcome;      my $outcome;
     my $linefeed =  '<br />'."\n";      my $linefeed =  '<br />'."\n";
     if ($context eq 'auto') {      if ($context eq 'auto') {
Line 15195  sub construct_course { Line 14658  sub construct_course {
                 my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$class,$cenv{'internal.courseowner'});                  my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$class,$cenv{'internal.courseowner'});
                 $cenv{'internal.sectionnums'} .= $item.',';                  $cenv{'internal.sectionnums'} .= $item.',';
                 unless ($addcheck eq 'ok') {                  unless ($addcheck eq 'ok') {
                     push(@badclasses,$class);                      push @badclasses, $class;
                 }                  }
             }              }
             $cenv{'internal.sectionnums'} =~ s/,$//;              $cenv{'internal.sectionnums'} =~ s/,$//;
Line 15223  sub construct_course { Line 14686  sub construct_course {
                 my $addcheck =  &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$xl,$cenv{'internal.courseowner'});                  my $addcheck =  &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$xl,$cenv{'internal.courseowner'});
                 $cenv{'internal.crosslistings'} .= $item.',';                  $cenv{'internal.crosslistings'} .= $item.',';
                 unless ($addcheck eq 'ok') {                  unless ($addcheck eq 'ok') {
                     push(@badclasses,$xl);                      push @badclasses, $xl;
                 }                  }
             }              }
             $cenv{'internal.crosslistings'} =~ s/,$//;              $cenv{'internal.crosslistings'} =~ s/,$//;
Line 15258  sub construct_course { Line 14721  sub construct_course {
     }      }
     if (@badclasses > 0) {      if (@badclasses > 0) {
         my %lt=&Apache::lonlocal::texthash(          my %lt=&Apache::lonlocal::texthash(
                 'tclb' => 'The courses listed below were included as sections or crosslistings affiliated with your new LON-CAPA course.',                  'tclb' => 'The courses listed below were included as sections or crosslistings affiliated with your new LON-CAPA course.  However, if automated course roster updates are enabled for this class, these particular sections/crosslistings will not contribute towards enrollment, because the user identified as the course owner for this LON-CAPA course',
                 'howi' => 'However, if automated course roster updates are enabled for this class, these particular sections/crosslistings are not guaranteed to contribute towards enrollment.',                  'dnhr' => 'does not have rights to access enrollment in these classes',
                 'itis' => 'It is possible that rights to access enrollment for these classes will be available through assignment of co-owners.',                  'adby' => 'as determined by the policies of your institution on access to official classlists'
         );          );
         my $badclass_msg = $lt{'tclb'}.$linefeed.$lt{'howi'}.$linefeed.          my $badclass_msg = $cenv{'internal.courseowner'}.') - '.$lt{'dnhr'}.
                            &mt('That is because the user identified as the course owner ([_1]) does not have rights to access enrollment in these classes, as determined by the policies of your institution on access to official classlists',$cenv{'internal.courseowner'}).$linefeed.$lt{'itis'};                             ' ('.$lt{'adby'}.')';
         if ($context eq 'auto') {          if ($context eq 'auto') {
             $outcome .= $badclass_msg.$linefeed;              $outcome .= $badclass_msg.$linefeed;
         } else {  
             $outcome .= '<div class="LC_warning">'.$badclass_msg.$linefeed.'<ul>'."\n";              $outcome .= '<div class="LC_warning">'.$badclass_msg.$linefeed.'<ul>'."\n";
         }              foreach my $item (@badclasses) {
         foreach my $item (@badclasses) {                  if ($context eq 'auto') {
                       $outcome .= " - $item\n";
                   } else {
                       $outcome .= "<li>$item</li>\n";
                   }
               }
             if ($context eq 'auto') {              if ($context eq 'auto') {
                 $outcome .= " - $item\n";                  $outcome .= $linefeed;
             } else {              } else {
                 $outcome .= "<li>$item</li>\n";                  $outcome .= "</ul><br /><br /></div>\n";
             }              }
         }          } 
         if ($context eq 'auto') {  
             $outcome .= $linefeed;  
         } else {  
             $outcome .= "</ul><br /><br /></div>\n";  
         }  
     }      }
     if ($args->{'no_end_date'}) {      if ($args->{'no_end_date'}) {
         $args->{'endaccess'} = 0;          $args->{'endaccess'} = 0;
Line 15312  sub construct_course { Line 14774  sub construct_course {
        if ($args->{'setcontent'}) {         if ($args->{'setcontent'}) {
            $cenv{'question.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};             $cenv{'question.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
        }         }
        if ($args->{'setcomment'}) {  
            $cenv{'comment.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};  
        }  
     }      }
     if ($args->{'reshome'}) {      if ($args->{'reshome'}) {
  $cenv{'reshome'}=$args->{'reshome'}.'/';   $cenv{'reshome'}=$args->{'reshome'}.'/';
Line 15349  sub construct_course { Line 14808  sub construct_course {
             if (ref($crsinfo{$$crsudom.'_'.$$crsunum}) eq 'HASH') {              if (ref($crsinfo{$$crsudom.'_'.$$crsunum}) eq 'HASH') {
                 $crsinfo{$$crsudom.'_'.$$crsunum}{'uniquecode'} = $code;                  $crsinfo{$$crsudom.'_'.$$crsunum}{'uniquecode'} = $code;
                 my $putres = &Apache::lonnet::courseidput($$crsudom,\%crsinfo,$crsuhome,'notime');                  my $putres = &Apache::lonnet::courseidput($$crsudom,\%crsinfo,$crsuhome,'notime');
             }              } 
             if (ref($coderef)) {              if (ref($coderef)) {
                 $$coderef = $code;                  $$coderef = $code;
             }              }
Line 15434  sub make_unique_code { Line 14893  sub make_unique_code {
     my $tries = 0;      my $tries = 0;
     my $gotlock = &Apache::lonnet::newput_dom('uniquecodes',$lockhash,$cdom);      my $gotlock = &Apache::lonnet::newput_dom('uniquecodes',$lockhash,$cdom);
     my ($code,$error);      my ($code,$error);
     
     while (($gotlock ne 'ok') && ($tries<3)) {      while (($gotlock ne 'ok') && ($tries<3)) {
         $tries ++;          $tries ++;
         sleep 1;          sleep 1;
Line 15660  sub init_user_environment { Line 15119  sub init_user_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) {
       } else {
  undef(%userenv);   undef(%userenv);
     }      }
     if (($userenv{'interface'}) && (!$form->{'interface'})) {      if (($userenv{'interface'}) && (!$form->{'interface'})) {
Line 15712  sub init_user_environment { Line 15172  sub init_user_environment {
             $env{'user.noloadbalance'} = $lonhost;              $env{'user.noloadbalance'} = $lonhost;
         }          }
   
         if ($form->{'noloadbalance'}) {          my %is_adv = ( is_adv => $env{'user.adv'} );
             my @hosts = &Apache::lonnet::current_machine_ids();          my %domdef;
             my $hosthere = $form->{'noloadbalance'};  
             if (grep(/^\Q$hosthere\E$/,@hosts)) {  
                 $initial_env{"user.noloadbalance"} = $hosthere;  
                 $env{'user.noloadbalance'} = $hosthere;  
             }  
         }  
   
         unless ($domain eq 'public') {          unless ($domain eq 'public') {
             my %is_adv = ( is_adv => $env{'user.adv'} );              %domdef = &Apache::lonnet::get_domain_defaults($domain);
             my %domdef = &Apache::lonnet::get_domain_defaults($domain);          }
   
             foreach my $tool ('aboutme','blog','webdav','portfolio') {  
                 $userenv{'availabletools.'.$tool} =   
                     &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',  
                                                       undef,\%userenv,\%domdef,\%is_adv);  
             }  
   
             foreach my $crstype ('official','unofficial','community','textbook') {          foreach my $tool ('aboutme','blog','webdav','portfolio') {
                 $userenv{'canrequest.'.$crstype} =              $userenv{'availabletools.'.$tool} = 
                     &Apache::lonnet::usertools_access($username,$domain,$crstype,                  &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',
                                                       'reload','requestcourses',                                                    undef,\%userenv,\%domdef,\%is_adv);
                                                       \%userenv,\%domdef,\%is_adv);          }
             }  
   
             $userenv{'canrequest.author'} =          foreach my $crstype ('official','unofficial','community','textbook') {
                 &Apache::lonnet::usertools_access($username,$domain,'requestauthor',              $userenv{'canrequest.'.$crstype} =
                                                   'reload','requestauthor',                  &Apache::lonnet::usertools_access($username,$domain,$crstype,
                                                     'reload','requestcourses',
                                                   \%userenv,\%domdef,\%is_adv);                                                    \%userenv,\%domdef,\%is_adv);
             my %reqauthor = &Apache::lonnet::get('requestauthor',['author_status','author'],          }
                                                  $domain,$username);  
             my $reqstatus = $reqauthor{'author_status'};          $userenv{'canrequest.author'} =
             if ($reqstatus eq 'approval' || $reqstatus eq 'approved') {              &Apache::lonnet::usertools_access($username,$domain,'requestauthor',
                 if (ref($reqauthor{'author'}) eq 'HASH') {                                          'reload','requestauthor',
                     $userenv{'requestauthorqueued'} = $reqstatus.':'.                                          \%userenv,\%domdef,\%is_adv);
                                                       $reqauthor{'author'}{'timestamp'};          my %reqauthor = &Apache::lonnet::get('requestauthor',['author_status','author'],
                 }                                               $domain,$username);
           my $reqstatus = $reqauthor{'author_status'};
           if ($reqstatus eq 'approval' || $reqstatus eq 'approved') { 
               if (ref($reqauthor{'author'}) eq 'HASH') {
                   $userenv{'requestauthorqueued'} = $reqstatus.':'.
                                                     $reqauthor{'author'}{'timestamp'};
             }              }
         }          }
   
Line 15856  and quotacheck.pl Line 15308  and quotacheck.pl
   
 Inputs:  Inputs:
   
 filterlist - anonymous array of fields to include as potential filters  filterlist - anonymous array of fields to include as potential filters 
   
 crstype - course type  crstype - course type
   
 roleelement - fifth arg in selectcourse_link() populates fifth arg in javascript: opencrsbrowser() function, used  roleelement - fifth arg in selectcourse_link() populates fifth arg in javascript: opencrsbrowser() function, used
               to pop-open a course selector (will contain "extra element").                to pop-open a course selector (will contain "extra element"). 
   
 multelement - if multiple course selections will be allowed, this will be a hidden form element: name: multiple; value: 1  multelement - if multiple course selections will be allowed, this will be a hidden form element: name: multiple; value: 1
   
Line 15877  cloneruname - username of owner of new c Line 15329  cloneruname - username of owner of new c
   
 clonerudom - domain of owner of new course who wants to clone  clonerudom - domain of owner of new course who wants to clone
   
 typeelem - text to use for left column in row containing course type (i.e., Course, Community or Course/Community)  typeelem - text to use for left column in row containing course type (i.e., Course, Community or Course/Community) 
   
 codetitlesref - reference to array of titles of components in institutional codes (official courses)  codetitlesref - reference to array of titles of components in institutional codes (official courses)
   
 codedom - domain  codedom - domain
   
 formname - value of form element named "form".  formname - value of form element named "form". 
   
 fixeddom - domain, if fixed.  fixeddom - domain, if fixed.
   
 prevphase - value to assign to form element named "phase" when going back to the previous screen  prevphase - value to assign to form element named "phase" when going back to the previous screen  
   
 cnameelement - name of form element in form on opener page which will receive title of selected course  cnameelement - name of form element in form on opener page which will receive title of selected course 
   
 cnumelement - name of form element in form on opener page which will receive courseID  of selected course  cnumelement - name of form element in form on opener page which will receive courseID  of selected course
   
Line 16031  sub build_filters { Line 15483  sub build_filters {
         if (exists($filter->{'instcodefilter'})) {          if (exists($filter->{'instcodefilter'})) {
 #            if (($fixeddom) || ($formname eq 'requestcrs') ||  #            if (($fixeddom) || ($formname eq 'requestcrs') ||
 #                ($formname eq 'modifycourse') || ($formname eq 'filterpicker')) {  #                ($formname eq 'modifycourse') || ($formname eq 'filterpicker')) {
             if ($codedom) {              if ($codedom) { 
                 $officialjs = 1;                  $officialjs = 1;
                 ($instcodeform,$jscript,$$numtitlesref) =                  ($instcodeform,$jscript,$$numtitlesref) =
                     &Apache::courseclassifier::instcode_selectors($codedom,'filterpicker',                      &Apache::courseclassifier::instcode_selectors($codedom,'filterpicker',
Line 16160  $typeelement Line 15612  $typeelement
     return $jscript.$clonewarning.$output;      return $jscript.$clonewarning.$output;
 }  }
   
 =pod  =pod 
   
 =item * &timebased_select_form()  =item * &timebased_select_form()
   
Line 16175  item - name of form element (sincefilter Line 15627  item - name of form element (sincefilter
 filter - anonymous hash of criteria and their values  filter - anonymous hash of criteria and their values
   
 Returns: HTML for a select box contained a blank, then six time selections,  Returns: HTML for a select box contained a blank, then six time selections,
          with value set in incoming form variables currently selected.           with value set in incoming form variables currently selected. 
   
 Side Effects: None  Side Effects: None
   
Line 16212  page load completion for page showing se Line 15664  page load completion for page showing se
   
 Inputs: None  Inputs: None
   
 Returns: markup containing updateFilters() and hideSearching() javascript functions.  Returns: markup containing updateFilters() and hideSearching() javascript functions. 
   
 Side Effects: None  Side Effects: None
   
Line 16251  to retrieve a hash for which keys are co Line 15703  to retrieve a hash for which keys are co
   
 Inputs:  Inputs:
   
 dom - domain being searched  dom - domain being searched 
   
 type - course type ('Course' or 'Community' or '.' if any).  type - course type ('Course' or 'Community' or '.' if any).
   
Line 16263  cloneruname - optional username of new c Line 15715  cloneruname - optional username of new c
   
 clonerudom - optional domain of new course owner  clonerudom - optional domain of new course owner
   
 domcloner - optional "domcloner" flag; has value=1 if user has ccc priv in domain being filtered by,  domcloner - optional "domcloner" flag; has value=1 if user has ccc priv in domain being filtered by, 
             (used when DC is using course creation form)              (used when DC is using course creation form)
   
 codetitles - reference to array of titles of components in institutional codes (official courses).  codetitles - reference to array of titles of components in institutional codes (official courses).
Line 16273  cc_clone - escaped comma separated list Line 15725  cc_clone - escaped comma separated list
   
 reqcrsdom - domain of new course, where search_courses is used to identify potential courses to clone  reqcrsdom - domain of new course, where search_courses is used to identify potential courses to clone
   
 reqinstcode - institutional code of new course, where search_courses is used to identify potential  reqinstcode - institutional code of new course, where search_courses is used to identify potential 
               courses to clone                courses to clone 
   
 Returns: %courses - hash of courses satisfying search criteria, keys = course IDs, values are corresponding colon-separated escaped description, institutional code, owner and type.  Returns: %courses - hash of courses satisfying search criteria, keys = course IDs, values are corresponding colon-separated escaped description, institutional code, owner and type.
   
Line 16357  sub search_courses { Line 15809  sub search_courses {
                 if (ref($courses{$cid}) eq 'HASH') {                  if (ref($courses{$cid}) eq 'HASH') {
                     if (ref($courses{$cid}{roles}) eq 'ARRAY') {                      if (ref($courses{$cid}{roles}) eq 'ARRAY') {
                         if (!grep(/^\Q$courserole\E$/,@{$courses{$cid}{roles}})) {                          if (!grep(/^\Q$courserole\E$/,@{$courses{$cid}{roles}})) {
                             push(@{$courses{$cid}{roles}},$courserole);                              push (@{$courses{$cid}{roles}},$courserole);
                         }                          }
                     } else {                      } else {
                         $courses{$cid}{roles} = [$courserole];                          $courses{$cid}{roles} = [$courserole];
Line 16400  $required - LON-CAPA version needed by c Line 15852  $required - LON-CAPA version needed by c
   
 Returns:  Returns:
   
 $switchserver - query string tp append to /adm/switchserver call (if  $switchserver - query string tp append to /adm/switchserver call (if 
                 current server's LON-CAPA version is too old.                  current server's LON-CAPA version is too old. 
   
 $warning - Message is displayed if no suitable server could be found.  $warning - Message is displayed if no suitable server could be found.
   
Line 16514  Inputs: Line 15966  Inputs:
 $loncaparev - Version on current server (format: Major.Minor.Subrelease-datestamp)  $loncaparev - Version on current server (format: Major.Minor.Subrelease-datestamp)
   
 $interval (optional) - Time which may elapse (in s) between last check for content  $interval (optional) - Time which may elapse (in s) between last check for content
                        change in current course. (default: 600 s).                         change in current course. (default: 600 s).  
   
 Returns: an array; first element is:  Returns: an array; first element is:
   
Line 16522  Returns: an array; first element is: Line 15974  Returns: an array; first element is:
   
 'switch' - if content updates mean user's session  'switch' - if content updates mean user's session
            needs to be switched to a server running a newer LON-CAPA version             needs to be switched to a server running a newer LON-CAPA version
    
 'update' - if course session needs to be refreshed (i.e., Big Hash needs to be reloaded)  'update' - if course session needs to be refreshed (i.e., Big Hash needs to be reloaded)
            on current server hosting user's session             on current server hosting user's session                
   
 ''       - if no action required.  ''       - if no action required.
   
Line 16532  Returns: an array; first element is: Line 15984  Returns: an array; first element is:
   
 If first item element is 'switch':  If first item element is 'switch':
   
 second item is $switchwarning - Warning message if no suitable server found to host session.  second item is $switchwarning - Warning message if no suitable server found to host session. 
   
 third item is $switchserver - query string to append to /adm/switchserver containing lonHostID  third item is $switchserver - query string to append to /adm/switchserver containing lonHostID
                               and current role.                                and current role. 
   
 otherwise: no other elements returned.  otherwise: no other elements returned.
   
Line 16582  sub update_content_constraints { Line 16034  sub update_content_constraints {
     my ($reqdmajor,$reqdminor) = split(/\./,$curr_reqd_hash{'internal.releaserequired'});      my ($reqdmajor,$reqdminor) = split(/\./,$curr_reqd_hash{'internal.releaserequired'});
     my %checkresponsetypes;      my %checkresponsetypes;
     foreach my $key (keys(%Apache::lonnet::needsrelease)) {      foreach my $key (keys(%Apache::lonnet::needsrelease)) {
         my ($item,$name,$value) = split(/:/,$key);          my ($item,$name,$value,$valmatch) = split(/:/,$key);
         if ($item eq 'resourcetag') {          if ($item eq 'resourcetag') {
             if ($name eq 'responsetype') {              if ($name eq 'responsetype') {
                 $checkresponsetypes{$value} = $Apache::lonnet::needsrelease{$key}                  $checkresponsetypes{$value} = $Apache::lonnet::needsrelease{$key}
Line 16687  sub recurse_supplemental { Line 16139  sub recurse_supplemental {
 }  }
   
 sub symb_to_docspath {  sub symb_to_docspath {
     my ($symb,$navmapref) = @_;      my ($symb) = @_;
     return unless ($symb && ref($navmapref));      return unless ($symb);
     my ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($symb);      my ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($symb);
     if ($resurl=~/\.(sequence|page)$/) {      if ($resurl=~/\.(sequence|page)$/) {
         $mapurl=$resurl;          $mapurl=$resurl;
Line 16696  sub symb_to_docspath { Line 16148  sub symb_to_docspath {
         $mapurl=$env{'course.'.$env{'request.course.id'}.'.url'};          $mapurl=$env{'course.'.$env{'request.course.id'}.'.url'};
     }      }
     my $mapresobj;      my $mapresobj;
     unless (ref($$navmapref)) {      my $navmap = Apache::lonnavmaps::navmap->new();
         $$navmapref = Apache::lonnavmaps::navmap->new();      if (ref($navmap)) {
     }          $mapresobj = $navmap->getResourceByUrl($mapurl);
     if (ref($$navmapref)) {  
         $mapresobj = $$navmapref->getResourceByUrl($mapurl);  
     }      }
     $mapurl=~s{^.*/([^/]+)\.(\w+)$}{$1};      $mapurl=~s{^.*/([^/]+)\.(\w+)$}{$1};
     my $type=$2;      my $type=$2;
Line 16710  sub symb_to_docspath { Line 16160  sub symb_to_docspath {
         if ($pcslist ne '') {          if ($pcslist ne '') {
             foreach my $pc (split(/,/,$pcslist)) {              foreach my $pc (split(/,/,$pcslist)) {
                 next if ($pc <= 1);                  next if ($pc <= 1);
                 my $res = $$navmapref->getByMapPc($pc);                  my $res = $navmap->getByMapPc($pc);
                 if (ref($res)) {                  if (ref($res)) {
                     my $thisurl = $res->src();                      my $thisurl = $res->src();
                     $thisurl=~s{^.*/([^/]+)\.\w+$}{$1};                      $thisurl=~s{^.*/([^/]+)\.\w+$}{$1};
Line 16759  sub symb_to_docspath { Line 16209  sub symb_to_docspath {
 sub captcha_display {  sub captcha_display {
     my ($context,$lonhost) = @_;      my ($context,$lonhost) = @_;
     my ($output,$error);      my ($output,$error);
     my ($captcha,$pubkey,$privkey,$version) =      my ($captcha,$pubkey,$privkey) = &get_captcha_config($context,$lonhost);
         &get_captcha_config($context,$lonhost);  
     if ($captcha eq 'original') {      if ($captcha eq 'original') {
         $output = &create_captcha();          $output = &create_captcha();
         unless ($output) {          unless ($output) {
             $error = 'captcha';              $error = 'captcha';
         }          }
     } elsif ($captcha eq 'recaptcha') {      } elsif ($captcha eq 'recaptcha') {
         $output = &create_recaptcha($pubkey,$version);          $output = &create_recaptcha($pubkey);
         unless ($output) {          unless ($output) {
             $error = 'recaptcha';              $error = 'recaptcha';
         }          }
     }      }
     return ($output,$error,$captcha,$version);      return ($output,$error,$captcha);
 }  }
   
 sub captcha_response {  sub captcha_response {
     my ($context,$lonhost) = @_;      my ($context,$lonhost) = @_;
     my ($captcha_chk,$captcha_error);      my ($captcha_chk,$captcha_error);
     my ($captcha,$pubkey,$privkey,$version) = &get_captcha_config($context,$lonhost);      my ($captcha,$pubkey,$privkey) = &get_captcha_config($context,$lonhost);
     if ($captcha eq 'original') {      if ($captcha eq 'original') {
         ($captcha_chk,$captcha_error) = &check_captcha();          ($captcha_chk,$captcha_error) = &check_captcha();
     } elsif ($captcha eq 'recaptcha') {      } elsif ($captcha eq 'recaptcha') {
         $captcha_chk = &check_recaptcha($privkey,$version);          $captcha_chk = &check_recaptcha($privkey);
     } else {      } else {
         $captcha_chk = 1;          $captcha_chk = 1;
     }      }
Line 16791  sub captcha_response { Line 16240  sub captcha_response {
   
 sub get_captcha_config {  sub get_captcha_config {
     my ($context,$lonhost) = @_;      my ($context,$lonhost) = @_;
     my ($captcha,$pubkey,$privkey,$version,$hashtocheck);      my ($captcha,$pubkey,$privkey,$hashtocheck);
     my $hostname = &Apache::lonnet::hostname($lonhost);      my $hostname = &Apache::lonnet::hostname($lonhost);
     my $serverhomeID = &Apache::lonnet::get_server_homeID($hostname);      my $serverhomeID = &Apache::lonnet::get_server_homeID($hostname);
     my $serverhomedom = &Apache::lonnet::host_domain($serverhomeID);      my $serverhomedom = &Apache::lonnet::host_domain($serverhomeID);
Line 16807  sub get_captcha_config { Line 16256  sub get_captcha_config {
                     }                      }
                     if ($privkey && $pubkey) {                      if ($privkey && $pubkey) {
                         $captcha = 'recaptcha';                          $captcha = 'recaptcha';
                         $version = $hashtocheck->{'recaptchaversion'};  
                         if ($version ne '2') {  
                             $version = 1;  
                         }  
                     } else {                      } else {
                         $captcha = 'original';                          $captcha = 'original';
                     }                      }
Line 16828  sub get_captcha_config { Line 16273  sub get_captcha_config {
             $privkey = $domconfhash{$serverhomedom.'.login.recaptchakeys_private'};              $privkey = $domconfhash{$serverhomedom.'.login.recaptchakeys_private'};
             if ($privkey && $pubkey) {              if ($privkey && $pubkey) {
                 $captcha = 'recaptcha';                  $captcha = 'recaptcha';
                 $version = $domconfhash{$serverhomedom.'.login.recaptchaversion'};  
                 if ($version ne '2') {  
                     $version = 1;  
                 }  
             } else {              } else {
                 $captcha = 'original';                  $captcha = 'original';
             }              }
Line 16839  sub get_captcha_config { Line 16280  sub get_captcha_config {
             $captcha = 'original';              $captcha = 'original';
         }          }
     }      }
     return ($captcha,$pubkey,$privkey,$version);      return ($captcha,$pubkey,$privkey);
 }  }
   
 sub create_captcha {  sub create_captcha {
Line 16898  sub check_captcha { Line 16339  sub check_captcha {
 }  }
   
 sub create_recaptcha {  sub create_recaptcha {
     my ($pubkey,$version) = @_;      my ($pubkey) = @_;
     if ($version >= 2) {      my $use_ssl;
         return '<div class="g-recaptcha" data-sitekey="'.$pubkey.'"></div>';      if ($ENV{'SERVER_PORT'} == 443) {
     } else {          $use_ssl = 1;
         my $use_ssl;      }
         if ($ENV{'SERVER_PORT'} == 443) {      my $captcha = Captcha::reCAPTCHA->new;
             $use_ssl = 1;      return $captcha->get_options_setter({theme => 'white'})."\n".
         }             $captcha->get_html($pubkey,undef,$use_ssl).
         my $captcha = Captcha::reCAPTCHA->new;             &mt('If the text is hard to read, [_1] will replace them.',
         return $captcha->get_options_setter({theme => 'white'})."\n".                 '<img src="/res/adm/pages/refresh.gif" alt="reCAPTCHA refresh" />').
                $captcha->get_html($pubkey,undef,$use_ssl).             '<br /><br />';
                &mt('If the text is hard to read, [_1] will replace them.',  
                    '<img src="/res/adm/pages/refresh.gif" alt="reCAPTCHA refresh" />').  
                '<br /><br />';  
      }  
 }  }
   
 sub check_recaptcha {  sub check_recaptcha {
     my ($privkey,$version) = @_;      my ($privkey) = @_;
     my $captcha_chk;      my $captcha_chk;
     if ($version >= 2) {      my $captcha = Captcha::reCAPTCHA->new;
         my $ua = LWP::UserAgent->new;      my $captcha_result =
         $ua->timeout(10);          $captcha->check_answer(
         my %info = (                                  $privkey,
                      secret   => $privkey,                                  $ENV{'REMOTE_ADDR'},
                      response => $env{'form.g-recaptcha-response'},                                  $env{'form.recaptcha_challenge_field'},
                      remoteip => $ENV{'REMOTE_ADDR'},                                  $env{'form.recaptcha_response_field'},
                    );                                );
         my $response = $ua->post('https://www.google.com/recaptcha/api/siteverify',\%info);      if ($captcha_result->{is_valid}) {
         if ($response->is_success)  {          $captcha_chk = 1;
             my $data = JSON::DWIW->from_json($response->decoded_content);  
             if (ref($data) eq 'HASH') {  
                 if ($data->{'success'}) {  
                     $captcha_chk = 1;  
                 }  
             }  
         }  
     } else {  
         my $captcha = Captcha::reCAPTCHA->new;  
         my $captcha_result =  
             $captcha->check_answer(  
                                     $privkey,  
                                     $ENV{'REMOTE_ADDR'},  
                                     $env{'form.recaptcha_challenge_field'},  
                                     $env{'form.recaptcha_response_field'},  
                                   );  
         if ($captcha_result->{is_valid}) {  
             $captcha_chk = 1;  
         }  
     }      }
     return $captcha_chk;      return $captcha_chk;
 }  }
   
 sub emailusername_info {  sub emailusername_info {
     my @fields = ('firstname','lastname','institution','web','location','officialemail','id');      my @fields = ('firstname','lastname','institution','web','location','officialemail');
     my %titles = &Apache::lonlocal::texthash (      my %titles = &Apache::lonlocal::texthash (
                      lastname      => 'Last Name',                       lastname      => 'Last Name',
                      firstname     => 'First Name',                       firstname     => 'First Name',
Line 16960  sub emailusername_info { Line 16378  sub emailusername_info {
                      location      => "School's city, state/province, country",                       location      => "School's city, state/province, country",
                      web           => "School's web address",                       web           => "School's web address",
                      officialemail => 'E-mail address at institution (if different)',                       officialemail => 'E-mail address at institution (if different)',
                      id            => 'Student/Employee ID',  
                  );                   );
     return (\@fields,\%titles);      return (\@fields,\%titles);
 }  }
Line 16992  sub cleanup_html { Line 16409  sub cleanup_html {
 sub critical_redirect {  sub critical_redirect {
     my ($interval) = @_;      my ($interval) = @_;
     if ((time-$env{'user.criticalcheck.time'})>$interval) {      if ((time-$env{'user.criticalcheck.time'})>$interval) {
         my @what=&Apache::lonnet::dump('critical', $env{'user.domain'},          my @what=&Apache::lonnet::dump('critical', $env{'user.domain'}, 
                                         $env{'user.name'});                                          $env{'user.name'});
         &Apache::lonnet::appenv({'user.criticalcheck.time'=>time});          &Apache::lonnet::appenv({'user.criticalcheck.time'=>time});
         my $redirecturl;          my $redirecturl;
         if ($what[0]) {          if ($what[0]) {
             if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) {      if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) {
                 $redirecturl='/adm/email?critical=display';          $redirecturl='/adm/email?critical=display';
                 my $url=&Apache::lonnet::absolute_url().$redirecturl;          my $url=&Apache::lonnet::absolute_url().$redirecturl;
                 return (1, $url);                  return (1, $url);
             }              }
         }          }
     }      } 
     return ();      return ();
 }  }
   
Line 17041  sub des_decrypt { Line 16458  sub des_decrypt {
     } else {      } else {
         $cypher=new DES $keybin;          $cypher=new DES $keybin;
     }      }
     my $plaintext='';      my $plaintext=
     my $cypherlength = length($cyphertext);          $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,0,16))));
     my $numchunks = int($cypherlength/32);      $plaintext.=
     for (my $j=0; $j<$numchunks; $j++) {          $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,16,16))));
         my $start = $j*32;      $plaintext=substr($plaintext,1,ord(substr($plaintext,0,1)) );
         my $cypherblock = substr($cyphertext,$start,32);  
         my $chunk =  
             $cypher->decrypt(unpack("a8",pack("H16",substr($cypherblock,0,16))));  
         $chunk .=  
             $cypher->decrypt(unpack("a8",pack("H16",substr($cypherblock,16,16))));  
         $chunk=substr($chunk,1,ord(substr($chunk,0,1)) );  
         $plaintext .= $chunk;  
     }  
     return $plaintext;      return $plaintext;
 }  }
   
 sub make_short_symbs {  
     my ($cdom,$cnum,$navmap) = @_;  
     return unless (ref($navmap));  
     my ($numnew,@errors);  
     my @toshorten = &Apache::loncommon::get_env_multiple('form.addtiny');  
     if (@toshorten) {  
         my (%maps,%resources,%titles);  
         &Apache::loncourserespicker::enumerate_course_contents($navmap,\%maps,\%resources,\%titles,  
                                                                'shorturls',$cdom,$cnum);  
         my %tocreate;  
         if (keys(%resources)) {  
             foreach my $item (sort {$a <=> $b} (@toshorten)) {  
                 my $symb = $resources{$item};  
                 if ($symb) {  
                     $tocreate{$cnum.'&'.$symb} = 1;  
                 }  
             }  
         }  
         if (keys(%tocreate)) {  
             my %coursetiny = &Apache::lonnet::dump('tiny',$cdom,$cnum);  
             my $su = Short::URL->new(no_vowels => 1);  
             my $init = '';  
             my (%newunique,%addcourse,%courseonly,%failed);  
             # get lock on tiny db  
             my $now = time;  
             my $lockhash = {  
                                 "lock\0$now" => $env{'user.name'}.  
                                                 ':'.$env{'user.domain'},  
                             };  
             my $tries = 0;  
             my $gotlock = &Apache::lonnet::newput_dom('tiny',$lockhash,$cdom);  
             my ($code,$error);  
             while (($gotlock ne 'ok') && ($tries<3)) {  
                 $tries ++;  
                 sleep 1;  
                 $gotlock = &Apache::lonnet::newput_dom('tiny',$lockhash,$cdom);  
             }  
             if ($gotlock eq 'ok') {  
                 $init = &shorten_symbs($cdom,$init,$su,\%coursetiny,\%tocreate,\%newunique,  
                                        \%addcourse,\%courseonly,\%failed);  
                 if (keys(%failed)) {  
                     my $numfailed = scalar(keys(%failed));  
                     push(@errors,&mt('error: could not obtain unique six character URL for [quant,_1,resource]',$numfailed));  
                 }  
                 if (keys(%newunique)) {  
                     my $putres = &Apache::lonnet::newput_dom('tiny',\%newunique,$cdom);  
                     if ($putres eq 'ok') {  
                         $numnew = scalar(keys(%newunique));  
                         my $newputres = &Apache::lonnet::newput('tiny',\%addcourse,$cdom,$cnum);  
                         unless ($newputres eq 'ok') {  
                             push(@errors,&mt('error: could not store course look-up of short URLs'));  
                         }  
                     } else {  
                         push(@errors,&mt('error: could not store unique six character URLs'));  
                     }  
                 }  
         }  
     }  
     return ($numnew,\@errors);  
 }  
   
 sub shorten_symbs {  
     my ($cdom,$init,$su,$coursetiny,$tocreate,$newunique,$addcourse,$courseonly,$failed) = @_;  
     return unless ((ref($su)) && (ref($coursetiny) eq 'HASH') && (ref($tocreate) eq 'HASH') &&  
                    (ref($newunique) eq 'HASH') && (ref($addcourse) eq 'HASH') &&  
                    (ref($courseonly) eq 'HASH') && (ref($failed) eq 'HASH'));  
     my (%possibles,%collisions);  
     foreach my $key (keys(%{$tocreate})) {  
         my $num = String::CRC32::crc32($key);  
         my $tiny = $su->encode($num,$init);  
         if ($tiny) {  
             $possibles{$tiny} = $key;  
         }  
     }  
     if (!$init) {  
         $init = 1;  
     } else {  
         $init ++;  
     }  
     if (keys(%possibles)) {  
         my @posstiny = keys(%possibles);  
         my $configuname = &Apache::lonnet::get_domainconfiguser($cdom);  
         my %currtiny = &Apache::lonnet::get('tiny',\@posstiny,$cdom,$configuname);  
         if (keys(%currtiny)) {  
             foreach my $key (keys(%currtiny)) {  
                 next if ($currtiny{$key} eq '');  
                 if ($currtiny{$key} eq $possibles{$key}) {  
                     my ($tcnum,$tsymb) = split(/\&/,$currtiny{$key});  
                     unless (($coursetiny->{$tsymb} eq $key) || ($addcourse->{$tsymb} eq $key) || ($courseonly->{$tsymb} eq $key)) {  
                         $courseonly->{$tsymb} = $key;  
                     }  
                 } else {  
                     $collisions{$possibles{$key}} = 1;  
                 }  
                 delete($possibles{$key});  
             }  
         }  
         foreach my $key (keys(%possibles)) {  
             $newunique->{$key} = $possibles{$key};  
             my ($tcnum,$tsymb) = split(/\&/,$possibles{$key});  
             unless (($coursetiny->{$tsymb} eq $key) || ($addcourse->{$tsymb} eq $key) || ($courseonly->{$tsymb} eq $key)) {  
                 $addcourse->{$tsymb} = $key;  
             }  
         }  
     }  
     if (keys(%collisions)) {  
         if ($init <5) {  
             if (!$init) {  
                 $init = 1;  
             } else {  
                 $init ++;  
             }  
             $init = &shorten_symbs($cdom,$init,$su,$coursetiny,\%collisions,  
                                    $newunique,$addcourse,$courseonly,$failed);  
         } else {  
             foreach my $key (keys(%collisions)) {  
                 $failed->{$key} = 1;  
             }  
         }  
     }  
     return $init;  
 }  
   
 1;  1;
 __END__;  __END__;
   

Removed from v.1.1075.2.127.2.7  
changed lines
  Added in v.1.1222


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