Diff for /loncom/interface/loncommon.pm between versions 1.1075.2.92 and 1.1118

version 1.1075.2.92, 2015/04/07 15:13:35 version 1.1118, 2013/03/20 01:26:15
Line 69  use Apache::lontexconvert(); Line 69  use Apache::lontexconvert();
 use Apache::lonclonecourse();  use Apache::lonclonecourse();
 use Apache::lonuserutils();  use Apache::lonuserutils();
 use Apache::lonuserstate();  use Apache::lonuserstate();
 use Apache::courseclassifier();  
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale::Catalog;  use DateTime::Locale::Catalog;
   use Text::Aspell;
 use Authen::Captcha;  use Authen::Captcha;
 use Captcha::reCAPTCHA;  use Captcha::reCAPTCHA;
 use Crypt::DES;  
 use DynaLoader; # for Crypt::DES version  
   
 # ---------------------------------------------- Designs  # ---------------------------------------------- Designs
 use vars qw(%defaultdesign);  use vars qw(%defaultdesign);
Line 161  sub ssi_with_retries { Line 159  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 195  BEGIN { Line 194  BEGIN {
             while (my $line = <$fh>) {              while (my $line = <$fh>) {
                 next if ($line=~/^\#/);                  next if ($line=~/^\#/);
                 chomp($line);                  chomp($line);
                 my ($key,$two,$country,$three,$enc,$val,$sup,$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 666  if (!Array.prototype.indexOf) { Line 666  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 902  sub check_uncheck_jscript { Line 902  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 1017  sub select_language { Line 1017  sub select_language {
   
 =pod  =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
   
 =item * &linked_select_forms(...)  =item * &linked_select_forms(...)
   
 linked_select_forms returns a string containing a <script></script> block  linked_select_forms returns a string containing a <script></script> block
Line 1237  sub help_open_topic { Line 1264  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 1292  sub helpLatexCheatsheet { Line 1315  sub helpLatexCheatsheet {
     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>';
                .&help_open_topic('Authoring_Multilingual_Problems',&mt('Languages'),$stayOnPage,undef,600)  
                .'</span>';  
     }      }
     $out .= '</span>'; # End cheatsheet      $out .= '</span>'; # End cheatsheet
     return $out;      return $out;
Line 1357  sub help_open_menu { Line 1378  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 = ($stay_on_page) ? "javascript:helpMenu('display')"
     }                       : "javascript:helpMenu('open')";
     my ($link,$banner_link);      my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);
     unless ($env{'request.noversionuri'} =~ m{^/adm/helpmenu}) {  
         $link = ($stay_on_page) ? "javascript:helpMenu('display')"  
                          : "javascript:helpMenu('open')";  
         $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);  
     }  
     my $title = &mt('Get help');      my $title = &mt('Get help');
     if ($link) {  
         return <<"END";      return <<"END";
 $banner_link  $banner_link
 <a href="$link" title="$title">$text</a>   <a href="$link" title="$title">$text</a>
 END  END
     } else {  
         return '&nbsp;'.$text.'&nbsp;';  
     }  
 }  }
   
 sub help_menu_js {  sub help_menu_js {
     my ($httphost) = @_;      my ($text) = @_;
     my $stayOnPage = 1;      my $stayOnPage = 1;
     my $width = 620;      my $width = 620;
     my $height = 600;      my $height = 600;
     my $helptopic=&general_help();      my $helptopic=&general_help();
     my $details_link = $httphost.'/adm/help/'.$helptopic.'.hlp';      my $details_link = '/adm/help/'.$helptopic.'.hlp';
     my $nothing=&Apache::lonhtmlcommon::javascript_nothing();      my $nothing=&Apache::lonhtmlcommon::javascript_nothing();
     my $start_page =      my $start_page =
         &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,   
  'add_entries' => {   'add_entries' => {
     'border' => '0',      'border' => '0',
     'rows'   => "110,*",},});      'rows'   => "110,*",},});
Line 1422  function helpMenu(target) { Line 1435  function helpMenu(target) {
     return;      return;
 }  }
 function writeHelp(caller) {  function writeHelp(caller) {
     caller.document.writeln('$start_page\\n<frame name="bannerframe" src="'+banner_link+'" marginwidth="0" marginheight="0" frameborder="0">\\n');      caller.document.writeln('$start_page\\n<frame name="bannerframe" src="'+banner_link+'" />\\n<frame name="bodyframe" src="$details_link" />\\n$end_page')
     caller.document.writeln('<frame name="bodyframe" src="$details_link" marginwidth="0" marginheight="0" frameborder="0">\\n$end_page');      caller.document.close()
     caller.document.close();      caller.focus()
     caller.focus();  
 }  }
 // END LON-CAPA Internal -->  // END LON-CAPA Internal -->
 // ]]>  // ]]>
Line 1737  RESIZE Line 1749  RESIZE
   
 =head1 Excel and CSV file utility routines  =head1 Excel and CSV file utility routines
   
   =over 4
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 1744  RESIZE Line 1758  RESIZE
   
 =pod  =pod
   
 =over 4  
   
 =item * &csv_translate($text)   =item * &csv_translate($text) 
   
 Translate $text to allow it to be output as a 'comma separated values'   Translate $text to allow it to be output as a 'comma separated values' 
Line 2179  sub select_level_form { Line 2191  sub select_level_form {
   
 =pod  =pod
   
 =item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms)  =item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms)
   
 Returns a string containing a <select name='$name' size='1'> form to   Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select the domain to preform an operation in.    allow a user to select the domain to preform an operation in.  
Line 2192  If the $showdomdesc flag is set, the dom Line 2204  If the $showdomdesc flag is set, the dom
   
 The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.  The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.
   
 The optional $incdoms is a reference to an array of domains which will be the only available options.  The optional $incdoms is a reference to an array of domains which will be the only available options. 
   
 The optional $excdoms is a reference to an array of domains which will be excluded from the available options.   
   
 =cut  =cut
   
 #-------------------------------------------  #-------------------------------------------
 sub select_dom_form {  sub select_dom_form {
     my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms) = @_;      my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) = @_;
     if ($onchange) {      if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';          $onchange = ' onchange="'.$onchange.'"';
     }      }
     my (@domains,%exclude);      my @domains;
     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});
     } else {      } else {
         @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());          @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
     }      }
     if ($includeempty) { @domains=('',@domains); }      if ($includeempty) { @domains=('',@domains); }
     if (ref($excdoms) eq 'ARRAY') {  
         map { $exclude{$_} = 1; } @{$excdoms};  
     }  
     my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange>\n";      my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange>\n";
     foreach my $dom (@domains) {      foreach my $dom (@domains) {
         next if ($exclude{$dom});  
         $selectdomain.="<option value=\"$dom\" ".          $selectdomain.="<option value=\"$dom\" ".
             ($dom eq $defdom ? 'selected="selected" ' : '').'>'.$dom;              ($dom eq $defdom ? 'selected="selected" ' : '').'>'.$dom;
         if ($showdomdesc) {          if ($showdomdesc) {
Line 2337  Outputs: Line 2343  Outputs:
   
 =item * $clientos  =item * $clientos
   
 =item * $clientmobile  
   
 =item * $clientinfo  
   
 =item * $clientosversion  
   
 =back  =back
   
 =back   =back 
Line 2361  sub decode_user_agent { Line 2361  sub decode_user_agent {
     my $clientversion='0';      my $clientversion='0';
     my $clientmathml='';      my $clientmathml='';
     my $clientunicode='0';      my $clientunicode='0';
     my $clientmobile=0;  
     my $clientosversion='';  
     for (my $i=0;$i<=$#browsertype;$i++) {      for (my $i=0;$i<=$#browsertype;$i++) {
         my ($bname,$match,$notmatch,$vreg,$minv,$univ)=split(/\%/,$browsertype[$i]);          my ($bname,$match,$notmatch,$vreg,$minv,$univ)=split(/\:/,$browsertype[$i]);
  if (($httpbrowser=~/$match/i)  && ($httpbrowser!~/$notmatch/i)) {   if (($httpbrowser=~/$match/i)  && ($httpbrowser!~/$notmatch/i)) {
     $clientbrowser=$bname;      $clientbrowser=$bname;
             $httpbrowser=~/$vreg/i;              $httpbrowser=~/$vreg/i;
Line 2374  sub decode_user_agent { Line 2372  sub decode_user_agent {
  }   }
     }      }
     my $clientos='unknown';      my $clientos='unknown';
     my $clientinfo;  
     if (($httpbrowser=~/linux/i) ||      if (($httpbrowser=~/linux/i) ||
         ($httpbrowser=~/unix/i) ||          ($httpbrowser=~/unix/i) ||
         ($httpbrowser=~/ux/i) ||          ($httpbrowser=~/ux/i) ||
Line 2384  sub decode_user_agent { Line 2381  sub decode_user_agent {
     if ($httpbrowser=~/next/i) { $clientos='next'; }      if ($httpbrowser=~/next/i) { $clientos='next'; }
     if (($httpbrowser=~/mac/i) ||      if (($httpbrowser=~/mac/i) ||
         ($httpbrowser=~/powerpc/i)) { $clientos='mac'; }          ($httpbrowser=~/powerpc/i)) { $clientos='mac'; }
     if ($httpbrowser=~/win/i) {      if ($httpbrowser=~/win/i) { $clientos='win'; }
         $clientos='win';  
         if ($httpbrowser =~/Windows\s+NT\s+(\d+\.\d+)/i) {  
             $clientosversion = $1;  
         }  
     }  
     if ($httpbrowser=~/embed/i) { $clientos='pda'; }      if ($httpbrowser=~/embed/i) { $clientos='pda'; }
     if ($httpbrowser=~/(Android|iPod|iPad|iPhone|webOS|Blackberry|Windows Phone|Opera m(?:ob|in)|Fennec)/i) {  
         $clientmobile=lc($1);  
     }  
     if ($httpbrowser=~ m{Firefox/(\d+\.\d+)}) {  
         $clientinfo = 'firefox-'.$1;  
     } elsif ($httpbrowser=~ m{chromeframe/(\d+\.\d+)\.}) {  
         $clientinfo = 'chromeframe-'.$1;  
     }  
     return ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,      return ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
             $clientunicode,$clientos,$clientmobile,$clientinfo,              $clientunicode,$clientos,);
             $clientosversion);  
 }  }
   
 ###############################################################  ###############################################################
Line 2568  sub authform_nochange { Line 2551  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 3064  sub get_related_words { Line 3047  sub get_related_words {
     untie %thesaurus_db;      untie %thesaurus_db;
     return @Words;      return @Words;
 }  }
   ###############################################################
   #
   #  Spell checking
   #
   
   =pod
   
   =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
   
   
 =pod  =pod
   
Line 3071  sub get_related_words { Line 3093  sub get_related_words {
   
 =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 3261  sub screenname { Line 3308  sub screenname {
 # ------------------------------------------------------------- Confirm Wrapper  # ------------------------------------------------------------- Confirm Wrapper
 =pod  =pod
   
 =item * &confirmwrapper($message)  =item confirmwrapper
   
 Wrap messages about completion of operation in box  Wrap messages about completion of operation in box
   
Line 3677  sub user_lang { Line 3724  sub user_lang {
 =over 4  =over 4
   
 =item * &get_previous_attempt($symb, $username, $domain, $course,  =item * &get_previous_attempt($symb, $username, $domain, $course,
     $getattempt, $regexp, $gradesub, $usec, $identifier)      $getattempt, $regexp, $gradesub)
   
 Return string with previous attempt on problem. Arguments:  Return string with previous attempt on problem. Arguments:
   
Line 3699  Return string with previous attempt on p Line 3746  Return string with previous attempt on p
   
 =item * $gradesub: routine that processes the string if it matches $regexp  =item * $gradesub: routine that processes the string if it matches $regexp
   
 =item * $usec: section of the desired student  
   
 =item * $identifier: counter for student (multiple students one problem) or  
     problem (one student; whole sequence).  
   
 =back  =back
   
 The output string is a table containing all desired attempts, if any.  The output string is a table containing all desired attempts, if any.
Line 3711  The output string is a table containing Line 3753  The output string is a table containing
 =cut  =cut
   
 sub get_previous_attempt {  sub get_previous_attempt {
   my ($symb,$username,$domain,$course,$getattempt,$regexp,$gradesub,$usec,$identifier)=@_;    my ($symb,$username,$domain,$course,$getattempt,$regexp,$gradesub)=@_;
   my $prevattempts='';    my $prevattempts='';
   no strict 'refs';    no strict 'refs';
   if ($symb) {    if ($symb) {
Line 3721  sub get_previous_attempt { Line 3763  sub get_previous_attempt {
       my %lasthash=();        my %lasthash=();
       my $version;        my $version;
       for ($version=1;$version<=$returnhash{'version'};$version++) {        for ($version=1;$version<=$returnhash{'version'};$version++) {
         foreach my $key (reverse(sort(split(/\:/,$returnhash{$version.':keys'})))) {          foreach my $key (sort(split(/\:/,$returnhash{$version.':keys'}))) {
             if ($key =~ /\.rawrndseed$/) {    $lasthash{$key}=$returnhash{$version.':'.$key};
                 my ($id) = ($key =~ /^(.+)\.rawrndseed$/);  
                 $lasthash{$id.'.rndseed'} = $returnhash{$version.':'.$key};  
             } else {  
                 $lasthash{$key}=$returnhash{$version.':'.$key};  
             }  
         }          }
       }        }
       $prevattempts=&start_data_table().&start_data_table_header_row();        $prevattempts=&start_data_table().&start_data_table_header_row();
       $prevattempts.='<th>'.&mt('History').'</th>';        $prevattempts.='<th>'.&mt('History').'</th>';
       my (%typeparts,%lasthidden,%regraded,%hidestatus);        my (%typeparts,%lasthidden);
       my $showsurv=&Apache::lonnet::allowed('vas',$env{'request.course.id'});        my $showsurv=&Apache::lonnet::allowed('vas',$env{'request.course.id'});
       foreach my $key (sort(keys(%lasthash))) {        foreach my $key (sort(keys(%lasthash))) {
  my ($ign,@parts) = split(/\./,$key);   my ($ign,@parts) = split(/\./,$key);
Line 3749  sub get_previous_attempt { Line 3786  sub get_previous_attempt {
                       $lasthidden{$ign.'.'.$id} = 1;                        $lasthidden{$ign.'.'.$id} = 1;
                   }                    }
               }                }
               if ($identifier ne '') {  
                   my $id = join(',',@parts);  
                   if (&Apache::lonnet::EXT("resource.$id.problemstatus",$symb,  
                                                $domain,$username,$usec,undef,$course) =~ /^no/) {  
                       $hidestatus{$ign.'.'.$id} = 1;  
                   }  
               }  
           } elsif ($data eq 'regrader') {  
               if (($identifier ne '') && (@parts)) {  
                   my $id = join(',',@parts);  
                   $regraded{$ign.'.'.$id} = 1;  
               }  
           }             } 
  } else {   } else {
   if ($#parts == 0) {    if ($#parts == 0) {
Line 3772  sub get_previous_attempt { Line 3797  sub get_previous_attempt {
       }        }
       $prevattempts.=&end_data_table_header_row();        $prevattempts.=&end_data_table_header_row();
       if ($getattempt eq '') {        if ($getattempt eq '') {
         my (%solved,%resets,%probstatus);  
         if (($identifier ne '') && (keys(%regraded) > 0)) {  
             for ($version=1;$version<=$returnhash{'version'};$version++) {  
                 foreach my $id (keys(%regraded)) {  
                     if (($returnhash{$version.':'.$id.'.regrader'}) &&  
                         ($returnhash{$version.':'.$id.'.tries'} eq '') &&  
                         ($returnhash{$version.':'.$id.'.award'} eq '')) {  
                         push(@{$resets{$id}},$version);  
                     }  
                 }  
             }  
         }  
  for ($version=1;$version<=$returnhash{'version'};$version++) {   for ($version=1;$version<=$returnhash{'version'};$version++) {
             my (@hidden,@unsolved);              my @hidden;
             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 '') {  
                         unless (($returnhash{$version.':'.$id.'.type'} eq 'survey') ||  
                                 ($returnhash{$version.':'.$id.'.type'} eq 'surveycred') ||  
                                 ($hidestatus{$id})) {  
                             next if ((ref($resets{$id}) eq 'ARRAY') && grep(/^\Q$version\E$/,@{$resets{$id}}));  
                             if ($returnhash{$version.':'.$id.'.solved'} eq 'correct_by_student') {  
                                 push(@{$solved{$id}},$version);  
                             } elsif (($returnhash{$version.':'.$id.'.solved'} ne '') &&  
                                      (ref($solved{$id}) eq 'ARRAY')) {  
                                 my $skip;  
                                 if (ref($resets{$id}) eq 'ARRAY') {  
                                     foreach my $reset (@{$resets{$id}}) {  
                                         if ($reset > $solved{$id}[-1]) {  
                                             $skip=1;  
                                             last;  
                                         }  
                                     }  
                                 }  
                                 unless ($skip) {  
                                     my ($ign,$partslist) = split(/\./,$id,2);  
                                     push(@unsolved,$partslist);  
                                 }  
                             }  
                         }  
                     }                      }
                 }                  }
             }              }
             $prevattempts.=&start_data_table_row().              $prevattempts.=&start_data_table_row().
                            '<td>'.&mt('Transaction [_1]',$version);                             '<td>'.&mt('Transaction [_1]',$version).'</td>';
             if (@unsolved) {  
                 $prevattempts .= '<span class="LC_nobreak"><label>'.  
                                  '<input type="checkbox" name="HIDE'.$identifier.'" value="'.$version.':'.join('_',@unsolved).'" />'.  
                                  &mt('Hide').'</label></span>';  
             }  
             $prevattempts .= '</td>';  
             if (@hidden) {              if (@hidden) {
                 foreach my $key (sort(keys(%lasthash))) {                  foreach my $key (sort(keys(%lasthash))) {
                     next if ($key =~ /\.foilorder$/);                      next if ($key =~ /\.foilorder$/);
Line 3847  sub get_previous_attempt { Line 3829  sub get_previous_attempt {
                         }                          }
                     } else {                      } else {
                         if ($key =~ /\./) {                          if ($key =~ /\./) {
                             my $value = $returnhash{$version.':'.$key};                              my $value = &format_previous_attempt_value($key,
                             if ($key =~ /\.rndseed$/) {                                                $returnhash{$version.':'.$key});
                                 my ($id) = ($key =~ /^(.+)\.rndseed$/);                              $prevattempts.='<td>'.$value.'&nbsp;</td>';
                                 if (exists($returnhash{$version.':'.$id.'.rawrndseed'})) {  
                                     $value = $returnhash{$version.':'.$id.'.rawrndseed'};  
                                 }  
                             }  
                             $prevattempts.='<td>'.&format_previous_attempt_value($key,$value).  
                                            '&nbsp;</td>';  
                         } else {                          } else {
                             $prevattempts.='<td>&nbsp;</td>';                              $prevattempts.='<td>&nbsp;</td>';
                         }                          }
Line 3864  sub get_previous_attempt { Line 3840  sub get_previous_attempt {
             } else {              } else {
         foreach my $key (sort(keys(%lasthash))) {          foreach my $key (sort(keys(%lasthash))) {
                     next if ($key =~ /\.foilorder$/);                      next if ($key =~ /\.foilorder$/);
                     my $value = $returnhash{$version.':'.$key};      my $value = &format_previous_attempt_value($key,
                     if ($key =~ /\.rndseed$/) {              $returnhash{$version.':'.$key});
                         my ($id) = ($key =~ /^(.+)\.rndseed$/);      $prevattempts.='<td>'.$value.'&nbsp;</td>';
                         if (exists($returnhash{$version.':'.$id.'.rawrndseed'})) {  
                             $value = $returnhash{$version.':'.$id.'.rawrndseed'};  
                         }  
                     }  
                     $prevattempts.='<td>'.&format_previous_attempt_value($key,$value).  
                                    '&nbsp;</td>';  
         }          }
             }              }
     $prevattempts.=&end_data_table_row();      $prevattempts.=&end_data_table_row();
Line 4322  sub findallcourses { Line 4292  sub findallcourses {
 ###############################################  ###############################################
   
 sub blockcheck {  sub blockcheck {
     my ($setters,$activity,$uname,$udom,$url,$is_course) = @_;      my ($setters,$activity,$uname,$udom,$url) = @_;
   
     if (defined($udom) && defined($uname)) {      if (!defined($udom)) {
         # If uname and udom are for a course, check for blocks in the course.  
         if (($is_course) || (&Apache::lonnet::is_course($udom,$uname))) {  
             my ($startblock,$endblock,$triggerblock) =  
                 &get_blocks($setters,$activity,$udom,$uname,$url);  
             return ($startblock,$endblock,$triggerblock);  
         }  
     } else {  
         $udom = $env{'user.domain'};          $udom = $env{'user.domain'};
       }
       if (!defined($uname)) {
         $uname = $env{'user.name'};          $uname = $env{'user.name'};
     }      }
   
       # If uname and udom are for a course, check for blocks in the course.
   
       if (&Apache::lonnet::is_course($udom,$uname)) {
           my ($startblock,$endblock,$triggerblock) = 
               &get_blocks($setters,$activity,$udom,$uname,$url);
           return ($startblock,$endblock,$triggerblock);
       }
   
     my $startblock = 0;      my $startblock = 0;
     my $endblock = 0;      my $endblock = 0;
     my $triggerblock = '';      my $triggerblock = '';
Line 4345  sub blockcheck { Line 4318  sub blockcheck {
     # boards, chat or groups, check for blocking in current course only.      # boards, chat or groups, check for blocking in current course only.
   
     if (($activity eq 'boards' || $activity eq 'chat' ||      if (($activity eq 'boards' || $activity eq 'chat' ||
          $activity eq 'groups' || $activity eq 'printout') &&           $activity eq 'groups') && ($env{'request.course.id'})) {
         ($env{'request.course.id'})) {  
         foreach my $key (keys(%live_courses)) {          foreach my $key (keys(%live_courses)) {
             if ($key ne $env{'request.course.id'}) {              if ($key ne $env{'request.course.id'}) {
                 delete($live_courses{$key});                  delete($live_courses{$key});
Line 4610  sub parse_block_record { Line 4582  sub parse_block_record {
 }  }
   
 sub blocking_status {  sub blocking_status {
     my ($activity,$uname,$udom,$url,$is_course) = @_;      my ($activity,$uname,$udom,$url) = @_;
     my %setters;      my %setters;
   
 # check for active blocking  # check for active blocking
     my ($startblock,$endblock,$triggerblock) =       my ($startblock,$endblock,$triggerblock) = 
         &blockcheck(\%setters,$activity,$uname,$udom,$url,$is_course);          &blockcheck(\%setters,$activity,$uname,$udom,$url);
     my $blocked = 0;      my $blocked = 0;
     if ($startblock && $endblock) {      if ($startblock && $endblock) {
         $blocked = 1;          $blocked = 1;
Line 4772  sub get_domainconf { Line 4744  sub get_domainconf {
             if (keys(%{$domconfig{'login'}})) {              if (keys(%{$domconfig{'login'}})) {
                 foreach my $key (keys(%{$domconfig{'login'}})) {                  foreach my $key (keys(%{$domconfig{'login'}})) {
                     if (ref($domconfig{'login'}{$key}) eq 'HASH') {                      if (ref($domconfig{'login'}{$key}) eq 'HASH') {
                         if (($key eq 'loginvia') || ($key eq 'headtag')) {                          if ($key eq 'loginvia') {
                             if (ref($domconfig{'login'}{$key}) eq 'HASH') {                              if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') {
                                 foreach my $hostname (keys(%{$domconfig{'login'}{$key}})) {                                  foreach my $hostname (keys(%{$domconfig{'login'}{'loginvia'}})) {
                                     if (ref($domconfig{'login'}{$key}{$hostname}) eq 'HASH') {                                      if (ref($domconfig{'login'}{'loginvia'}{$hostname}) eq 'HASH') {
                                         if ($key eq 'loginvia') {                                          if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {
                                             if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {                                              my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};
                                                 my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};                                              $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'};
                                                 }  
                                             }                                              }
                                         } elsif ($key eq 'headtag') {                                              if ($domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}) {
                                             if ($domconfig{'login'}{'headtag'}{$hostname}{'url'}) {                                                  $designhash{$udom.'.login.loginvia_exempt_'.$hostname} = $domconfig{'login'}{'loginvia'}{$hostname}{'exempt'};
                                                 $designhash{$udom.'.login.headtag_'.$hostname} = $domconfig{'login'}{'headtag'}{$hostname}{'url'};  
                                             }                                              }
                                         }                                          }
                                         if ($domconfig{'login'}{$key}{$hostname}{'exempt'}) {  
                                             $designhash{$udom.'.login.'.$key.'_exempt_'.$hostname} = $domconfig{'login'}{$key}{$hostname}{'exempt'};  
                                         }  
                                     }                                      }
                                 }                                  }
                             }                              }
Line 4959  sub designparm { Line 4926  sub designparm {
   
 Inputs: $url (usually will be undef).  Inputs: $url (usually will be undef).
   
 Returns: Path to Authoring Space containing the resource or   Returns: Path to Construction Space containing the resource or 
          directory being viewed (or for which action is being taken).            directory being viewed (or for which action is being taken). 
          If $url is provided, and begins /priv/<domain>/<uname>           If $url is provided, and begins /priv/<domain>/<uname>
          the path will be that portion of the $context argument.           the path will be that portion of the $context argument.
Line 5022  Input: (optional) filename from which br Line 4989  Input: (optional) filename from which br
        is appropriate for use in building the breadcrumb trail.         is appropriate for use in building the breadcrumb trail.
   
 Returns: HTML div with CSTR path and recent box  Returns: HTML div with CSTR path and recent box
          To be included on Authoring Space pages           To be included on Construction Space pages
   
 =cut  =cut
   
Line 5053  sub CSTR_pageheader { Line 5020  sub CSTR_pageheader {
     my $output =      my $output =
          '<div>'           '<div>'
         .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?          .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?
         .'<b>'.&mt('Authoring Space:').'</b> '          .'<b>'.&mt('Construction Space:').'</b> '
         .'<form name="dirs" method="post" action="'.$formaction          .'<form name="dirs" method="post" action="'.$formaction
         .'" target="_top">' #FIXME lonpubdir: target="_parent"          .'" target="_top">' #FIXME lonpubdir: target="_parent"
         .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv/'.$udom,undef,undef);          .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv/'.$udom,undef,undef);
Line 5112  Inputs: Line 5079  Inputs:
   
 =item * $bgcolor, used to override the bgcolor on a webpage to a specific value  =item * $bgcolor, used to override the bgcolor on a webpage to a specific value
   
 =item * $no_inline_link, if true and in remote mode, don't show the  
          'Switch To Inline Menu' link  
   
 =item * $args, optional argument valid values are  =item * $args, optional argument valid values are
             no_auto_mt_title -> prevents &mt()ing the title arg              no_auto_mt_title -> prevents &mt()ing the title arg
             inherit_jsmath -> when creating popup window in a page,              inherit_jsmath -> when creating popup window in a page,
Line 5136  other decorations will be returned. Line 5100  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 5144  sub bodytag { Line 5108  sub bodytag {
         $public = 1;          $public = 1;
     }      }
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }      if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
     my $httphost = $args->{'use_absolute'};  
   
     $function = &get_users_function() if (!$function);      $function = &get_users_function() if (!$function);
     my $img =    &designparm($function.'.img',$domain);      my $img =    &designparm($function.'.img',$domain);
Line 5160  sub bodytag { Line 5123  sub bodytag {
     @design{keys(%$addentries)} = @$addentries{keys(%$addentries)};       @design{keys(%$addentries)} = @$addentries{keys(%$addentries)}; 
   
  # role and realm   # role and realm
     my ($role,$realm) = split(m{\./},$env{'request.role'},2);      my ($role,$realm) = split(/\./,$env{'request.role'},2);
     if ($realm) {  
         $realm = '/'.$realm;  
     }  
     if ($role  eq 'ca') {      if ($role  eq 'ca') {
         my ($rdom,$rname) = ($realm =~ m{^/($match_domain)/($match_username)$});          my ($rdom,$rname) = ($realm =~ m{^/($match_domain)/($match_username)$});
         $realm = &plainname($rname,$rdom);          $realm = &plainname($rname,$rdom);
Line 5189  sub bodytag { Line 5149  sub bodytag {
     my $bodytag = "<body $extra_body_attr>".      my $bodytag = "<body $extra_body_attr>".
  &Apache::lontexconvert::init_math_support($args->{'inherit_jsmath'});   &Apache::lontexconvert::init_math_support($args->{'inherit_jsmath'});
   
     &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);      if ($bodyonly) {
   
     if (($bodyonly) || ($no_nav_bar) || ($env{'form.inhibitmenu'} eq 'yes')) {  
         return $bodytag;          return $bodytag;
     }      } 
   
       my $name = &plainname($env{'user.name'},$env{'user.domain'});
     if ($public) {      if ($public) {
  undef($role);   undef($role);
       } else {
    $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'},
                                   undef,'LC_menubuttons_link');
     }      }
           
     my $titleinfo = '<h1>'.$title.'</h1>';      my $titleinfo = '<h1>'.$title.'</h1>';
Line 5212  sub bodytag { Line 5174  sub bodytag {
     }      }
   
     $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;      $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;
       &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
   
     if ($env{'request.state'} eq 'construct') { $forcereg=1; }          if ($no_nav_bar || $env{'form.inhibitmenu'} eq 'yes') { 
               return $bodytag; 
           } 
   
     my $funclist;          if ($env{'request.state'} eq 'construct') { $forcereg=1; }
     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
         #    }          #    }
   
         $bodytag .= Apache::lonhtmlcommon::scripttag(  
             Apache::lonmenu::utilityfunctions($httphost), 'start');  
   
         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">$name $role<br />
                            <em>$realm</em> $dc_info</div>|;                  <em>$realm</em> $dc_info</div>|;
             return $bodytag;              return $bodytag;
         }          }
   
         unless ($env{'request.symb'} =~ m/\.page___\d+___/) {          unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
             $bodytag .= qq|<div id="LC_nav_bar">$left $role</div>|;              $bodytag .= qq|<div id="LC_nav_bar">$name $role</div>|;
         }          }
   
         $bodytag .= $right;          $bodytag .= Apache::lonhtmlcommon::scripttag(
               Apache::lonmenu::utilityfunctions(), 'start');
   
           $bodytag .= Apache::lonmenu::primary_menu();
   
         if ($dc_info) {          if ($dc_info) {
             $dc_info = &dc_courseid_toggle($dc_info);              $dc_info = &dc_courseid_toggle($dc_info);
         }          }
         $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 ($args->{'no_secondary_menu'}) {  
             return $bodytag;  
         }  
         #don't show menus for public users          #don't show menus for public users
         if (!$public){          if (!$public){
             $bodytag .= Apache::lonmenu::secondary_menu($httphost);              $bodytag .= Apache::lonmenu::secondary_menu();
             $bodytag .= Apache::lonmenu::serverform();              $bodytag .= Apache::lonmenu::serverform();
             $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');              $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
             if ($env{'request.state'} eq 'construct') {              if ($env{'request.state'} eq 'construct') {
                 $bodytag .= &Apache::lonmenu::innerregister($forcereg,                  $bodytag .= &Apache::lonmenu::innerregister($forcereg,
                                 $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'});
             } 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 5293  sub bodytag { Line 5237  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 5372  sub make_attr_string { Line 5268  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;
     foreach my $attr (sort(keys(%$attr_ref))) {      foreach my $attr (keys(%$attr_ref)) {
  $attr_string .= " $attr=\"".$attr_ref->{$attr}.'" ';   $attr_string .= " $attr=\"".$attr_ref->{$attr}.'" ';
     }      }
     return $attr_string;      return $attr_string;
Line 5515  form, .inline { Line 5404  form, .inline {
   vertical-align:middle;    vertical-align:middle;
 }  }
   
 .LC_floatleft {  
   float: left;  
 }  
   
 .LC_floatright {  
   float: right;  
 }  
   
 .LC_400Box {  .LC_400Box {
   width:400px;    width:400px;
 }  }
Line 6593  div.LC_edit_problem_saves { Line 6474  div.LC_edit_problem_saves {
   padding-bottom: 5px;    padding-bottom: 5px;
 }  }
   
 .LC_edit_opt {  
   padding-left: 1em;  
   white-space: nowrap;  
 }  
   
 .LC_edit_problem_latexhelper{  
     text-align: right;  
 }  
   
 #LC_edit_problem_colorful div{  
     margin-left: 40px;  
 }  
   
 img.stift {  img.stift {
   border-width: 0;    border-width: 0;
   vertical-align: middle;    vertical-align: middle;
Line 6620  div.LC_createcourse { Line 6488  div.LC_createcourse {
 }  }
   
 .LC_dccid {  .LC_dccid {
   float: right;  
   margin: 0.2em 0 0 0;    margin: 0.2em 0 0 0;
   padding: 0;    padding: 0;
   font-size: 90%;    font-size: 90%;
Line 6693  fieldset { Line 6560  fieldset {
   /* overflow: hidden; */    /* overflow: hidden; */
 }  }
   
 article.geogebraweb div {  
     margin: 0;  
 }  
   
 fieldset > legend {  fieldset > legend {
   font-weight: bold;    font-weight: bold;
   padding: 0 5px 0 5px;    padding: 0 5px 0 5px;
Line 6722  fieldset > legend { Line 6585  fieldset > legend {
 }  }
   
 ol.LC_primary_menu {  ol.LC_primary_menu {
     float: right;
   margin: 0;    margin: 0;
   padding: 0;    padding: 0;
   background-color: $pgbg_or_bgcolor;    background-color: $pgbg_or_bgcolor;
Line 6833  ul#LC_secondary_menu li { Line 6697  ul#LC_secondary_menu li {
   font-weight: bold;    font-weight: bold;
   line-height: 1.8em;    line-height: 1.8em;
   border-right: 1px solid black;    border-right: 1px solid black;
   vertical-align: middle;  
   float: left;    float: left;
 }  }
   
Line 6866  ul#LC_secondary_menu li ul li { Line 6729  ul#LC_secondary_menu li ul li {
   vertical-align: top;    vertical-align: top;
   border-left: 1px solid black;    border-left: 1px solid black;
   border-right: 1px solid black;    border-right: 1px solid black;
   background-color: $data_table_light;    background-color: $data_table_light
   list-style:none;    list-style:none;
   float: none;    float: none;
 }  }
Line 7376  sub headtag { Line 7239  sub headtag {
     my $function = $args->{'function'} || &get_users_function();      my $function = $args->{'function'} || &get_users_function();
     my $domain   = $args->{'domain'}   || &determinedomain();      my $domain   = $args->{'domain'}   || &determinedomain();
     my $bgcolor  = $args->{'bgcolor'}  || &designparm($function.'.pgbg',$domain);      my $bgcolor  = $args->{'bgcolor'}  || &designparm($function.'.pgbg',$domain);
     my $httphost = $args->{'use_absolute'};  
     my $url = join(':',$env{'user.name'},$env{'user.domain'},      my $url = join(':',$env{'user.name'},$env{'user.domain'},
    $Apache::lonnet::perlvar{'lonVersion'},     $Apache::lonnet::perlvar{'lonVersion'},
    #time(),     #time(),
Line 7387  sub headtag { Line 7249  sub headtag {
   
     my $result =      my $result =
  '<head>'.   '<head>'.
  &font_settings($args);   &font_settings();
   
     my $inhibitprint;      my $inhibitprint = &print_suppression();
     if ($args->{'print_suppress'}) {  
         $inhibitprint = &print_suppression();  
     }  
   
     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'}
  && !$args->{'frameset'}) {   && !$args->{'frameset'}) {
  $result .= &help_menu_js($httphost);   $result .= &help_menu_js();
         $result.=&modal_window();          $result.=&modal_window();
         $result.=&togglebox_script();          $result.=&togglebox_script();
         $result.=&wishlist_window();          $result.=&wishlist_window();
Line 7432  sub headtag { Line 7291  sub headtag {
 <meta http-equiv="pragma" content="no-cache" />  <meta http-equiv="pragma" content="no-cache" />
 <meta http-equiv="Refresh" content="$time; url=$url" />  <meta http-equiv="Refresh" content="$time; url=$url" />
 ADDMETA  ADDMETA
     } else {  
         unless (($args->{'frameset'}) || ($args->{'js_ready'}) || ($args->{'only_body'}) || ($args->{'no_nav_bar'})) {  
             my $requrl = $env{'request.uri'};  
             if ($requrl eq '') {  
                 $requrl = $ENV{'REQUEST_URI'};  
                 $requrl =~ s/\?.+$//;  
             }  
             unless (($requrl =~ m{^/adm/(?:switchserver|login|authenticate|logout|groupsort|cleanup|helper|slotrequest|grades)(\?|$)}) ||  
                     (($requrl =~ m{^/res/}) && (($env{'form.submitted'} eq 'scantron') ||  
                      ($env{'form.grade_symb'}) || ($Apache::lonhomework::scantronmode)))) {  
                 my $dom_in_use = $Apache::lonnet::perlvar{'lonDefDomain'};  
                 unless (&Apache::lonnet::allowed('mau',$dom_in_use)) {  
                     my %domdefs = &Apache::lonnet::get_domain_defaults($dom_in_use);  
                     if (ref($domdefs{'offloadnow'}) eq 'HASH') {  
                         my $lonhost = $Apache::lonnet::perlvar{'lonHostID'};  
                         if ($domdefs{'offloadnow'}{$lonhost}) {  
                             my $newserver = &Apache::lonnet::spareserver(30000,undef,1,$dom_in_use);  
                             if (($newserver) && ($newserver ne $lonhost)) {  
                                 my $numsec = 5;  
                                 my $timeout = $numsec * 1000;  
                                 my ($newurl,$locknum,%locks,$msg);  
                                 if ($env{'request.role.adv'}) {  
                                     ($locknum,%locks) = &Apache::lonnet::get_locks();  
                                 }  
                                 my $disable_submit = 0;  
                                 if ($requrl =~ /$LONCAPA::assess_re/) {  
                                     $disable_submit = 1;  
                                 }  
                                 if ($locknum) {  
                                     my @lockinfo = sort(values(%locks));  
                                     $msg = &mt('Once the following tasks are complete: ')."\\n".  
                                            join(", ",sort(values(%locks)))."\\n".  
                                            &mt('your session will be transferred to a different server, after you click "Roles".');  
                                 } else {  
                                     if (($requrl =~ m{^/res/}) && ($env{'form.submitted'} =~ /^part_/)) {  
                                         $msg = &mt('Your LON-CAPA submission has been recorded')."\\n";  
                                     }  
                                     $msg .= &mt('Your current LON-CAPA session will be transferred to a different server in [quant,_1,second].',$numsec);  
                                     $newurl = '/adm/switchserver?otherserver='.$newserver;  
                                     if (($env{'request.role'}) && ($env{'request.role'} ne 'cm')) {  
                                         $newurl .= '&role='.$env{'request.role'};  
                                     }  
                                     if ($env{'request.symb'}) {  
                                         $newurl .= '&symb='.$env{'request.symb'};  
                                     } else {  
                                         $newurl .= '&origurl='.$requrl;  
                                     }  
                                 }  
                                 $result.=<<OFFLOAD  
 <meta http-equiv="pragma" content="no-cache" />  
 <script type="text/javascript">  
 // <![CDATA[  
 function LC_Offload_Now() {  
     var dest = "$newurl";  
     if (dest != '') {  
         window.location.href="$newurl";  
     }  
 }  
 \$(document).ready(function () {  
     window.alert('$msg');  
     if ($disable_submit) {  
         \$(".LC_hwk_submit").prop("disabled", true);  
         \$( ".LC_textline" ).prop( "readonly", "readonly");  
     }  
     setTimeout('LC_Offload_Now()', $timeout);  
 });  
 // ]]>  
 </script>  
 OFFLOAD  
                             }  
                         }  
                     }  
                 }  
             }  
         }  
     }      }
     if (!defined($title)) {      if (!defined($title)) {
  $title = 'The LearningOnline Network with CAPA';   $title = 'The LearningOnline Network with CAPA';
     }      }
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }      if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
     $result .= '<title> LON-CAPA '.$title.'</title>'      $result .= '<title> LON-CAPA '.$title.'</title>'
  .'<link rel="stylesheet" type="text/css" href="'.$url.'"';   .'<link rel="stylesheet" type="text/css" href="'.$url.'" />'
     if (!$args->{'frameset'}) {  
         $result .= ' /';  
     }  
     $result .= '>'  
         .$inhibitprint          .$inhibitprint
  .$head_extra;   .$head_extra;
     if ($env{'browser.mobile'}) {  
         $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="apple-mobile-web-app-capable" content="yes" />';  
     }  
     return $result.'</head>';      return $result.'</head>';
 }  }
   
Line 7534  OFFLOAD Line 7309  OFFLOAD
   
 Returns neccessary <meta> to set the proper encoding  Returns neccessary <meta> to set the proper encoding
   
 Inputs: optional reference to HASH -- $args passed to &headtag()  Inputs: none
   
 =cut  =cut
   
 sub font_settings {  sub font_settings {
     my ($args) = @_;  
     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'}))) {  
  $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'}) {  
             $headerstring.= ' /';  
         }  
         $headerstring .= '>'."\n";  
     }      }
     return $headerstring;      return $headerstring;
 }  }
Line 7593  sub print_suppression { Line 7362  sub print_suppression {
         }          }
         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
         my $blocked = &blocking_status('printout',$cnum,$cdom,undef,1);          my $blocked = &blocking_status('printout',$cnum,$cdom);
         if ($blocked) {          if ($blocked) {
             my $checkrole = "cm./$cdom/$cnum";              my $checkrole = "cm./$cdom/$cnum";
             if ($env{'request.course.sec'} ne '') {              if ($env{'request.course.sec'} ne '') {
Line 7640  Inputs: none Line 7409  Inputs: none
 =cut  =cut
   
 sub xml_begin {  sub xml_begin {
     my ($is_frameset) = @_;  
     my $output='';      my $output='';
   
     if ($env{'browser.mathml'}) {      if ($env{'browser.mathml'}) {
Line 7652  sub xml_begin { Line 7420  sub xml_begin {
     .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">'      .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">'
             .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" '               .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" ' 
     .'xmlns="http://www.w3.org/1999/xhtml">';      .'xmlns="http://www.w3.org/1999/xhtml">';
     } elsif ($is_frameset) {  
         $output='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'."\n".  
                 '<html>'."\n";  
     } else {      } else {
  $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n".   $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
                 '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'."\n";             .'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
     }      }
     return $output;      return $output;
 }  }
Line 7701  $args - additional optional args support Line 7466  $args - additional optional args support
              skip_phases    -> hash ref of                skip_phases    -> hash ref of 
                                     head -> skip the <html><head> generation                                      head -> skip the <html><head> generation
                                     body -> skip all <body> generation                                      body -> skip all <body> generation
              no_inline_link -> if true and in remote mode, don't show the  
                                     'Switch To Inline Menu' link  
              no_auto_mt_title -> prevent &mt()ing the title arg               no_auto_mt_title -> prevent &mt()ing the title arg
              inherit_jsmath -> when creating popup window in a page,               inherit_jsmath -> when creating popup window in a page,
                                     should it have jsmath forced on by the                                      should it have jsmath forced on by the
                                     current page                                      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
              group          -> includes the current group, if page is for a               group          -> includes the current group, if page is for a 
                                specific group                                 specific group  
   
 =back  =back
   
Line 7726  sub start_page { Line 7489  sub start_page {
     my ($result,@advtools);      my ($result,@advtools);
   
     if (! exists($args->{'skip_phases'}{'head'}) ) {      if (! exists($args->{'skip_phases'}{'head'}) ) {
         $result .= &xml_begin($args->{'frameset'}) . &headtag($title, $head_extra, $args);          $result .= &xml_begin() . &headtag($title, $head_extra, $args);
     }      }
           
     if (! exists($args->{'skip_phases'}{'body'}) ) {      if (! exists($args->{'skip_phases'}{'body'}) ) {
Line 7740  sub start_page { Line 7503  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 7781  sub start_page { Line 7544  sub start_page {
  }else{   }else{
  $result .= &Apache::lonhtmlcommon::breadcrumbs();   $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 7832  function set_wishlistlink(title, path) { Line 7590  function set_wishlistlink(title, path) {
         title = document.title;          title = document.title;
         title = title.replace(/^LON-CAPA /,'');          title = title.replace(/^LON-CAPA /,'');
     }      }
     title = encodeURIComponent(title);  
     title = title.replace("'","\\\'");  
     if (!path) {      if (!path) {
         path = location.pathname;          path = location.pathname;
     }      }
     path = encodeURIComponent(path);  
     path = path.replace("'","\\\'");  
     Win = window.open('/adm/wishlist?mode=newLink&setTitle='+title+'&setPath='+path,      Win = window.open('/adm/wishlist?mode=newLink&setTitle='+title+'&setPath='+path,
                       'wishlistNewLink','width=560,height=350,scrollbars=0');                        'wishlistNewLink','width=560,height=350,scrollbars=0');
 }  }
Line 7879  var modalWindow = { Line 7633  var modalWindow = {
  $(".LCmodal-overlay").click(function(){modalWindow.close();});   $(".LCmodal-overlay").click(function(){modalWindow.close();});
  }   }
 };  };
  var openMyModal = function(source,width,height,scrolling,transparency,style)   var openMyModal = function(source,width,height,scrolling)
  {   {
                 source = source.replace("'","&#39;");  
  modalWindow.windowId = "myModal";   modalWindow.windowId = "myModal";
  modalWindow.width = width;   modalWindow.width = width;
  modalWindow.height = height;   modalWindow.height = height;
  modalWindow.content = "<iframe width='"+width+"' height='"+height+"' frameborder='0' scrolling='"+scrolling+"' allowtransparency='"+transparency+"' src='" + source + "' style='"+style+"'></iframe>";   modalWindow.content = "<iframe width='"+width+"' height='"+height+"' frameborder='0' scrolling='"+scrolling+"' allowtransparency='true' src='" + source + "'>&lt/iframe>";
  modalWindow.open();   modalWindow.open();
  };   };
 // END LON-CAPA Internal -->  // END LON-CAPA Internal -->
 // ]]>  // ]]>
 </script>  </script>
Line 7895  ENDMODAL Line 7648  ENDMODAL
 }  }
   
 sub modal_link {  sub modal_link {
     my ($link,$linktext,$width,$height,$target,$scrolling,$title,$transparency,$style)=@_;      my ($link,$linktext,$width,$height,$target,$scrolling,$title)=@_;
     unless ($width) { $width=480; }      unless ($width) { $width=480; }
     unless ($height) { $height=400; }      unless ($height) { $height=400; }
     unless ($scrolling) { $scrolling='yes'; }      unless ($scrolling) { $scrolling='yes'; }
     unless ($transparency) { $transparency='true'; }  
   
     my $target_attr;      my $target_attr;
     if (defined($target)) {      if (defined($target)) {
         $target_attr = 'target="'.$target.'"';          $target_attr = 'target="'.$target.'"';
     }      }
     return <<"ENDLINK";      return <<"ENDLINK";
 <a href="$link" $target_attr title="$title" onclick="javascript:openMyModal('$link',$width,$height,'$scrolling','$transparency','$style'); return false;">  <a href="$link" $target_attr title="$title" onclick="javascript:openMyModal('$link',$width,$height,'$scrolling'); return false;">
            $linktext</a>             $linktext</a>
 ENDLINK  ENDLINK
 }  }
Line 7934  sub modal_adhoc_inner { Line 7685  sub modal_adhoc_inner {
     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').
                  $content.                      $content.
                  &end_scrollbox().                   &end_scrollbox().
                  &end_page()                 &end_page()
              );               );
     return &modal_adhoc_script($funcname,$width,$height,$content);      return &modal_adhoc_script($funcname,$width,$height,$content);
 }  }
Line 8056  sub LCprogressbar { Line 7807  sub LCprogressbar {
     $LCcurrentid=$$.'_'.$LCidcnt;      $LCcurrentid=$$.'_'.$LCidcnt;
     my $starting=&mt('Starting');      my $starting=&mt('Starting');
     my $content=(<<ENDPROGBAR);      my $content=(<<ENDPROGBAR);
   <p>
   <div id="progressbar$LCcurrentid">    <div id="progressbar$LCcurrentid">
     <span class="pblabel">$starting</span>      <span class="pblabel">$starting</span>
   </div>    </div>
   </p>
 ENDPROGBAR  ENDPROGBAR
     &r_print($r,$content.&LCprogressbar_script($LCcurrentid));      &r_print($r,$content.&LCprogressbar_script($LCcurrentid));
 }  }
Line 8154  sub validate_page { Line 7907  sub validate_page {
   
   
 sub start_scrollbox {  sub start_scrollbox {
     my ($outerwidth,$width,$height,$id,$bgcolor,$cursor,$needjsready) = @_;      my ($outerwidth,$width,$height,$id,$bgcolor)=@_;
     unless ($outerwidth) { $outerwidth='520px'; }      unless ($outerwidth) { $outerwidth='520px'; }
     unless ($width) { $width='500px'; }      unless ($width) { $width='500px'; }
     unless ($height) { $height='200px'; }      unless ($height) { $height='200px'; }
     my ($table_id,$div_id,$tdcol);      my ($table_id,$div_id,$tdcol);
     if ($id ne '') {      if ($id ne '') {
         $table_id = ' id="table_'.$id.'"';          $table_id = " id='table_$id'";
         $div_id = ' id="div_'.$id.'"';          $div_id = " id='div_$id'";
     }      }
     if ($bgcolor ne '') {      if ($bgcolor ne '') {
         $tdcol = "background-color: $bgcolor;";          $tdcol = "background-color: $bgcolor;";
     }      }
     my $nicescroll_js;  
     if ($env{'browser.mobile'}) {  
         $nicescroll_js = &nicescroll_javascript('div_'.$id,$cursor,$needjsready);  
     }  
     return <<"END";      return <<"END";
 $nicescroll_js  <table style="width: $outerwidth; border: 1px solid none;"$table_id><tr><td style="width: $width;$tdcol"><div style="overflow:auto; width:$width; height: $height;"$div_id>
   
 <table style="width: $outerwidth; border: 1px solid none;"$table_id><tr><td style="width: $width;$tdcol">  
 <div style="overflow:auto; width:$width; height:$height;"$div_id>  
 END  END
 }  }
   
Line 8182  sub end_scrollbox { Line 7928  sub end_scrollbox {
     return '</div></td></tr></table>';      return '</div></td></tr></table>';
 }  }
   
 sub nicescroll_javascript {  
     my ($id,$cursor,$needjsready,$framecheck,$location) = @_;  
     my %options;  
     if (ref($cursor) eq 'HASH') {  
         %options = %{$cursor};  
     }  
     unless ($options{'railalign'} =~ /^left|right$/) {  
         $options{'railalign'} = 'left';  
     }  
     unless ($options{'cursorcolor'} =~ /^\#\w+$/) {  
         my $function  = &get_users_function();  
         $options{'cursorcolor'} = &designparm($function.'.sidebg',$env{'request.role.domain'});  
         unless ($options{'cursorcolor'} =~ /^\#\w+$/) {  
             $options{'cursorcolor'} = '#00F';  
         }  
     }  
     if ($options{'cursoropacity'} =~ /^[\d.]+$/) {  
         unless ($options{'cursoropacity'} >= 0.0 && $options{'cursoropacity'} <=1.0) {  
             $options{'cursoropacity'}='1.0';  
         }  
     } else {  
         $options{'cursoropacity'}='1.0';  
     }  
     if ($options{'cursorfixedheight'} eq 'none') {  
         delete($options{'cursorfixedheight'});  
     } else {  
         unless ($options{'cursorfixedheight'} =~ /^\d+$/) { $options{'cursorfixedheight'}='50'; }  
     }  
     unless ($options{'railoffset'} =~ /^{[\w\:\d\-,]+}$/) {  
         delete($options{'railoffset'});  
     }  
     my @niceoptions;  
     while (my($key,$value) = each(%options)) {  
         if ($value =~ /^\{.+\}$/) {  
             push(@niceoptions,$key.':'.$value);  
         } else {  
             push(@niceoptions,$key.':"'.$value.'"');  
         }  
     }  
     my $nicescroll_js = '  
 $(document).ready(  
       function() {  
           $("#'.$id.'").niceScroll({'.join(',',@niceoptions).'});  
       }  
 );  
 ';  
     if ($framecheck) {  
         $nicescroll_js .= '  
 function expand_div(caller) {  
     if (top === self) {  
         document.getElementById("'.$id.'").style.width = "auto";  
         document.getElementById("'.$id.'").style.height = "auto";  
     } else {  
         try {  
             if (parent.frames) {  
                 if (parent.frames.length > 1) {  
                     var framesrc = parent.frames[1].location.href;  
                     var currsrc = framesrc.replace(/\#.*$/,"");  
                     if ((caller == "search") || (currsrc == "'.$location.'")) {  
                         document.getElementById("'.$id.'").style.width = "auto";  
                         document.getElementById("'.$id.'").style.height = "auto";  
                     }  
                 }  
             }  
         } catch (e) {  
             return;  
         }  
     }  
     return;  
 }  
 ';  
     }  
     if ($needjsready) {  
         $nicescroll_js = '  
 <script type="text/javascript">'."\n".$nicescroll_js."\n</script>\n";  
     } else {  
         $nicescroll_js = &Apache::lonhtmlcommon::scripttag($nicescroll_js);  
     }  
     return $nicescroll_js;  
 }  
   
 sub simple_error_page {  sub simple_error_page {
     my ($r,$title,$msg,$args) = @_;      my ($r,$title,$msg) = @_;
     if (ref($args) eq 'HASH') {  
         if (!$args->{'no_auto_mt_msg'}) { $msg = &mt($msg); }  
     } else {  
         $msg = &mt($msg);  
     }  
   
     my $page =      my $page =
  &Apache::loncommon::start_page($title).   &Apache::loncommon::start_page($title).
  '<p class="LC_error">'.$msg.'</p>'.   '<p class="LC_error">'.&mt($msg).'</p>'.
  &Apache::loncommon::end_page();   &Apache::loncommon::end_page();
     if (ref($r)) {      if (ref($r)) {
  $r->print($page);   $r->print($page);
Line 8489  role status: active, previous or future. Line 8148  role status: active, previous or future.
 sub check_user_status {  sub check_user_status {
     my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;      my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
     my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);      my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
     my @uroles = keys(%userinfo);      my @uroles = keys %userinfo;
     my $srchstr;      my $srchstr;
     my $active_chk = 'none';      my $active_chk = 'none';
     my $now = time;      my $now = time;
Line 8578  sub get_sections { Line 8237  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 8755  sub get_course_users { Line 8414  sub get_course_users {
                               active   => 'Active',                                active   => 'Active',
                               future   => 'Future',                                future   => 'Future',
                             );                              );
         my (%nothide,@possdoms);          my %nothide;
         if ($hidepriv) {          if ($hidepriv) {
             my %coursehash=&Apache::lonnet::coursedescription($cdom.'_'.$cnum);              my %coursehash=&Apache::lonnet::coursedescription($cdom.'_'.$cnum);
             foreach my $user (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {              foreach my $user (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
Line 8765  sub get_course_users { Line 8424  sub get_course_users {
                     $nothide{$user} = 1;                      $nothide{$user} = 1;
                 }                  }
             }              }
             my @possdoms = ($cdom);  
             if ($coursehash{'checkforpriv'}) {  
                 push(@possdoms,split(/,/,$coursehash{'checkforpriv'}));  
             }  
         }          }
         foreach my $person (sort(keys(%coursepersonnel))) {          foreach my $person (sort(keys(%coursepersonnel))) {
             my $match = 0;              my $match = 0;
Line 8804  sub get_course_users { Line 8459  sub get_course_users {
                 }                  }
                 if ($uname ne '' && $udom ne '') {                  if ($uname ne '' && $udom ne '') {
                     if ($hidepriv) {                      if ($hidepriv) {
                         if ((&Apache::lonnet::privileged($uname,$udom,\@possdoms)) &&                          if ((&Apache::lonnet::privileged($uname,$udom)) &&
                             (!$nothide{$uname.':'.$udom})) {                              (!$nothide{$uname.':'.$udom})) {
                             next;                              next;
                         }                          }
Line 8892  sub get_user_info { Line 8547  sub get_user_info {
   
 =item * &get_user_quota()  =item * &get_user_quota()
   
 Retrieves quota assigned for storage of user files.  Retrieves quota assigned for storage of portfolio files for a user  
 Default is to report quota for portfolio files.  
   
 Incoming parameters:  Incoming parameters:
 1. user's username  1. user's username
 2. user's domain  2. user's domain
 3. quota name - portfolio, author, or course  
    (if no quota name provided, defaults to portfolio).  
 4. crstype - official, unofficial, textbook or community, if quota name is  
    course  
   
 Returns:  Returns:
 1. Disk quota (in MB) assigned to student.  1. Disk quota (in Mb) assigned to student.
 2. (Optional) Type of setting: custom or default  2. (Optional) Type of setting: custom or default
    (individually assigned or default for user's      (individually assigned or default for user's 
    institutional status).     institutional status).
Line 8915  Returns: Line 8565  Returns:
   
 If a value has been stored in the user's environment,   If a value has been stored in the user's environment, 
 it will return that, otherwise it returns the maximal default  it will return that, otherwise it returns the maximal default
 defined for the user's institutional status(es) in the domain.  defined for the user's instituional status(es) in the domain.
   
 =cut  =cut
   
Line 8923  defined for the user's institutional sta Line 8573  defined for the user's institutional sta
   
   
 sub get_user_quota {  sub get_user_quota {
     my ($uname,$udom,$quotaname,$crstype) = @_;      my ($uname,$udom) = @_;
     my ($quota,$quotatype,$settingstatus,$defquota);      my ($quota,$quotatype,$settingstatus,$defquota);
     if (!defined($udom)) {      if (!defined($udom)) {
         $udom = $env{'user.domain'};          $udom = $env{'user.domain'};
Line 8938  sub get_user_quota { Line 8588  sub get_user_quota {
         $defquota = 0;           $defquota = 0; 
     } else {      } else {
         my $inststatus;          my $inststatus;
         if ($quotaname eq 'course') {          if ($udom eq $env{'user.domain'} && $uname eq $env{'user.name'}) {
             if (($env{'course.'.$udom.'_'.$uname.'.num'} eq $uname) &&              $quota = $env{'environment.portfolioquota'};
                 ($env{'course.'.$udom.'_'.$uname.'.domain'} eq $udom)) {              $inststatus = $env{'environment.inststatus'};
                 $quota = $env{'course.'.$udom.'_'.$uname.'.internal.uploadquota'};          } else {
             } else {              my %userenv = 
                 my %cenv = &Apache::lonnet::coursedescription("$udom/$uname");                  &Apache::lonnet::get('environment',['portfolioquota',
                 $quota = $cenv{'internal.uploadquota'};                                       'inststatus'],$udom,$uname);
             }              my ($tmp) = keys(%userenv);
               if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
                   $quota = $userenv{'portfolioquota'};
                   $inststatus = $userenv{'inststatus'};
               } else {
                   undef(%userenv);
               }
           }
           ($defquota,$settingstatus) = &default_quota($udom,$inststatus);
           if ($quota eq '') {
               $quota = $defquota;
               $quotatype = 'default';
         } else {          } else {
             if ($udom eq $env{'user.domain'} && $uname eq $env{'user.name'}) {              $quotatype = 'custom';
                 if ($quotaname eq 'author') {  
                     $quota = $env{'environment.authorquota'};  
                 } else {  
                     $quota = $env{'environment.portfolioquota'};  
                 }  
                 $inststatus = $env{'environment.inststatus'};  
             } else {  
                 my %userenv =   
                     &Apache::lonnet::get('environment',['portfolioquota',  
                                          'authorquota','inststatus'],$udom,$uname);  
                 my ($tmp) = keys(%userenv);  
                 if ($tmp !~ /^(con_lost|error|no_such_host)/i) {  
                     if ($quotaname eq 'author') {  
                         $quota = $userenv{'authorquota'};  
                     } else {  
                         $quota = $userenv{'portfolioquota'};  
                     }  
                     $inststatus = $userenv{'inststatus'};  
                 } else {  
                     undef(%userenv);  
                 }  
             }  
         }  
         if ($quota eq '' || wantarray) {  
             if ($quotaname eq 'course') {  
                 my %domdefs = &Apache::lonnet::get_domain_defaults($udom);  
                 if (($crstype eq 'official') || ($crstype eq 'unofficial') ||  
                     ($crstype eq 'community') || ($crstype eq 'textbook')) {  
                     $defquota = $domdefs{$crstype.'quota'};  
                 }  
                 if ($defquota eq '') {  
                     $defquota = 500;  
                 }  
             } else {  
                 ($defquota,$settingstatus) = &default_quota($udom,$inststatus,$quotaname);  
             }  
             if ($quota eq '') {  
                 $quota = $defquota;  
                 $quotatype = 'default';  
             } else {  
                 $quotatype = 'custom';  
             }  
         }          }
     }      }
     if (wantarray) {      if (wantarray) {
Line 9009  Retrieves default quota assigned for sto Line 8628  Retrieves default quota assigned for sto
 given an (optional) user's institutional status.  given an (optional) user's institutional status.
   
 Incoming parameters:  Incoming parameters:
   
 1. domain  1. domain
 2. (Optional) institutional status(es).  This is a : separated list of   2. (Optional) institutional status(es).  This is a : separated list of 
    status types (e.g., faculty, staff, student etc.)     status types (e.g., faculty, staff, student etc.)
    which apply to the user for whom the default is being retrieved.     which apply to the user for whom the default is being retrieved.
    If the institutional status string in undefined, the domain     If the institutional status string in undefined, the domain
    default quota will be returned.     default quota will be returned. 
 3.  quota name - portfolio, author, or course  
    (if no quota name provided, defaults to portfolio).  
   
 Returns:  Returns:
   1. Default disk quota (in Mb) for user portfolios in the domain.
 1. Default disk quota (in MB) for user portfolios in the domain.  
 2. (Optional) institutional type which determined the value of the  2. (Optional) institutional type which determined the value of the
    default quota.     default quota.
   
 If a value has been stored in the domain's configuration db,  If a value has been stored in the domain's configuration db,
 it will return that, otherwise it returns 20 (for backwards   it will return that, otherwise it returns 20 (for backwards 
 compatibility with domains which have not set up a configuration  compatibility with domains which have not set up a configuration
 db file; the original statically defined portfolio quota was 20 MB).   db file; the original statically defined portfolio quota was 20 Mb). 
   
 If the user's status includes multiple types (e.g., staff and student),  If the user's status includes multiple types (e.g., staff and student),
 the largest default quota which applies to the user determines the  the largest default quota which applies to the user determines the
 default quota returned.  default quota returned.
   
   =back
   
 =cut  =cut
   
 ###############################################  ###############################################
   
   
 sub default_quota {  sub default_quota {
     my ($udom,$inststatus,$quotaname) = @_;      my ($udom,$inststatus) = @_;
     my ($defquota,$settingstatus);      my ($defquota,$settingstatus);
     my %quotahash = &Apache::lonnet::get_dom('configuration',      my %quotahash = &Apache::lonnet::get_dom('configuration',
                                             ['quotas'],$udom);                                              ['quotas'],$udom);
     my $key = 'defaultquota';  
     if ($quotaname eq 'author') {  
         $key = 'authorquota';  
     }  
     if (ref($quotahash{'quotas'}) eq 'HASH') {      if (ref($quotahash{'quotas'}) eq 'HASH') {
         if ($inststatus ne '') {          if ($inststatus ne '') {
             my @statuses = map { &unescape($_); } split(/:/,$inststatus);              my @statuses = map { &unescape($_); } split(/:/,$inststatus);
             foreach my $item (@statuses) {              foreach my $item (@statuses) {
                 if (ref($quotahash{'quotas'}{$key}) eq 'HASH') {                  if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') {
                     if ($quotahash{'quotas'}{$key}{$item} ne '') {                      if ($quotahash{'quotas'}{'defaultquota'}{$item} ne '') {
                         if ($defquota eq '') {                          if ($defquota eq '') {
                             $defquota = $quotahash{'quotas'}{$key}{$item};                              $defquota = $quotahash{'quotas'}{'defaultquota'}{$item};
                             $settingstatus = $item;                              $settingstatus = $item;
                         } elsif ($quotahash{'quotas'}{$key}{$item} > $defquota) {                          } elsif ($quotahash{'quotas'}{'defaultquota'}{$item} > $defquota) {
                             $defquota = $quotahash{'quotas'}{$key}{$item};                              $defquota = $quotahash{'quotas'}{'defaultquota'}{$item};
                             $settingstatus = $item;                              $settingstatus = $item;
                         }                          }
                     }                      }
                 } elsif ($key eq 'defaultquota') {                  } else {
                     if ($quotahash{'quotas'}{$item} ne '') {                      if ($quotahash{'quotas'}{$item} ne '') {
                         if ($defquota eq '') {                          if ($defquota eq '') {
                             $defquota = $quotahash{'quotas'}{$item};                              $defquota = $quotahash{'quotas'}{$item};
Line 9076  sub default_quota { Line 8689  sub default_quota {
             }              }
         }          }
         if ($defquota eq '') {          if ($defquota eq '') {
             if (ref($quotahash{'quotas'}{$key}) eq 'HASH') {              if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') {
                 $defquota = $quotahash{'quotas'}{$key}{'default'};                  $defquota = $quotahash{'quotas'}{'defaultquota'}{'default'};
             } elsif ($key eq 'defaultquota') {              } else {
                 $defquota = $quotahash{'quotas'}{'default'};                  $defquota = $quotahash{'quotas'}{'default'};
             }              }
             $settingstatus = 'default';              $settingstatus = 'default';
             if ($defquota eq '') {  
                 if ($quotaname eq 'author') {  
                     $defquota = 500;  
                 }  
             }  
         }          }
     } else {      } else {
         $settingstatus = 'default';          $settingstatus = 'default';
         if ($quotaname eq 'author') {          $defquota = 20;
             $defquota = 500;  
         } else {  
             $defquota = 20;  
         }  
     }      }
     if (wantarray) {      if (wantarray) {
         return ($defquota,$settingstatus);          return ($defquota,$settingstatus);
Line 9103  sub default_quota { Line 8707  sub default_quota {
     }      }
 }  }
   
 ###############################################  
   
 =pod  
   
 =item * &excess_filesize_warning()  
   
 Returns warning message if upload of file to authoring space, or copying  
 of existing file within authoring space will cause quota for the authoring  
 space to be exceeded.  
   
 Same, if upload of a file directly to a course/community via Course Editor  
 will cause quota for uploaded content for the course to be exceeded.  
   
 Inputs: 7   
 1. username or coursenum  
 2. domain  
 3. context ('author' or 'course')  
 4. filename of file for which action is being requested  
 5. filesize (kB) of file  
 6. action being taken: copy or upload.  
 7. quotatype (in course context -- official, unofficial, community or textbook).  
   
 Returns: 1 scalar: HTML to display containing warning if quota would be exceeded,  
          otherwise return null.  
   
 =back  
   
 =cut  
   
 sub excess_filesize_warning {  
     my ($uname,$udom,$context,$filename,$filesize,$action,$quotatype) = @_;  
     my $current_disk_usage = 0;  
     my $disk_quota = &get_user_quota($uname,$udom,$context,$quotatype); #expressed in MB  
     if ($context eq 'author') {  
         my $authorspace = $Apache::lonnet::perlvar{'lonDocRoot'}."/priv/$udom/$uname";  
         $current_disk_usage = &Apache::lonnet::diskusage($udom,$uname,$authorspace);  
     } else {  
         foreach my $subdir ('docs','supplemental') {  
             $current_disk_usage += &Apache::lonnet::diskusage($udom,$uname,"userfiles/$subdir",1);  
         }  
     }  
     $disk_quota = int($disk_quota * 1000);  
     if (($current_disk_usage + $filesize) > $disk_quota) {  
         return '<p class="LC_warning">'.  
                 &mt("Unable to $action [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.",  
                     '<span class="LC_filename">'.$filename.'</span>',$filesize).'</p>'.  
                '<p>'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',  
                             $disk_quota,$current_disk_usage).  
                '</p>';  
     }  
     return;  
 }  
   
 ###############################################  
   
   
 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 9600  sub personal_data_fieldtitles { Line 9148  sub personal_data_fieldtitles {
   
 sub sorted_inst_types {  sub sorted_inst_types {
     my ($dom) = @_;      my ($dom) = @_;
     my ($usertypes,$order);      my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom);
     my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);  
     if (ref($domdefaults{'inststatus'}) eq 'HASH') {  
         $usertypes = $domdefaults{'inststatus'}{'inststatustypes'};  
         $order = $domdefaults{'inststatus'}{'inststatusorder'};  
     } else {  
         ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom);  
     }  
     my $othertitle = &mt('All users');      my $othertitle = &mt('All users');
     if ($env{'request.course.id'}) {      if ($env{'request.course.id'}) {
         $othertitle  = &mt('Any users');          $othertitle  = &mt('Any users');
Line 10005  sub ask_for_embedded_content { Line 9546  sub ask_for_embedded_content {
     my $numexisting = 0;      my $numexisting = 0;
     my $numunused = 0;      my $numunused = 0;
     my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath,$cdom,$cnum,      my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath,$cdom,$cnum,
         $fileloc,$filename,$delete_output,$modify_output,$title,$symb,$path,$navmap);          $fileloc,$filename,$delete_output,$modify_output,$title,$symb,$path);
     my $heading = &mt('Upload embedded files');      my $heading = &mt('Upload embedded files');
     my $buttontext = &mt('Upload');      my $buttontext = &mt('Upload');
   
       my $navmap;
     if ($env{'request.course.id'}) {      if ($env{'request.course.id'}) {
         if ($actionurl eq '/adm/dependencies') {          $navmap = Apache::lonnavmaps::navmap->new();
             $navmap = Apache::lonnavmaps::navmap->new();  
         }  
         $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};  
         $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'}) {
             $current_path = $env{'form.currentpath'};              $current_path = $env{'form.currentpath'};
         }          }
         if ($actionurl eq '/adm/coursegrp_portfolio') {          if ($actionurl eq '/adm/coursegrp_portfolio') {
             $udom = $cdom;              $udom = $env{'course.'.$env{'request.course.id'}.'.domain'};
             $uname = $cnum;              $uname = $env{'course.'.$env{'request.course.id'}.'.num'};
             $url = '/userfiles/groups/'.$env{'form.group'}.'/portfolio';              $url = '/userfiles/groups/'.$env{'form.group'}.'/portfolio';
         } else {          } else {
             $udom = $env{'user.domain'};              $udom = $env{'user.domain'};
Line 10048  sub ask_for_embedded_content { Line 9585  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 '') {
               $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
               $cnum =  $env{'course.'.$env{'request.course.id'}.'.num'};
             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{^/}) {  
                     $toplevel = "/$url";  
                 }  
                 ($rem) = ($toplevel =~ m{^(.+/)[^/]+$});                  ($rem) = ($toplevel =~ m{^(.+/)[^/]+$});
                 if ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/portfolio/syllabus\E)}) {                  ($path) =  
                     $path = $1;                      ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});
                 } else {                  $fileloc = &Apache::lonnet::filelocation('',$toplevel);
                     ($path) =  
                         ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});  
                 }  
                 if ($toplevel=~/^\/*(uploaded|editupload)/) {  
                     $fileloc = $toplevel;  
                     $fileloc=~ s/^\s*(\S+)\s*$/$1/;  
                     my ($udom,$uname,$fname) =  
                         ($fileloc=~ m{^/+(?:uploaded|editupload)/+($match_domain)/+($match_name)/+(.*)$});  
                     $fileloc = propath($udom,$uname).'/userfiles/'.$fname;  
                 } else {  
                     $fileloc = &Apache::lonnet::filelocation('',$toplevel);  
                 }  
                 $fileloc =~ s{^/}{};                  $fileloc =~ s{^/}{};
                 ($filename) = ($fileloc =~ m{.+/([^/]+)$});                  ($filename) = ($fileloc =~ m{.+/([^/]+)$});
                 $heading = &mt('Status of dependencies in [_1]',"$title ($filename)");                  $heading = &mt('Status of dependencies in [_1]',"$title ($filename)");
             }              }
         }          }
     } elsif ($actionurl eq "/public/$cdom/$cnum/syllabus") {      }
         $udom = $cdom;      my $now = time();
         $uname = $cnum;      foreach my $embed_file (keys(%{$allfiles})) {
         $url = "/uploaded/$cdom/$cnum/portfolio/syllabus";          my $absolutepath;
         $toplevel = $url;  
         $path = $url;  
         $fileloc = &Apache::lonnet::filelocation('',$toplevel).'/';  
         $fileloc =~ s{^/}{};  
     }  
     foreach my $file (keys(%{$allfiles})) {  
         my $embed_file;  
         if (($path eq "/uploaded/$cdom/$cnum/portfolio/syllabus") && ($file =~ m{^\Q$path/\E(.+)$})) {  
             $embed_file = $1;  
         } else {  
             $embed_file = $file;  
         }  
         my ($absolutepath,$cleaned_file);  
         if ($embed_file =~ m{^\w+://}) {          if ($embed_file =~ m{^\w+://}) {
             $cleaned_file = $embed_file;              $newfiles{$embed_file} = 1;
             $newfiles{$cleaned_file} = 1;              $mapping{$embed_file} = $embed_file;
             $mapping{$cleaned_file} = $embed_file;  
         } else {          } else {
             $cleaned_file = &clean_path($embed_file);  
             if ($embed_file =~ m{^/}) {              if ($embed_file =~ m{^/}) {
                 $absolutepath = $embed_file;                  $absolutepath = $embed_file;
                   $embed_file =~ s{^(/+)}{};
             }              }
             if ($cleaned_file =~ m{/}) {              if ($embed_file =~ m{/}) {
                 my ($path,$fname) = ($cleaned_file =~ m{^(.+)/([^/]*)$});                  my ($path,$fname) = ($embed_file =~ m{^(.+)/([^/]*)$});
                 $path = &check_for_traversal($path,$url,$toplevel);                  $path = &check_for_traversal($path,$url,$toplevel);
                 my $item = $fname;                  my $item = $fname;
                 if ($path ne '') {                  if ($path ne '') {
Line 10128  sub ask_for_embedded_content { Line 9638  sub ask_for_embedded_content {
             } else {              } else {
                 $dependencies{$embed_file} = 1;                  $dependencies{$embed_file} = 1;
                 if ($absolutepath) {                  if ($absolutepath) {
                     $mapping{$cleaned_file} = $absolutepath;                      $mapping{$embed_file} = $absolutepath;
                 } else {                  } else {
                     $mapping{$cleaned_file} = $embed_file;                      $mapping{$embed_file} = $embed_file;
                 }                  }
             }              }
         }          }
Line 10138  sub ask_for_embedded_content { Line 9648  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 10155  sub ask_for_embedded_content { Line 9664  sub ask_for_embedded_content {
             }              }
         } elsif (($actionurl eq '/adm/dependencies') ||          } elsif (($actionurl eq '/adm/dependencies') ||
                  (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&                   (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&
                   ($args->{'context'} eq 'paste')) ||                    ($args->{'context'} eq 'paste'))) {
                  ($actionurl eq "/public/$cdom/$cnum/syllabus")) {  
             if ($env{'request.course.id'} ne '') {              if ($env{'request.course.id'} ne '') {
                 my $dir;                  my ($dir) = ($fileloc =~ m{^(.+/)[^/]+$});
                 if ($actionurl eq "/public/$cdom/$cnum/syllabus") {  
                     $dir = $fileloc;  
                 } else {  
                     ($dir) = ($fileloc =~ m{^(.+/)[^/]+$});  
                 }  
                 if ($dir ne '') {                  if ($dir ne '') {
                     my ($sublistref,$listerror) =                      my ($sublistref,$listerror) =
                         &Apache::lonnet::dirlist($dir.$path,$cdom,$cnum,$getpropath,undef,'/');                          &Apache::lonnet::dirlist($dir.$path,$cdom,$cnum,$getpropath,undef,'/');
Line 10211  sub ask_for_embedded_content { Line 9714  sub ask_for_embedded_content {
         }          }
     }      }
     my %currfile;      my %currfile;
     if (($actionurl eq '/adm/portfolio') ||      if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
         ($actionurl eq '/adm/coursegrp_portfolio')) {  
         my ($dirlistref,$listerror) =          my ($dirlistref,$listerror) =
             &Apache::lonnet::dirlist($url,$udom,$uname,$getpropath);              &Apache::lonnet::dirlist($url,$udom,$uname,$getpropath);
         if (ref($dirlistref) eq 'ARRAY') {          if (ref($dirlistref) eq 'ARRAY') {
Line 10228  sub ask_for_embedded_content { Line 9730  sub ask_for_embedded_content {
         }          }
     } elsif (($actionurl eq '/adm/dependencies') ||      } elsif (($actionurl eq '/adm/dependencies') ||
              (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&               (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&
               ($args->{'context'} eq 'paste')) ||                ($args->{'context'} eq 'paste'))) {
              ($actionurl eq "/public/$cdom/$cnum/syllabus")) {  
         if ($env{'request.course.id'} ne '') {          if ($env{'request.course.id'} ne '') {
             my ($dir) = ($fileloc =~ m{^(.+/)[^/]+$});              my ($dir) = ($fileloc =~ m{^(.+/)[^/]+$});
             if ($dir ne '') {              if ($dir ne '') {
Line 10264  sub ask_for_embedded_content { Line 9765  sub ask_for_embedded_content {
                 ($file eq $filename.'.bak') ||                  ($file eq $filename.'.bak') ||
                 ($dependencies{$file})) {                  ($dependencies{$file})) {
             if ($actionurl eq '/adm/dependencies') {              if ($actionurl eq '/adm/dependencies') {
                 unless ($toplevel =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus\E}) {                  next if (($rem ne '') &&
                     next if (($rem ne '') &&                           (($env{"httpref.$rem".$file} ne '') ||
                              (($env{"httpref.$rem".$file} ne '') ||                            (ref($navmap) &&
                               (ref($navmap) &&                            (($navmap->getResourceByUrl($rem.$file) ne '') ||
                               (($navmap->getResourceByUrl($rem.$file) ne '') ||                             (($file =~ /^(.*\.s?html?)\.bak$/i) &&
                                (($file =~ /^(.*\.s?html?)\.bak$/i) &&                              ($navmap->getResourceByUrl($rem.$1)))))));
                                 ($navmap->getResourceByUrl($rem.$1)))))));  
                 }  
             }              }
             $unused{$file} = 1;              $unused{$file} = 1;
         }          }
Line 10280  sub ask_for_embedded_content { Line 9779  sub ask_for_embedded_content {
         ($args->{'context'} eq 'paste')) {          ($args->{'context'} eq 'paste')) {
         $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") &&  
              (ref($args) eq 'HASH') && ($args->{'context'} eq 'rewrites')) {  
         $counter = scalar(keys(%existing));  
         $numpathchg = scalar(keys(%pathchanges));  
         return ($output,$counter,$numpathchg,\%existing,\%mapping);  
     }      }
     foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) {      foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) {
         if ($actionurl eq '/adm/dependencies') {          if ($actionurl eq '/adm/dependencies') {
             next if ($embed_file =~ m{^\w+://});              next if ($embed_file =~ m{^\w+://});
         }          }
         $upload_output .= &start_data_table_row().          $upload_output .= &start_data_table_row().
                           '<td valign="top"><img src="'.&icon($embed_file).'" />&nbsp;'.                            '<td><img src="'.&icon($embed_file).'" />&nbsp;'.
                           '<span class="LC_filename">'.$embed_file.'</span>';                            '<span class="LC_filename">'.$embed_file.'</span>';
         unless ($mapping{$embed_file} eq $embed_file) {          unless ($mapping{$embed_file} eq $embed_file) {
             $upload_output .= '<br /><span class="LC_info" style="font-size:smaller;">'.              $upload_output .= '<br /><span class="LC_info" style="font-size:smaller;">'.&mt('changed from: [_1]',$mapping{$embed_file}).'</span>';
                               &mt('changed from: [_1]',$mapping{$embed_file}).'</span>';  
         }          }
         $upload_output .= '</td>';          $upload_output .= '</td><td>';
         if ($args->{'ignore_remote_references'} && $embed_file =~ m{^\w+://}) {           if ($args->{'ignore_remote_references'} && $embed_file =~ m{^\w+://}) { 
             $upload_output.='<td align="right">'.              $upload_output.='<span class="LC_warning">'.&mt("URL points to other server.").'</span>';
                             '<span class="LC_info LC_fontsize_medium">'.  
                             &mt("URL points to web address").'</span>';  
             $numremref++;              $numremref++;
         } elsif ($args->{'error_on_invalid_names'}          } elsif ($args->{'error_on_invalid_names'}
             && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) {              && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) {
             $upload_output.='<td align="right"><span class="LC_warning">'.              $upload_output.='<span class="LC_warning">'.&mt('Invalid characters').'</span>';
                             &mt('Invalid characters').'</span>';  
             $numinvalid++;              $numinvalid++;
         } else {          } else {
             $upload_output .= '<td>'.              $upload_output .= &embedded_file_element('upload_embedded',$counter,
                               &embedded_file_element('upload_embedded',$counter,  
                                                      $embed_file,\%mapping,                                                       $embed_file,\%mapping,
                                                      $allfiles,$codebase,'upload');                                                       $allfiles,$codebase,'upload');
             $counter ++;              $counter ++;
Line 10340  sub ask_for_embedded_content { Line 9829  sub ask_for_embedded_content {
             $counter ++;              $counter ++;
         } else {          } else {
             $upload_output .= &start_data_table_row().              $upload_output .= &start_data_table_row().
                               '<td valign="top"><img src="'.&icon($embed_file).'" />&nbsp;'.                                '<td><span class="LC_filename">'.$embed_file.'</span></td>';
                               '<span class="LC_filename">'.$embed_file.'</span></td>'.                                '<td><span class="LC_warning">'.&mt('Already exists').'</span></td>'.
                               '<td align="right"><span class="LC_info LC_fontsize_medium">'.&mt('Already exists').'</span></td>'.  
                               &Apache::loncommon::end_data_table_row()."\n";                                &Apache::loncommon::end_data_table_row()."\n";
         }          }
     }      }
Line 10437  sub ask_for_embedded_content { Line 9925  sub ask_for_embedded_content {
         $output = '<b>'.&mt('Referenced files').'</b>:<br />';          $output = '<b>'.&mt('Referenced files').'</b>:<br />';
         if ($applies > 1) {          if ($applies > 1) {
             $output .=                $output .=  
                 &mt('No dependencies need to be uploaded, as one of the following applies to each reference:').'<ul>';                  &mt('No files need to be uploaded, as one of the following applies to each reference:').'<ul>';
             if ($numremref) {              if ($numremref) {
                 $output .= '<li>'.&mt('reference is to a URL which points to another server').'</li>'."\n";                  $output .= '<li>'.&mt('reference is to a URL which points to another server').'</li>'."\n";
             }              }
Line 10480  sub ask_for_embedded_content { Line 9968  sub ask_for_embedded_content {
             $chgcount ++;              $chgcount ++;
         }          }
     }      }
     if (($counter) || ($numunused)) {      if ($counter) {
         if ($numpathchg) {          if ($numpathchg) {
             $output .= '<input type ="hidden" name="number_pathchange_items" value="'.              $output .= '<input type ="hidden" name="number_pathchange_items" value="'.
                        $numpathchg.'" />'."\n";                         $numpathchg.'" />'."\n";
Line 10493  sub ask_for_embedded_content { Line 9981  sub ask_for_embedded_content {
         } elsif ($actionurl eq '/adm/dependencies') {          } elsif ($actionurl eq '/adm/dependencies') {
             $output .= '<input type="hidden" name="action" value="process_changes" />';              $output .= '<input type="hidden" name="action" value="process_changes" />';
         }          }
         $output .= '<input type ="submit" value="'.$buttontext.'" />'."\n".'</form>'."\n";          $output .=  '<input type ="submit" value="'.$buttontext.'" />'."\n".'</form>'."\n";
     } elsif ($numpathchg) {      } elsif ($numpathchg) {
         my %pathchange = ();          my %pathchange = ();
         $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);          $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);
         if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {          if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
             $output .= '<p>'.&mt('or').'</p>';               $output .= '<p>'.&mt('or').'</p>'; 
         }          } 
     }      }
     return ($output,$counter,$numpathchg);      return ($output,$counter,$numpathchg);
 }  }
   
 =pod  
   
 =item * clean_path($name)  
   
 Performs clean-up of directories, subdirectories and filename in an  
 embedded object, referenced in an HTML file which is being uploaded  
 to a course or portfolio, where  
 "Upload embedded images/multimedia files if HTML file" checkbox was  
 checked.  
   
 Clean-up is similar to replacements in lonnet::clean_filename()  
 except each / between sub-directory and next level is preserved.  
   
 =cut  
   
 sub clean_path {  
     my ($embed_file) = @_;  
     $embed_file =~s{^/+}{};  
     my @contents;  
     if ($embed_file =~ m{/}) {  
         @contents = split(/\//,$embed_file);  
     } else {  
         @contents = ($embed_file);  
     }  
     my $lastidx = scalar(@contents)-1;  
     for (my $i=0; $i<=$lastidx; $i++) {  
         $contents[$i]=~s{\\}{/}g;  
         $contents[$i]=~s/\s+/\_/g;  
         $contents[$i]=~s{[^/\w\.\-]}{}g;  
         if ($i == $lastidx) {  
             $contents[$i]=~s/\.(\d+)(?=\.)/_$1/g;  
         }  
     }  
     if ($lastidx > 0) {  
         return join('/',@contents);  
     } else {  
         return $contents[0];  
     }  
 }  
   
 sub embedded_file_element {  sub embedded_file_element {
     my ($context,$num,$embed_file,$mapping,$allfiles,$codebase,$type) = @_;      my ($context,$num,$embed_file,$mapping,$allfiles,$codebase,$type) = @_;
     return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&      return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&
Line 10668  sub upload_embedded { Line 10116  sub upload_embedded {
         # Check if extension is valid          # Check if extension is valid
         if (($fname =~ /\.(\w+)$/) &&          if (($fname =~ /\.(\w+)$/) &&
             (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {              (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
             $output .= &mt('Invalid file extension ([_1]) - reserved for internal use.',$1)              $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1).'<br />';
                       .' '.&mt('Rename the file with a different extension and re-upload.').'<br />';  
             next;              next;
         } elsif (($fname =~ /\.(\w+)$/) &&          } elsif (($fname =~ /\.(\w+)$/) &&
                  (!defined(&Apache::loncommon::fileembstyle($1)))) {                   (!defined(&Apache::loncommon::fileembstyle($1)))) {
             $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1).'<br />';              $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1).'<br />';
             next;              next;
         } elsif ($fname=~/\.(\d+)\.(\w+)$/) {          } elsif ($fname=~/\.(\d+)\.(\w+)$/) {
             $output .= &mt('Filename not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).'<br />';              $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).'<br />';
             next;              next;
         }          }
         $env{'form.embedded_item_'.$i.'.filename'}=$fname;          $env{'form.embedded_item_'.$i.'.filename'}=$fname;
         my $subdir = $path;  
         $subdir =~ s{/+$}{};  
         if ($context eq 'portfolio') {          if ($context eq 'portfolio') {
             my $result;              my $result;
             if ($state eq 'existingfile') {              if ($state eq 'existingfile') {
                 $result=                  $result=
                     &Apache::lonnet::userfileupload('embedded_item_'.$i,'existingfile',                      &Apache::lonnet::userfileupload('embedded_item_'.$i,'existingfile',
                                                     $dirpath.$env{'form.currentpath'}.$subdir);                                                      $dirpath.$env{'form.currentpath'}.$path);
             } else {              } else {
                 $result=                  $result=
                     &Apache::lonnet::userfileupload('embedded_item_'.$i,'',                      &Apache::lonnet::userfileupload('embedded_item_'.$i,'',
                                                     $dirpath.                                                      $dirpath.
                                                     $env{'form.currentpath'}.$subdir);                                                      $env{'form.currentpath'}.$path);
                 if ($result !~ m|^/uploaded/|) {                  if ($result !~ m|^/uploaded/|) {
                     $output .= '<span class="LC_error">'                      $output .= '<span class="LC_error">'
                                .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'                                 .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
Line 10704  sub upload_embedded { Line 10149  sub upload_embedded {
                                $path.$fname.'</span>').'<br />';                                      $path.$fname.'</span>').'<br />';     
                 }                  }
             }              }
         } elsif (($context eq 'coursedoc') || ($context eq 'syllabus')) {          } elsif ($context eq 'coursedoc') {
             my $extendedsubdir = $dirpath.'/'.$subdir;  
             $extendedsubdir =~ s{/+$}{};  
             my $result =              my $result =
                 &Apache::lonnet::userfileupload('embedded_item_'.$i,$context,$extendedsubdir);                  &Apache::lonnet::userfileupload('embedded_item_'.$i,'coursedoc',
                                                   $dirpath.'/'.$path);
             if ($result !~ m|^/uploaded/|) {              if ($result !~ m|^/uploaded/|) {
                 $output .= '<span class="LC_error">'                  $output .= '<span class="LC_error">'
                            .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'                             .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
Line 10718  sub upload_embedded { Line 10162  sub upload_embedded {
             } else {              } else {
                 $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.                  $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
                            $path.$fname.'</span>').'<br />';                             $path.$fname.'</span>').'<br />';
                 if ($context eq 'syllabus') {  
                     &Apache::lonnet::make_public_indefinitely($result);  
                 }  
             }              }
         } else {          } else {
 # Save the file  # Save the file
Line 10852  sub modify_html_form { Line 10293  sub modify_html_form {
 }  }
   
 sub modify_html_refs {  sub modify_html_refs {
     my ($context,$dirpath,$uname,$udom,$dir_root,$url) = @_;      my ($context,$dirpath,$uname,$udom,$dir_root) = @_;
     my $container;      my $container;
     if ($context eq 'portfolio') {      if ($context eq 'portfolio') {
         $container = $env{'form.container'};          $container = $env{'form.container'};
Line 10861  sub modify_html_refs { Line 10302  sub modify_html_refs {
     } elsif ($context eq 'manage_dependencies') {      } elsif ($context eq 'manage_dependencies') {
         (undef,undef,$container) = &Apache::lonnet::decode_symb($env{'form.symb'});          (undef,undef,$container) = &Apache::lonnet::decode_symb($env{'form.symb'});
         $container = "/$container";          $container = "/$container";
     } elsif ($context eq 'syllabus') {  
         $container = $url;  
     } else {      } else {
         $container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'};          $container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'};
     }      }
     my (%allfiles,%codebase,$output,$content);      my (%allfiles,%codebase,$output,$content);
     my @changes = &get_env_multiple('form.namechange');      my @changes = &get_env_multiple('form.namechange');
     unless ((@changes > 0)  || ($context eq 'syllabus')) {      unless (@changes > 0) {
         if (wantarray) {          if (wantarray) {
             return ('',0,0);               return ('',0,0); 
         } else {          } else {
Line 10876  sub modify_html_refs { Line 10315  sub modify_html_refs {
         }          }
     }      }
     if (($context eq 'portfolio') || ($context eq 'coursedoc') ||       if (($context eq 'portfolio') || ($context eq 'coursedoc') || 
         ($context eq 'manage_dependencies') || ($context eq 'syllabus')) {          ($context eq 'manage_dependencies')) {
         unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/}) {          unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/}) {
             if (wantarray) {              if (wantarray) {
                 return ('',0,0);                  return ('',0,0);
Line 10932  sub modify_html_refs { Line 10371  sub modify_html_refs {
                     if ($content =~ m{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}) {                      if ($content =~ m{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}) {
                         my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);                          my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);
                         $count += $numchg;                          $count += $numchg;
                         $allfiles{$newname} = $allfiles{$ref};  
                         delete($allfiles{$ref});  
                     }                      }
                     if ($env{'form.embedded_codebase_'.$i} ne '') {                      if ($env{'form.embedded_codebase_'.$i} ne '') {
                         $codebase = &unescape($env{'form.embedded_codebase_'.$i});                          $codebase = &unescape($env{'form.embedded_codebase_'.$i});
Line 10942  sub modify_html_refs { Line 10379  sub modify_html_refs {
                     }                      }
                 }                  }
             }              }
             my $skiprewrites;  
             if ($count || $codebasecount) {              if ($count || $codebasecount) {
                 my $saveresult;                  my $saveresult;
                 if (($context eq 'portfolio') || ($context eq 'coursedoc') ||                   if (($context eq 'portfolio') || ($context eq 'coursedoc') || 
                     ($context eq 'manage_dependencies') || ($context eq 'syllabus')) {                      ($context eq 'manage_dependencies')) {
                     my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);                      my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
                     if ($url eq $container) {                      if ($url eq $container) {
                         my ($fname) = ($container =~ m{/([^/]+)$});                          my ($fname) = ($container =~ m{/([^/]+)$});
Line 10959  sub modify_html_refs { Line 10395  sub modify_html_refs {
                                    '<span class="LC_filename">'.                                     '<span class="LC_filename">'.
                                    $container.'</span>').'</p>';                                     $container.'</span>').'</p>';
                     }                      }
                     if ($context eq 'syllabus') {  
                         unless ($saveresult eq 'ok') {  
                             $skiprewrites = 1;  
                         }  
                     }  
                 } else {                  } else {
                     if (open(my $fh,">$container")) {                      if (open(my $fh,">$container")) {
                         print $fh $content;                          print $fh $content;
Line 10979  sub modify_html_refs { Line 10410  sub modify_html_refs {
                     }                      }
                 }                  }
             }              }
             if (($context eq 'syllabus') && (!$skiprewrites)) {  
                 my ($actionurl,$state);  
                 $actionurl = "/public/$udom/$uname/syllabus";  
                 my ($ignore,$num,$numpathchanges,$existing,$mapping) =  
                     &ask_for_embedded_content($actionurl,$state,\%allfiles,  
                                               \%codebase,  
                                               {'context' => 'rewrites',  
                                                'ignore_remote_references' => 1,});  
                 if (ref($mapping) eq 'HASH') {  
                     my $rewrites = 0;  
                     foreach my $key (keys(%{$mapping})) {  
                         next if ($key =~ m{^https?://});  
                         my $ref = $mapping->{$key};  
                         my $newname = "/uploaded/$udom/$uname/portfolio/syllabus/$key";  
                         my $attrib;  
                         if (ref($allfiles{$mapping->{$key}}) eq 'ARRAY') {  
                             $attrib = join('|',@{$allfiles{$mapping->{$key}}});  
                         }  
                         if ($content =~ m{($attrib\s*=\s*['"]?)\Q$ref\E(['"]?)}) {  
                             my $numchg = ($content =~ s{($attrib\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);  
                             $rewrites += $numchg;  
                         }  
                     }  
                     if ($rewrites) {  
                         my $saveresult;  
                         my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);  
                         if ($url eq $container) {  
                             my ($fname) = ($container =~ m{/([^/]+)$});  
                             $output .= '<p>'.&mt('Rewrote [quant,_1,link] as [quant,_1,absolute link] in [_2].',  
                                             $count,'<span class="LC_filename">'.  
                                             $fname.'</span>').'</p>';  
                         } else {  
                             $output .= '<p class="LC_error">'.  
                                        &mt('Error: could not update links in [_1].',  
                                        '<span class="LC_filename">'.  
                                        $container.'</span>').'</p>';  
   
                         }  
                     }  
                 }  
             }  
         } else {          } else {
             &logthis('Failed to parse '.$container.              &logthis('Failed to parse '.$container.
                      ' to modify references: '.$parse_result);                       ' to modify references: '.$parse_result);
Line 11109  sub check_for_upload { Line 10499  sub check_for_upload {
                     if ($currsize < $filesize) {                      if ($currsize < $filesize) {
                         my $extra = $filesize - $currsize;                          my $extra = $filesize - $currsize;
                         if (($current_disk_usage + $extra) > $disk_quota) {                          if (($current_disk_usage + $extra) > $disk_quota) {
                             my $msg = '<p class="LC_warning">'.                              my $msg = '<span class="LC_error">'.
                                       &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',                                        &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',
                                           '<span class="LC_filename">'.$fname.'</span>',$filesize,$currsize).'</p>'.                                            '<span class="LC_filename">'.$fname.'</span>',$filesize,$currsize).'</span>'.
                                       '<p>'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',                                        '<br />'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
                                                    $disk_quota,$current_disk_usage).'</p>';                                                     $disk_quota,$current_disk_usage);
                             return ('will_exceed_quota',$msg);                              return ('will_exceed_quota',$msg);
                         }                          }
                     }                      }
Line 11122  sub check_for_upload { Line 10512  sub check_for_upload {
         }          }
     }      }
     if (($current_disk_usage + $filesize) > $disk_quota){      if (($current_disk_usage + $filesize) > $disk_quota){
         my $msg = '<p class="LC_warning">'.          my $msg = '<span class="LC_error">'.
                 &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.','<span class="LC_filename">'.$fname.'</span>',$filesize).'</p>'.                  &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.','<span class="LC_filename">'.$fname.'</span>',$filesize).'</span>'.
                   '<p>'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',$disk_quota,$current_disk_usage).'</p>';                    '<br />'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',$disk_quota,$current_disk_usage);
         return ('will_exceed_quota',$msg);          return ('will_exceed_quota',$msg);
     } elsif ($found_file) {      } elsif ($found_file) {
         if ($locked_file) {          if ($locked_file) {
             my $msg = '<p class="LC_warning">';              my $msg = '<span class="LC_error">';
             $msg .= &mt('Unable to upload [_1]. A locked file by that name was found in [_2].','<span class="LC_filename">'.$fname.'</span>','<span class="LC_filename">'.$port_path.$env{'form.currentpath'}.'</span>');              $msg .= &mt('Unable to upload [_1]. A locked file by that name was found in [_2].','<span class="LC_filename">'.$fname.'</span>','<span class="LC_filename">'.$port_path.$env{'form.currentpath'}.'</span>');
             $msg .= '</p>';              $msg .= '</span><br />';
             $msg .= &mt('You will be able to rename or delete existing [_1] after a grade has been assigned.','<span class="LC_filename">'.$fname.'</span>');              $msg .= &mt('You will be able to rename or delete existing [_1] after a grade has been assigned.','<span class="LC_filename">'.$fname.'</span>');
             return ('file_locked',$msg);              return ('file_locked',$msg);
         } else {          } else {
             my $msg = '<p class="LC_error">';              my $msg = '<span class="LC_error">';
             $msg .= &mt(' A file by that name: [_1] was found in [_2].','<span class="LC_filename">'.$fname.'</span>',$port_path.$env{'form.currentpath'});              $msg .= &mt(' A file by that name: [_1] was found in [_2].','<span class="LC_filename">'.$fname.'</span>',$port_path.$env{'form.currentpath'});
             $msg .= '</p>';              $msg .= '</span>';
             return ('existingfile',$msg);              return ('existingfile',$msg);
         }          }
     }      }
Line 11227  sub decompress_form { Line 10617  sub decompress_form {
         }          }
     }      }
     if ($mimetype =~ m{^application/(x\-)?(compressed|zip)}) {      if ($mimetype =~ m{^application/(x\-)?(compressed|zip)}) {
         my @camtasia6 = ("$topdir/","$topdir/index.html",          my @camtasia = ("$topdir/","$topdir/index.html",
                         "$topdir/media/",                          "$topdir/media/",
                         "$topdir/media/$topdir.mp4",                          "$topdir/media/$topdir.mp4",
                         "$topdir/media/FirstFrame.png",                          "$topdir/media/FirstFrame.png",
                         "$topdir/media/player.swf",                          "$topdir/media/player.swf",
                         "$topdir/media/swfobject.js",                          "$topdir/media/swfobject.js",
                         "$topdir/media/expressInstall.swf");                          "$topdir/media/expressInstall.swf");
         my @camtasia8_1 = ("$topdir/","$topdir/$topdir.html",          my @diffs = &compare_arrays(\@paths,\@camtasia);
                          "$topdir/$topdir.mp4",  
                          "$topdir/$topdir\_config.xml",  
                          "$topdir/$topdir\_controller.swf",  
                          "$topdir/$topdir\_embed.css",  
                          "$topdir/$topdir\_First_Frame.png",  
                          "$topdir/$topdir\_player.html",  
                          "$topdir/$topdir\_Thumbnails.png",  
                          "$topdir/playerProductInstall.swf",  
                          "$topdir/scripts/",  
                          "$topdir/scripts/config_xml.js",  
                          "$topdir/scripts/handlebars.js",  
                          "$topdir/scripts/jquery-1.7.1.min.js",  
                          "$topdir/scripts/jquery-ui-1.8.15.custom.min.js",  
                          "$topdir/scripts/modernizr.js",  
                          "$topdir/scripts/player-min.js",  
                          "$topdir/scripts/swfobject.js",  
                          "$topdir/skins/",  
                          "$topdir/skins/configuration_express.xml",  
                          "$topdir/skins/express_show/",  
                          "$topdir/skins/express_show/player-min.css",  
                          "$topdir/skins/express_show/spritesheet.png");  
         my @camtasia8_4 = ("$topdir/","$topdir/$topdir.html",  
                          "$topdir/$topdir.mp4",  
                          "$topdir/$topdir\_config.xml",  
                          "$topdir/$topdir\_controller.swf",  
                          "$topdir/$topdir\_embed.css",  
                          "$topdir/$topdir\_First_Frame.png",  
                          "$topdir/$topdir\_player.html",  
                          "$topdir/$topdir\_Thumbnails.png",  
                          "$topdir/playerProductInstall.swf",  
                          "$topdir/scripts/",  
                          "$topdir/scripts/config_xml.js",  
                          "$topdir/scripts/techsmith-smart-player.min.js",  
                          "$topdir/skins/",  
                          "$topdir/skins/configuration_express.xml",  
                          "$topdir/skins/express_show/",  
                          "$topdir/skins/express_show/spritesheet.min.css",  
                          "$topdir/skins/express_show/spritesheet.png",  
                          "$topdir/skins/express_show/techsmith-smart-player.min.css");  
         my @diffs = &compare_arrays(\@paths,\@camtasia6);  
         if (@diffs == 0) {          if (@diffs == 0) {
             $is_camtasia = 6;              $is_camtasia = 1;
         } else {  
             @diffs = &compare_arrays(\@paths,\@camtasia8_1);  
             if (@diffs == 0) {  
                 $is_camtasia = 8;  
             } else {  
                 @diffs = &compare_arrays(\@paths,\@camtasia8_4);  
                 if (@diffs == 0) {  
                     $is_camtasia = 8;  
                 }  
             }  
         }          }
     }      }
     my $output;      my $output;
Line 11298  sub decompress_form { Line 10638  sub decompress_form {
 function camtasiaToggle() {  function camtasiaToggle() {
     for (var i=0; i<document.uploaded_decompress.autoextract_camtasia.length; i++) {      for (var i=0; i<document.uploaded_decompress.autoextract_camtasia.length; i++) {
         if (document.uploaded_decompress.autoextract_camtasia[i].checked) {          if (document.uploaded_decompress.autoextract_camtasia[i].checked) {
             if (document.uploaded_decompress.autoextract_camtasia[i].value == $is_camtasia) {              if (document.uploaded_decompress.autoextract_camtasia[i].value == 1) {
   
                 document.getElementById('camtasia_titles').style.display='block';                  document.getElementById('camtasia_titles').style.display='block';
             } else {              } else {
                 document.getElementById('camtasia_titles').style.display='none';                  document.getElementById('camtasia_titles').style.display='none';
Line 11360  ENDCAM Line 10701  ENDCAM
     if ($is_camtasia) {      if ($is_camtasia) {
         $output .= $lt{'auto'}.'<br />'.          $output .= $lt{'auto'}.'<br />'.
                    '<span class="LC_nobreak">'.$lt{'proa'}.'<label>'.                     '<span class="LC_nobreak">'.$lt{'proa'}.'<label>'.
                    '<input type="radio" name="autoextract_camtasia" value="'.$is_camtasia.'" onclick="javascript:camtasiaToggle();" checked="checked" />'.                     '<input type="radio" name="autoextract_camtasia" value="1" onclick="javascript:camtasiaToggle();" checked="checked" />'.
                    $lt{'yes'}.'</label>&nbsp;<label>'.                     $lt{'yes'}.'</label>&nbsp;<label>'.
                    '<input type="radio" name="autoextract_camtasia" value="0" onclick="javascript:camtasiaToggle();" />'.                     '<input type="radio" name="autoextract_camtasia" value="0" onclick="javascript:camtasiaToggle();" />'.
                    $lt{'no'}.'</label></span><br />'.                     $lt{'no'}.'</label></span><br />'.
Line 11483  sub decompress_uploaded_file { Line 10824  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) = @_;
     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)$/) {
         $error = &mt('Filename not a supported archive file type.').          $error = &mt('File name not a supported archive file type.').
                  '<br />'.&mt('Filename should end with one of: [_1].',                   '<br />'.&mt('File name should end with one of: [_1].',
                               '.zip, .tar, .bz2, .gz, .tar.gz, .tar.bz2, .tgz');                                '.zip, .tar, .bz2, .gz, .tar.gz, .tar.bz2, .tgz');
     } else {      } else {
         my $docuhome = &Apache::lonnet::homeserver($docuname,$docudom);          my $docuhome = &Apache::lonnet::homeserver($docuname,$docudom);
Line 11593  sub process_decompression { Line 10934  sub process_decompression {
                                                            \%titles,\%children);                                                             \%titles,\%children);
                         }                          }
                         if ($env{'form.autoextract_camtasia'}) {                          if ($env{'form.autoextract_camtasia'}) {
                             my $version = $env{'form.autoextract_camtasia'};  
                             my %displayed;                              my %displayed;
                             my $total = 1;                              my $total = 1;
                             $env{'form.archive_directory'} = [];                              $env{'form.archive_directory'} = [];
Line 11612  sub process_decompression { Line 10952  sub process_decompression {
                                     $env{'form.archive_'.$i} = 'display';                                      $env{'form.archive_'.$i} = 'display';
                                     $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") {
                                          (($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;
                                 } else {                                  } else {
                                     if ((($item eq "$contents[0]/media") && ($version == 6)) ||                                      if ($item eq "$contents[0]/media") {
                                         ((($item eq "$contents[0]/scripts") || ($item eq "$contents[0]/skins") ||  
                                              ($item eq "$contents[0]/skins/express_show")) && ($version == 8))) {  
                                         push(@{$env{'form.archive_directory'}},$i);                                          push(@{$env{'form.archive_directory'}},$i);
                                     }                                      }
                                     $env{'form.archive_'.$i} = 'dependency';                                      $env{'form.archive_'.$i} = 'dependency';
Line 12065  sub process_extracted_files { Line 11402  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 12185  sub process_extracted_files { Line 11522  sub process_extracted_files {
                     }                      }
                 }                  }
             } else {              } else {
                 $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).'<br />';                  $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).'<br />'; 
             }              }
         }          }
         for (my $i=1; $i<=$numitems; $i++) {          for (my $i=1; $i<=$numitems; $i++) {
Line 12207  sub process_extracted_files { Line 11544  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 12254  sub process_extracted_files { Line 11591  sub process_extracted_files {
                                     $showpath = "$relpath/$title";                                      $showpath = "$relpath/$title";
                                 } else {                                  } else {
                                     $showpath = "/$title";                                      $showpath = "/$title";
                                 }                                  } 
                                 $result .= '<li>'.&mt('[_1] included as a dependency',$showpath).'</li>'."\n";                                  $result .= '<li>'.&mt('[_1] included as a dependency',$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;
                             }                              }
                         }                          }
Line 12269  sub process_extracted_files { Line 11606  sub process_extracted_files {
                                     $path,$env{'form.archive_content_'.$referrer{$i}}).'<br />';                                      $path,$env{'form.archive_content_'.$referrer{$i}}).'<br />';
                 }                  }
             } else {              } else {
                 $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).'<br />';                  $warning .= &mt('Item extracted from archive: [_1] has unexpected path.',$path).'<br />'; 
             }              }
         }          }
         if (keys(%todelete)) {          if (keys(%todelete)) {
Line 12347  sub cleanup_empty_dirs { Line 11684  sub cleanup_empty_dirs {
   
 =pod  =pod
   
 =item * &get_folder_hierarchy()  =item &get_folder_hierarchy()
   
 Provides hierarchy of names of folders/sub-folders containing the current  Provides hierarchy of names of folders/sub-folders containing the current
 item,  item,
Line 12375  sub get_folder_hierarchy { Line 11712  sub get_folder_hierarchy {
                 my @pcs = split(/,/,$pcslist);                  my @pcs = split(/,/,$pcslist);
                 foreach my $pc (@pcs) {                  foreach my $pc (@pcs) {
                     if ($pc == 1) {                      if ($pc == 1) {
                         push(@pathitems,&mt('Main Content'));                          push(@pathitems,&mt('Main Course Documents'));
                     } else {                      } else {
                         my $res = $navmap->getByMapPc($pc);                          my $res = $navmap->getByMapPc($pc);
                         if (ref($res)) {                          if (ref($res)) {
Line 12390  sub get_folder_hierarchy { Line 11727  sub get_folder_hierarchy {
             }              }
             if ($showitem) {              if ($showitem) {
                 if ($mapres->{ID} eq '0.0') {                  if ($mapres->{ID} eq '0.0') {
                     push(@pathitems,&mt('Main Content'));                      push(@pathitems,&mt('Main Course Documents'));
                 } else {                  } else {
                     my $maptitle = $mapres->compTitle();                      my $maptitle = $mapres->compTitle();
                     $maptitle =~ s/\W+/_/g;                      $maptitle =~ s/\W+/_/g;
Line 12457  sub get_turnedin_filepath { Line 11794  sub get_turnedin_filepath {
                             my $title = $res->compTitle();                              my $title = $res->compTitle();
                             $title =~ s/\W+/_/g;                              $title =~ s/\W+/_/g;
                             if ($title ne '') {                              if ($title ne '') {
                                 if (($pc > 1) && (length($title) > 12)) {  
                                     $title = substr($title,0,12);  
                                 }  
                                 push(@pathitems,$title);                                  push(@pathitems,$title);
                             }                              }
                         }                          }
Line 12468  sub get_turnedin_filepath { Line 11802  sub get_turnedin_filepath {
                 my $maptitle = $mapres->compTitle();                  my $maptitle = $mapres->compTitle();
                 $maptitle =~ s/\W+/_/g;                  $maptitle =~ s/\W+/_/g;
                 if ($maptitle ne '') {                  if ($maptitle ne '') {
                     if (length($maptitle) > 12) {  
                         $maptitle = substr($maptitle,0,12);  
                     }  
                     push(@pathitems,$maptitle);                      push(@pathitems,$maptitle);
                 }                  }
                 unless ($env{'request.state'} eq 'construct') {                  unless ($env{'request.state'} eq 'construct') {
Line 12511  sub get_turnedin_filepath { Line 11842  sub get_turnedin_filepath {
                 $restitle = time;                  $restitle = time;
             }              }
         }          }
         if (length($restitle) > 12) {  
             $restitle = substr($restitle,0,12);  
         }  
         push(@pathitems,$restitle);          push(@pathitems,$restitle);
         $path .= join('/',@pathitems);          $path .= join('/',@pathitems);
     }      }
Line 13451  sub restore_settings { Line 12779  sub restore_settings {
   
 =item * &build_recipient_list()  =item * &build_recipient_list()
   
 Build recipient lists for following types of e-mail:  Build recipient lists for five types of e-mail:
 (a) Error Reports, (b) Package Updates, (c) lonstatus warnings/errors  (a) Error Reports, (b) Package Updates, (c) lonstatus warnings/errors
 (d) Help requests, (e) Course requests needing approval, (f) loncapa  (d) Help requests, (e) Course requests needing approval,  generated by
 module change checking, student/employee ID conflict checks, as  lonerrorhandler.pm, CHECKRPMS, loncron, lonsupportreq.pm and
 generated by lonerrorhandler.pm, CHECKRPMS, loncron,  loncoursequeueadmin.pm 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, or helpdeskmail), 
 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  
   
 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 13660  sub extract_categories { Line 12984  sub extract_categories {
   
 =pod  =pod
   
 =item * &recurse_categories()  =item *&recurse_categories()
   
 Recursively used to generate breadcrumb trails for course categories.  Recursively used to generate breadcrumb trails for course categories.
   
Line 13731  sub recurse_categories { Line 13055  sub recurse_categories {
   
 =pod  =pod
   
 =item * &assign_categories_table()  =item *&assign_categories_table()
   
 Create a datatable for display of hierarchical categories in a domain,  Create a datatable for display of hierarchical categories in a domain,
 with checkboxes to allow a course to be categorized.   with checkboxes to allow a course to be categorized. 
Line 13808  sub assign_categories_table { Line 13132  sub assign_categories_table {
   
 =pod  =pod
   
 =item * &assign_category_rows()  =item *&assign_category_rows()
   
 Create a datatable row for display of nested categories in a domain,  Create a datatable row for display of nested categories in a domain,
 with checkboxes to allow a course to be categorized,called recursively.  with checkboxes to allow a course to be categorized,called recursively.
Line 13842  sub assign_category_rows { Line 13166  sub assign_category_rows {
             if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {              if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {
                 my $numchildren = @{$cats->[$depth]{$parent}};                  my $numchildren = @{$cats->[$depth]{$parent}};
                 my $css_class = $itemcount%2?' class="LC_odd_row"':'';                  my $css_class = $itemcount%2?' class="LC_odd_row"':'';
                 $text .= '<td><table class="LC_data_table">';                  $text .= '<td><table class="LC_datatable">';
                 for (my $j=0; $j<$numchildren; $j++) {                  for (my $j=0; $j<$numchildren; $j++) {
                     $name = $cats->[$depth]{$parent}[$j];                      $name = $cats->[$depth]{$parent}[$j];
                     $item = &escape($name).':'.&escape($parent).':'.$depth;                      $item = &escape($name).':'.&escape($parent).':'.$depth;
Line 13874  sub assign_category_rows { Line 13198  sub assign_category_rows {
     return $text;      return $text;
 }  }
   
 =pod  
   
 =back  
   
 =cut  
   
 ############################################################  ############################################################
 ############################################################  ############################################################
   
Line 14010  sub commit_studentrole { Line 13328  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 14132  sub check_clone { Line 13450  sub check_clone {
 }  }
   
 sub construct_course {  sub construct_course {
     my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context,$cnum,$category,$coderef) = @_;      my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context,$cnum,$category) = @_;
     my $outcome;      my $outcome;
     my $linefeed =  '<br />'."\n";      my $linefeed =  '<br />'."\n";
     if ($context eq 'auto') {      if ($context eq 'auto') {
Line 14228  sub construct_course { Line 13546  sub construct_course {
                    'pch.users.denied',                     'pch.users.denied',
                    'plc.users.denied',                     'plc.users.denied',
                    'hidefromcat',                     'hidefromcat',
                    'checkforpriv',                     'categories'],
                    'categories',  
                    'internal.uniquecode'],  
                    $$crsudom,$$crsunum);                     $$crsudom,$$crsunum);
         if ($args->{'textbook'}) {  
             $cenv{'internal.textbook'} = $args->{'textbook'};  
         }  
     }      }
   
 #  #
Line 14289  sub construct_course { Line 13602  sub construct_course {
 # do not hide course coordinator from staff listing,   # do not hide course coordinator from staff listing, 
 # even if privileged  # even if privileged
     $cenv{'nothideprivileged'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};      $cenv{'nothideprivileged'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
 # add course coordinator's domain to domains to check for privileged users  
 # if different to course domain  
     if ($$crsudom ne $args->{'ccdomain'}) {  
         $cenv{'checkforpriv'} = $args->{'ccdomain'};  
     }  
 # add crosslistings  # add crosslistings
     if ($args->{'crsxlist'}) {      if ($args->{'crsxlist'}) {
         $cenv{'internal.crosslistings'}='';          $cenv{'internal.crosslistings'}='';
Line 14418  sub construct_course { Line 13726  sub construct_course {
  }   }
     }      }
   
 #  
 #  generate and store uniquecode (available to course requester), if course should have one.  
 #  
     if ($args->{'uniquecode'}) {  
         my ($code,$error) = &make_unique_code($$crsudom,$$crsunum);  
         if ($code) {  
             $cenv{'internal.uniquecode'} = $code;  
             my %crsinfo =  
                 &Apache::lonnet::courseiddump($$crsudom,'.',1,'.','.',$$crsunum,undef,undef,'.');  
             if (ref($crsinfo{$$crsudom.'_'.$$crsunum}) eq 'HASH') {  
                 $crsinfo{$$crsudom.'_'.$$crsunum}{'uniquecode'} = $code;  
                 my $putres = &Apache::lonnet::courseidput($$crsudom,\%crsinfo,$crsuhome,'notime');  
             }  
             if (ref($coderef)) {  
                 $$coderef = $code;  
             }  
         }  
     }  
   
     if ($args->{'disresdis'}) {      if ($args->{'disresdis'}) {
         $cenv{'pch.roles.denied'}='st';          $cenv{'pch.roles.denied'}='st';
     }      }
Line 14505  sub construct_course { Line 13794  sub construct_course {
     return (1,$outcome);      return (1,$outcome);
 }  }
   
 sub make_unique_code {  
     my ($cdom,$cnum) = @_;  
     # get lock on uniquecodes db  
     my $lockhash = {  
                       $cnum."\0".'uniquecodes' => $env{'user.name'}.  
                                                   ':'.$env{'user.domain'},  
                    };  
     my $tries = 0;  
     my $gotlock = &Apache::lonnet::newput_dom('uniquecodes',$lockhash,$cdom);  
     my ($code,$error);  
   
     while (($gotlock ne 'ok') && ($tries<3)) {  
         $tries ++;  
         sleep 1;  
         $gotlock = &Apache::lonnet::newput_dom('uniquecodes',$lockhash,$cdom);  
     }  
     if ($gotlock eq 'ok') {  
         my %currcodes = &Apache::lonnet::dump_dom('uniquecodes',$cdom);  
         my $gotcode;  
         my $attempts = 0;  
         while ((!$gotcode) && ($attempts < 100)) {  
             $code = &generate_code();  
             if (!exists($currcodes{$code})) {  
                 $gotcode = 1;  
                 unless (&Apache::lonnet::newput_dom('uniquecodes',{ $code => $cnum },$cdom) eq 'ok') {  
                     $error = 'nostore';  
                 }  
             }  
             $attempts ++;  
         }  
         my @del_lock = ($cnum."\0".'uniquecodes');  
         my $dellockoutcome = &Apache::lonnet::del_dom('uniquecodes',\@del_lock,$cdom);  
     } else {  
         $error = 'nolock';  
     }  
     return ($code,$error);  
 }  
   
 sub generate_code {  
     my $code;  
     my @letts = qw(B C D G H J K M N P Q R S T V W X Z);  
     for (my $i=0; $i<6; $i++) {  
         my $lettnum = int (rand 2);  
         my $item = '';  
         if ($lettnum) {  
             $item = $letts[int( rand(18) )];  
         } else {  
             $item = 1+int( rand(8) );  
         }  
         $code .= $item;  
     }  
     return $code;  
 }  
   
 ############################################################  ############################################################
 ############################################################  ############################################################
   
Line 14586  sub group_term { Line 13821  sub group_term {
 }  }
   
 sub course_types {  sub course_types {
     my @types = ('official','unofficial','community','textbook');      my @types = ('official','unofficial','community');
     my %typename = (      my %typename = (
                          official   => 'Official course',                           official   => 'Official course',
                          unofficial => 'Unofficial course',                           unofficial => 'Unofficial course',
                          community  => 'Community',                           community  => 'Community',
                          textbook   => 'Textbook course',  
                    );                     );
     return (\@types,\%typename);      return (\@types,\%typename);
 }  }
Line 14652  sub escape_url { Line 13886  sub escape_url {
     my ($url)   = @_;      my ($url)   = @_;
     my @urlslices = split(/\//, $url,-1);      my @urlslices = split(/\//, $url,-1);
     my $lastitem = &escape(pop(@urlslices));      my $lastitem = &escape(pop(@urlslices));
     return &HTML::Entities::encode(join('/',@urlslices),"'").'/'.$lastitem;      return join('/',@urlslices).'/'.$lastitem;
 }  }
   
 sub compare_arrays {  sub compare_arrays {
Line 14710  sub init_user_environment { Line 13944  sub init_user_environment {
  }   }
     }      }
     closedir(DIR);      closedir(DIR);
 # If there is a undeleted lockfile for the user's paste buffer remove it.  
             my $namespace = 'nohist_courseeditor';  
             my $lockingkey = 'paste'."\0".'locked_num';  
             my %lockhash = &Apache::lonnet::get($namespace,[$lockingkey],  
                                                 $domain,$username);  
             if (exists($lockhash{$lockingkey})) {  
                 my $delresult = &Apache::lonnet::del($namespace,[$lockingkey],$domain,$username);  
                 unless ($delresult eq 'ok') {  
                     &Apache::lonnet::logthis("Failed to delete paste buffer locking key in $namespace for ".$username.":".$domain." Result was: $delresult");  
                 }  
             }  
  }   }
 # Give them a new cookie  # Give them a new cookie
  my $id = ($args->{'robot'} ? 'robot'.$args->{'robot'}   my $id = ($args->{'robot'} ? 'robot'.$args->{'robot'}
Line 14734  sub init_user_environment { Line 13957  sub init_user_environment {
     }      }
 # ------------------------------------ Check browser type and MathML capability  # ------------------------------------ Check browser type and MathML capability
   
     my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,$clientunicode,      my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
         $clientos,$clientmobile,$clientinfo,$clientosversion) = &decode_user_agent($r);          $clientunicode,$clientos) = &decode_user_agent($r);
   
 # ------------------------------------------------------------- Get environment  # ------------------------------------------------------------- Get environment
   
Line 14766  sub init_user_environment { Line 13989  sub init_user_environment {
      "browser.mathml"     => $clientmathml,       "browser.mathml"     => $clientmathml,
      "browser.unicode"    => $clientunicode,       "browser.unicode"    => $clientunicode,
      "browser.os"         => $clientos,       "browser.os"         => $clientos,
              "browser.mobile"     => $clientmobile,  
              "browser.info"       => $clientinfo,  
              "browser.osversion"  => $clientosversion,  
      "server.domain"      => $Apache::lonnet::perlvar{'lonDefDomain'},       "server.domain"      => $Apache::lonnet::perlvar{'lonDefDomain'},
      "request.course.fn"  => '',       "request.course.fn"  => '',
      "request.course.uri" => '',       "request.course.uri" => '',
Line 14788  sub init_user_environment { Line 14008  sub init_user_environment {
     $env{'browser.interface'}=$form->{'interface'};      $env{'browser.interface'}=$form->{'interface'};
  }   }
   
         if ($form->{'iptoken'}) {  
             my $lonhost = $r->dir_config('lonHostID');  
             $initial_env{"user.noloadbalance"} = $lonhost;  
             $env{'user.noloadbalance'} = $lonhost;  
         }  
   
         my %is_adv = ( is_adv => $env{'user.adv'} );          my %is_adv = ( is_adv => $env{'user.adv'} );
         my %domdef;          my %domdef;
         unless ($domain eq 'public') {          unless ($domain eq 'public') {
Line 14806  sub init_user_environment { Line 14020  sub init_user_environment {
                                                   undef,\%userenv,\%domdef,\%is_adv);                                                    undef,\%userenv,\%domdef,\%is_adv);
         }          }
   
         foreach my $crstype ('official','unofficial','community','textbook') {          foreach my $crstype ('official','unofficial','community') {
             $userenv{'canrequest.'.$crstype} =              $userenv{'canrequest.'.$crstype} =
                 &Apache::lonnet::usertools_access($username,$domain,$crstype,                  &Apache::lonnet::usertools_access($username,$domain,$crstype,
                                                   'reload','requestcourses',                                                    'reload','requestcourses',
Line 14820  sub init_user_environment { Line 14034  sub init_user_environment {
         my %reqauthor = &Apache::lonnet::get('requestauthor',['author_status','author'],          my %reqauthor = &Apache::lonnet::get('requestauthor',['author_status','author'],
                                              $domain,$username);                                               $domain,$username);
         my $reqstatus = $reqauthor{'author_status'};          my $reqstatus = $reqauthor{'author_status'};
         if ($reqstatus eq 'approval' || $reqstatus eq 'approved') {          if ($reqstatus eq 'approval' || $reqstatus eq 'approved') { 
             if (ref($reqauthor{'author'}) eq 'HASH') {              if (ref($reqauthor{'author'}) eq 'HASH') {
                 $userenv{'requestauthorqueued'} = $reqstatus.':'.                  $userenv{'requestauthorqueued'} = $reqstatus.':'.
                                                   $reqauthor{'author'}{'timestamp'};                                                    $reqauthor{'author'}{'timestamp'};
Line 14911  sub clean_symb { Line 14125  sub clean_symb {
     return ($symb,$enc);      return ($symb,$enc);
 }  }
   
 ############################################################  sub build_release_hashes {
 ############################################################      my ($checkparms,$checkresponsetypes,$checkcrstypes,$anonsurvey,$randomizetry) = @_;
       return unless((ref($checkparms) eq 'HASH') && (ref($checkresponsetypes) eq 'HASH') &&
 =pod                    (ref($checkcrstypes) eq 'HASH') && (ref($anonsurvey) eq 'HASH') &&
                     (ref($randomizetry) eq 'HASH'));
 =head1 Routines for building display used to search for courses      foreach my $key (keys(%Apache::lonnet::needsrelease)) {
           my ($item,$name,$value) = split(/:/,$key);
           if ($item eq 'parameter') {
 =over 4              if (ref($checkparms->{$name}) eq 'ARRAY') {
                   unless(grep(/^\Q$name\E$/,@{$checkparms->{$name}})) {
 =item * &build_filters()                      push(@{$checkparms->{$name}},$value);
                   }
 Create markup for a table used to set filters to use when selecting  
 courses in a domain.  Used by lonpickcourse.pm, lonmodifycourse.pm  
 and quotacheck.pl  
   
   
 Inputs:  
   
 filterlist - anonymous array of fields to include as potential filters  
   
 crstype - course type  
   
 roleelement - fifth arg in selectcourse_link() populates fifth arg in javascript: opencrsbrowser() function, used  
               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  
   
 filter - anonymous hash of criteria and their values  
   
 action - form action  
   
 numfiltersref - ref to scalar (count of number of elements in institutional codes -- e.g., 4 for year, semester, department, and number)  
   
 caller - caller context (e.g., set to 'modifycourse' when routine is called from lonmodifycourse.pm)  
   
 cloneruname - username 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)  
   
 codetitlesref - reference to array of titles of components in institutional codes (official courses)  
   
 codedom - domain  
   
 formname - value of form element named "form".  
   
 fixeddom - domain, if fixed.  
   
 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  
   
 cnumelement - name of form element in form on opener page which will receive courseID  of selected course  
   
 cdomelement - name of form element in form on opener page which will receive domain of selected course  
   
 setroles - includes access constraint identifier when setting a roles-based condition for acces to a portfolio file  
   
 clonetext - hidden form elements containing list of courses cloneable by intended course owner when DC creates a course  
   
 clonewarning - warning message about missing information for intended course owner when DC creates a course  
   
   
 Returns: $output - HTML for display of search criteria, and hidden form elements.  
   
   
 Side Effects: None  
   
 =cut  
   
 # ---------------------------------------------- search for courses based on last activity etc.  
   
 sub build_filters {  
     my ($filterlist,$crstype,$roleelement,$multelement,$filter,$action,  
         $numtitlesref,$caller,$cloneruname,$clonerudom,$typeelement,  
         $codetitlesref,$codedom,$formname,$fixeddom,$prevphase,  
         $cnameelement,$cnumelement,$cdomelement,$setroles,  
         $clonetext,$clonewarning) = @_;  
     my ($list,$jscript);  
     my $onchange = 'javascript:updateFilters(this)';  
     my ($domainselectform,$sincefilterform,$createdfilterform,  
         $ownerdomselectform,$persondomselectform,$instcodeform,  
         $typeselectform,$instcodetitle);  
     if ($formname eq '') {  
         $formname = $caller;  
     }  
     foreach my $item (@{$filterlist}) {  
         unless (($item eq 'descriptfilter') || ($item eq 'instcodefilter') ||  
                 ($item eq 'sincefilter') || ($item eq 'createdfilter')) {  
             if ($item eq 'domainfilter') {  
                 $filter->{$item} = &LONCAPA::clean_domain($filter->{$item});  
             } elsif ($item eq 'coursefilter') {  
                 $filter->{$item} = &LONCAPA::clean_courseid($filter->{$item});  
             } elsif ($item eq 'ownerfilter') {  
                 $filter->{$item} = &LONCAPA::clean_username($filter->{$item});  
             } elsif ($item eq 'ownerdomfilter') {  
                 $filter->{'ownerdomfilter'} =  
                     &LONCAPA::clean_domain($filter->{$item});  
                 $ownerdomselectform = &select_dom_form($filter->{'ownerdomfilter'},  
                                                        'ownerdomfilter',1);  
             } elsif ($item eq 'personfilter') {  
                 $filter->{$item} = &LONCAPA::clean_username($filter->{$item});  
             } elsif ($item eq 'persondomfilter') {  
                 $persondomselectform = &select_dom_form($filter->{'persondomfilter'},  
                                                         'persondomfilter',1);  
             } else {              } else {
                 $filter->{$item} =~ s/\W//g;                  push(@{$checkparms->{$name}},$value);
             }              }
             if (!$filter->{$item}) {          } elsif ($item eq 'resourcetag') {
                 $filter->{$item} = '';              if ($name eq 'responsetype') {
                   $checkresponsetypes->{$value} = $Apache::lonnet::needsrelease{$key}
             }              }
         }          } elsif ($item eq 'course') {
         if ($item eq 'domainfilter') {              if ($name eq 'crstype') {
             my $allow_blank = 1;                  $checkcrstypes->{$value} = $Apache::lonnet::needsrelease{$key};
             if ($formname eq 'portform') {  
                 $allow_blank=0;  
             } elsif ($formname eq 'studentform') {  
                 $allow_blank=0;  
             }              }
             if ($fixeddom) {  
                 $domainselectform = '<input type="hidden" name="domainfilter"'.  
                                     ' value="'.$codedom.'" />'.  
                                     &Apache::lonnet::domain($codedom,'description');  
             } else {  
                 $domainselectform = &select_dom_form($filter->{$item},  
                                                      'domainfilter',  
                                                       $allow_blank,'',$onchange);  
             }  
         } else {  
             $list->{$item} = &HTML::Entities::encode($filter->{$item},'<>&"');  
         }  
     }  
   
     # last course activity filter and selection  
     $sincefilterform = &timebased_select_form('sincefilter',$filter);  
   
     # course created filter and selection  
     if (exists($filter->{'createdfilter'})) {  
         $createdfilterform = &timebased_select_form('createdfilter',$filter);  
     }  
   
     my %lt = &Apache::lonlocal::texthash(  
                 'cac' => "$crstype Activity",  
                 'ccr' => "$crstype Created",  
                 'cde' => "$crstype Title",  
                 'cdo' => "$crstype Domain",  
                 'ins' => 'Institutional Code',  
                 'inc' => 'Institutional Categorization',  
                 'cow' => "$crstype Owner/Co-owner",  
                 'cop' => "$crstype Personnel Includes",  
                 'cog' => 'Type',  
              );  
   
     if (($formname eq 'ccrs') || ($formname eq 'requestcrs')) {  
         my $typeval = 'Course';  
         if ($crstype eq 'Community') {  
             $typeval = 'Community';  
         }  
         $typeselectform = '<input type="hidden" name="type" value="'.$typeval.'" />';  
     } else {  
         $typeselectform =  '<select name="type" size="1"';  
         if ($onchange) {  
             $typeselectform .= ' onchange="'.$onchange.'"';  
         }  
         $typeselectform .= '>'."\n";  
         foreach my $posstype ('Course','Community') {  
             $typeselectform.='<option value="'.$posstype.'"'.  
                 ($posstype eq $crstype ? ' selected="selected" ' : ''). ">".&mt($posstype)."</option>\n";  
         }  
         $typeselectform.="</select>";  
     }  
   
     my ($cloneableonlyform,$cloneabletitle);  
     if (exists($filter->{'cloneableonly'})) {  
         my $cloneableon = '';  
         my $cloneableoff = ' checked="checked"';  
         if ($filter->{'cloneableonly'}) {  
             $cloneableon = $cloneableoff;  
             $cloneableoff = '';  
         }  
         $cloneableonlyform = '<span class="LC_nobreak"><label><input type="radio" name="cloneableonly" value="1" '.$cloneableon.'/>&nbsp;'.&mt('Required').'</label>'.('&nbsp;'x3).'<label><input type="radio" name="cloneableonly" value="" '.$cloneableoff.' />&nbsp;'.&mt('No restriction').'</label></span>';  
         if ($formname eq 'ccrs') {  
             $cloneabletitle = &mt('Cloneable for [_1]',$cloneruname.':'.$clonerudom);  
         } else {  
             $cloneabletitle = &mt('Cloneable by you');  
         }  
     }  
     my $officialjs;  
     if ($crstype eq 'Course') {  
         if (exists($filter->{'instcodefilter'})) {  
 #            if (($fixeddom) || ($formname eq 'requestcrs') ||  
 #                ($formname eq 'modifycourse') || ($formname eq 'filterpicker')) {  
             if ($codedom) {  
                 $officialjs = 1;  
                 ($instcodeform,$jscript,$$numtitlesref) =  
                     &Apache::courseclassifier::instcode_selectors($codedom,'filterpicker',  
                                                                   $officialjs,$codetitlesref);  
                 if ($jscript) {  
                     $jscript = '<script type="text/javascript">'."\n".  
                                '// <![CDATA['."\n".  
                                $jscript."\n".  
                                '// ]]>'."\n".  
                                '</script>'."\n";  
                 }  
             }  
             if ($instcodeform eq '') {  
                 $instcodeform =  
                     '<input type="text" name="instcodefilter" size="10" value="'.  
                     $list->{'instcodefilter'}.'" />';  
                 $instcodetitle = $lt{'ins'};  
             } else {  
                 $instcodetitle = $lt{'inc'};  
             }  
             if ($fixeddom) {  
                 $instcodetitle .= '<br />('.$codedom.')';  
             }  
         }  
     }  
     my $output = qq|  
 <form method="post" name="filterpicker" action="$action">  
 <input type="hidden" name="form" value="$formname" />  
 |;  
     if ($formname eq 'modifycourse') {  
         $output .= '<input type="hidden" name="phase" value="courselist" />'."\n".  
                    '<input type="hidden" name="prevphase" value="'.  
                    $prevphase.'" />'."\n";  
     } elsif ($formname eq 'quotacheck') {  
         $output .= qq|  
 <input type="hidden" name="sortby" value="" />  
 <input type="hidden" name="sortorder" value="" />  
 |;  
     } else {  
         my $name_input;  
         if ($cnameelement ne '') {  
             $name_input = '<input type="hidden" name="cnameelement" value="'.  
                           $cnameelement.'" />';  
         }  
         $output .= qq|  
 <input type="hidden" name="cnumelement" value="$cnumelement" />  
 <input type="hidden" name="cdomelement" value="$cdomelement" />  
 $name_input  
 $roleelement  
 $multelement  
 $typeelement  
 |;  
         if ($formname eq 'portform') {  
             $output .= '<input type="hidden" name="setroles" value="'.$setroles.'" />'."\n";  
         }          }
     }      }
     if ($fixeddom) {      ($anonsurvey->{major},$anonsurvey->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'});
         $output .= '<input type="hidden" name="fixeddom" value="'.$fixeddom.'" />'."\n";      ($randomizetry->{major},$randomizetry->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:randomizetry'});
     }  
     $output .= "<br />\n".&Apache::lonhtmlcommon::start_pick_box();  
     if ($sincefilterform) {  
         $output .= &Apache::lonhtmlcommon::row_title($lt{'cac'})  
                   .$sincefilterform  
                   .&Apache::lonhtmlcommon::row_closure();  
     }  
     if ($createdfilterform) {  
         $output .= &Apache::lonhtmlcommon::row_title($lt{'ccr'})  
                   .$createdfilterform  
                   .&Apache::lonhtmlcommon::row_closure();  
     }  
     if ($domainselectform) {  
         $output .= &Apache::lonhtmlcommon::row_title($lt{'cdo'})  
                   .$domainselectform  
                   .&Apache::lonhtmlcommon::row_closure();  
     }  
     if ($typeselectform) {  
         if (($formname eq 'ccrs') || ($formname eq 'requestcrs')) {  
             $output .= $typeselectform;  
         } else {  
             $output .= &Apache::lonhtmlcommon::row_title($lt{'cog'})  
                       .$typeselectform  
                       .&Apache::lonhtmlcommon::row_closure();  
         }  
     }  
     if ($instcodeform) {  
         $output .= &Apache::lonhtmlcommon::row_title($instcodetitle)  
                   .$instcodeform  
                   .&Apache::lonhtmlcommon::row_closure();  
     }  
     if (exists($filter->{'ownerfilter'})) {  
         $output .= &Apache::lonhtmlcommon::row_title($lt{'cow'}).  
                    '<table><tr><td>'.&mt('Username').'<br />'.  
                    '<input type="text" name="ownerfilter" size="20" value="'.  
                    $list->{'ownerfilter'}.'" /></td><td>'.&mt('Domain').'<br />'.  
                    $ownerdomselectform.'</td></tr></table>'.  
                    &Apache::lonhtmlcommon::row_closure();  
     }  
     if (exists($filter->{'personfilter'})) {  
         $output .= &Apache::lonhtmlcommon::row_title($lt{'cop'}).  
                    '<table><tr><td>'.&mt('Username').'<br />'.  
                    '<input type="text" name="personfilter" size="20" value="'.  
                    $list->{'personfilter'}.'" /></td><td>'.&mt('Domain').'<br />'.  
                    $persondomselectform.'</td></tr></table>'.  
                    &Apache::lonhtmlcommon::row_closure();  
     }  
     if (exists($filter->{'coursefilter'})) {  
         $output .= &Apache::lonhtmlcommon::row_title(&mt('LON-CAPA course ID'))  
                   .'<input type="text" name="coursefilter" size="25" value="'  
                   .$list->{'coursefilter'}.'" />'  
                   .&Apache::lonhtmlcommon::row_closure();  
     }  
     if ($cloneableonlyform) {  
         $output .= &Apache::lonhtmlcommon::row_title($cloneabletitle).  
                    $cloneableonlyform.&Apache::lonhtmlcommon::row_closure();  
     }  
     if (exists($filter->{'descriptfilter'})) {  
         $output .= &Apache::lonhtmlcommon::row_title($lt{'cde'})  
                   .'<input type="text" name="descriptfilter" size="40" value="'  
                   .$list->{'descriptfilter'}.'" />'  
                   .&Apache::lonhtmlcommon::row_closure(1);  
     }  
     $output .= &Apache::lonhtmlcommon::end_pick_box().'<p>'.$clonetext."\n".  
                '<input type="hidden" name="updater" value="" />'."\n".  
                '<input type="submit" name="gosearch" value="'.  
                &mt('Search').'" /></p>'."\n".'</form>'."\n".'<hr />'."\n";  
     return $jscript.$clonewarning.$output;  
 }  
   
 =pod  
   
 =item * &timebased_select_form()  
   
 Create markup for a dropdown list used to select a time-based  
 filter e.g., Course Activity, Course Created, when searching for courses  
 or communities  
   
 Inputs:  
   
 item - name of form element (sincefilter or createdfilter)  
   
 filter - anonymous hash of criteria and their values  
   
 Returns: HTML for a select box contained a blank, then six time selections,  
          with value set in incoming form variables currently selected.  
   
 Side Effects: None  
   
 =cut  
   
 sub timebased_select_form {  
     my ($item,$filter) = @_;  
     if (ref($filter) eq 'HASH') {  
         $filter->{$item} =~ s/[^\d-]//g;  
         if (!$filter->{$item}) { $filter->{$item}=-1; }  
         return &select_form(  
                             $filter->{$item},  
                             $item,  
                             {      '-1' => '',  
                                 '86400' => &mt('today'),  
                                '604800' => &mt('last week'),  
                               '2592000' => &mt('last month'),  
                               '7776000' => &mt('last three months'),  
                              '15552000' => &mt('last six months'),  
                              '31104000' => &mt('last year'),  
                     'select_form_order' =>  
                            ['-1','86400','604800','2592000','7776000',  
                             '15552000','31104000']});  
     }  
 }  
   
 =pod  
   
 =item * &js_changer()  
   
 Create script tag containing Javascript used to submit course search form  
 when course type or domain is changed, and also to hide 'Searching ...' on  
 page load completion for page showing search result.  
   
 Inputs: None  
   
 Returns: markup containing updateFilters() and hideSearching() javascript functions.  
   
 Side Effects: None  
   
 =cut  
   
 sub js_changer {  
     return <<ENDJS;  
 <script type="text/javascript">  
 // <![CDATA[  
 function updateFilters(caller) {  
     if (typeof(caller) != "undefined") {  
         document.filterpicker.updater.value = caller.name;  
     }  
     document.filterpicker.submit();  
 }  
   
 function hideSearching() {  
     if (document.getElementById('searching')) {  
         document.getElementById('searching').style.display = 'none';  
     }  
     return;      return;
 }  }
   
 // ]]>  
 </script>  
   
 ENDJS  
 }  
   
 =pod  
   
 =item * &search_courses()  
   
 Process selected filters form course search form and pass to lonnet::courseiddump  
 to retrieve a hash for which keys are courseIDs which match the selected filters.  
   
 Inputs:  
   
 dom - domain being searched  
   
 type - course type ('Course' or 'Community' or '.' if any).  
   
 filter - anonymous hash of criteria and their values  
   
 numtitles - for institutional codes - number of categories  
   
 cloneruname - optional username 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,  
             (used when DC is using course creation form)  
   
 codetitles - reference to array of titles of components in institutional codes (official courses).  
   
   
 Returns: %courses - hash of courses satisfying search criteria, keys = course IDs, values are corresponding colon-separated escaped description, institutional code, owner and type.  
   
   
 Side Effects: None  
   
 =cut  
   
   
 sub search_courses {  
     my ($dom,$type,$filter,$numtitles,$cloneruname,$clonerudom,$domcloner,$codetitles) = @_;  
     my (%courses,%showcourses,$cloner);  
     if (($filter->{'ownerfilter'} ne '') ||  
         ($filter->{'ownerdomfilter'} ne '')) {  
         $filter->{'combownerfilter'} = $filter->{'ownerfilter'}.':'.  
                                        $filter->{'ownerdomfilter'};  
     }  
     foreach my $item ('descriptfilter','coursefilter','combownerfilter') {  
         if (!$filter->{$item}) {  
             $filter->{$item}='.';  
         }  
     }  
     my $now = time;  
     my $timefilter =  
        ($filter->{'sincefilter'}==-1?1:$now-$filter->{'sincefilter'});  
     my ($createdbefore,$createdafter);  
     if (($filter->{'createdfilter'} ne '') && ($filter->{'createdfilter'} !=-1)) {  
         $createdbefore = $now;  
         $createdafter = $now-$filter->{'createdfilter'};  
     }  
     my ($instcodefilter,$regexpok);  
     if ($numtitles) {  
         if ($env{'form.official'} eq 'on') {  
             $instcodefilter =  
                 &Apache::courseclassifier::instcode_search_str($dom,$numtitles,$codetitles);  
             $regexpok = 1;  
         } elsif ($env{'form.official'} eq 'off') {  
             $instcodefilter = &Apache::courseclassifier::instcode_search_str($dom,$numtitles,$codetitles);  
             unless ($instcodefilter eq '') {  
                 $regexpok = -1;  
             }  
         }  
     } else {  
         $instcodefilter = $filter->{'instcodefilter'};  
     }  
     if ($instcodefilter eq '') { $instcodefilter = '.'; }  
     if ($type eq '') { $type = '.'; }  
   
     if (($clonerudom ne '') && ($cloneruname ne '')) {  
         $cloner = $cloneruname.':'.$clonerudom;  
     }  
     %courses = &Apache::lonnet::courseiddump($dom,  
                                              $filter->{'descriptfilter'},  
                                              $timefilter,  
                                              $instcodefilter,  
                                              $filter->{'combownerfilter'},  
                                              $filter->{'coursefilter'},  
                                              undef,undef,$type,$regexpok,undef,undef,  
                                              undef,undef,$cloner,$env{'form.cc_clone'},  
                                              $filter->{'cloneableonly'},  
                                              $createdbefore,$createdafter,undef,  
                                              $domcloner);  
     if (($filter->{'personfilter'} ne '') && ($filter->{'persondomfilter'} ne '')) {  
         my $ccrole;  
         if ($type eq 'Community') {  
             $ccrole = 'co';  
         } else {  
             $ccrole = 'cc';  
         }  
         my %rolehash = &Apache::lonnet::get_my_roles($filter->{'personfilter'},  
                                                      $filter->{'persondomfilter'},  
                                                      'userroles',undef,  
                                                      [$ccrole,'in','ad','ep','ta','cr'],  
                                                      $dom);  
         foreach my $role (keys(%rolehash)) {  
             my ($cnum,$cdom,$courserole) = split(':',$role);  
             my $cid = $cdom.'_'.$cnum;  
             if (exists($courses{$cid})) {  
                 if (ref($courses{$cid}) eq 'HASH') {  
                     if (ref($courses{$cid}{roles}) eq 'ARRAY') {  
                         if (!grep(/^\Q$courserole\E$/,@{$courses{$cid}{roles}})) {  
                             push (@{$courses{$cid}{roles}},$courserole);  
                         }  
                     } else {  
                         $courses{$cid}{roles} = [$courserole];  
                     }  
                     $showcourses{$cid} = $courses{$cid};  
                 }  
             }  
         }  
         %courses = %showcourses;  
     }  
     return %courses;  
 }  
   
 =pod  
   
 =back  
   
 =head1 Routines for version requirements for current course.  
   
 =over 4  
   
 =item * &check_release_required()  
   
 Compares required LON-CAPA version with version on server, and  
 if required version is newer looks for a server with the required version.  
   
 Looks first at servers in user's owen domain; if none suitable, looks at  
 servers in course's domain are permitted to host sessions for user's domain.  
   
 Inputs:  
   
 $loncaparev - Version on current server (format: Major.Minor.Subrelease-datestamp)  
   
 $courseid - Course ID of current course  
   
 $rolecode - User's current role in course (for switchserver query string).  
   
 $required - LON-CAPA version needed by course (format: Major.Minor).  
   
   
 Returns:  
   
 $switchserver - query string tp append to /adm/switchserver call (if  
                 current server's LON-CAPA version is too old.  
   
 $warning - Message is displayed if no suitable server could be found.  
   
 =cut  
   
 sub check_release_required {  
     my ($loncaparev,$courseid,$rolecode,$required) = @_;  
     my ($switchserver,$warning);  
     if ($required ne '') {  
         my ($reqdmajor,$reqdminor) = ($required =~ /^(\d+)\.(\d+)$/);  
         my ($major,$minor) = ($loncaparev =~ /^\'?(\d+)\.(\d+)\.[\w.\-]+\'?$/);  
         if ($reqdmajor ne '' && $reqdminor ne '') {  
             my $otherserver;  
             if (($major eq '' && $minor eq '') ||  
                 (($reqdmajor > $major) || (($reqdmajor == $major) && ($reqdminor > $minor)))) {  
                 my ($userdomserver) = &Apache::lonnet::choose_server($env{'user.domain'},undef,$required,1);  
                 my $switchlcrev =  
                     &Apache::lonnet::get_server_loncaparev($env{'user.domain'},  
                                                            $userdomserver);  
                 my ($swmajor,$swminor) = ($switchlcrev =~ /^\'?(\d+)\.(\d+)\.[\w.\-]+\'?$/);  
                 if (($swmajor eq '' && $swminor eq '') || ($reqdmajor > $swmajor) ||  
                     (($reqdmajor == $swmajor) && ($reqdminor > $swminor))) {  
                     my $cdom = $env{'course.'.$courseid.'.domain'};  
                     if ($cdom ne $env{'user.domain'}) {  
                         my ($coursedomserver,$coursehostname) = &Apache::lonnet::choose_server($cdom,undef,$required,1);  
                         my $serverhomeID = &Apache::lonnet::get_server_homeID($coursehostname);  
                         my $serverhomedom = &Apache::lonnet::host_domain($serverhomeID);  
                         my %defdomdefaults = &Apache::lonnet::get_domain_defaults($serverhomedom);  
                         my %udomdefaults = &Apache::lonnet::get_domain_defaults($env{'user.domain'});  
                         my $remoterev = &Apache::lonnet::get_server_loncaparev($serverhomedom,$coursedomserver);  
                         my $canhost =  
                             &Apache::lonnet::can_host_session($env{'user.domain'},  
                                                               $coursedomserver,  
                                                               $remoterev,  
                                                               $udomdefaults{'remotesessions'},  
                                                               $defdomdefaults{'hostedsessions'});  
   
                         if ($canhost) {  
                             $otherserver = $coursedomserver;  
                         } else {  
                             $warning = &mt('Requires LON-CAPA version [_1].',$env{'course.'.$courseid.'.internal.releaserequired'}).'<br />'. &mt("No suitable server could be found amongst servers in either your own domain or in the course's domain.");  
                         }  
                     } else {  
                         $warning = &mt('Requires LON-CAPA version [_1].',$env{'course.'.$courseid.'.internal.releaserequired'}).'<br />'.&mt("No suitable server could be found amongst servers in your own domain (which is also the course's domain).");  
                     }  
                 } else {  
                     $otherserver = $userdomserver;  
                 }  
             }  
             if ($otherserver ne '') {  
                 $switchserver = 'otherserver='.$otherserver.'&amp;role='.$rolecode;  
             }  
         }  
     }  
     return ($switchserver,$warning);  
 }  
   
 =pod  
   
 =item * &check_release_result()  
   
 Inputs:  
   
 $switchwarning - Warning message if no suitable server found to host session.  
   
 $switchserver - query string to append to /adm/switchserver containing lonHostID  
                 and current role.  
   
 Returns: HTML to display with information about requirement to switch server.  
          Either displaying warning with link to Roles/Courses screen or  
          display link to switchserver.  
   
 =cut  
   
 sub check_release_result {  
     my ($switchwarning,$switchserver) = @_;  
     my $output = &start_page('Selected course unavailable on this server').  
                  '<p class="LC_warning">';  
     if ($switchwarning) {  
         $output .= $switchwarning.'<br /><a href="/adm/roles">';  
         if (&show_course()) {  
             $output .= &mt('Display courses');  
         } else {  
             $output .= &mt('Display roles');  
         }  
         $output .= '</a>';  
     } elsif ($switchserver) {  
         $output .= &mt('This course requires a newer version of LON-CAPA than is installed on this server.').  
                    '<br />'.  
                    '<a href="/adm/switchserver?'.$switchserver.'">'.  
                    &mt('Switch Server').  
                    '</a>';  
     }  
     $output .= '</p>'.&end_page();  
     return $output;  
 }  
   
 =pod  
   
 =item * &needs_coursereinit()  
   
 Determine if course contents stored for user's session needs to be  
 refreshed, because content has changed since "Big Hash" last tied.  
   
 Check for change is made if time last checked is more than 10 minutes ago  
 (by default).  
   
 Inputs:  
   
 $loncaparev - Version on current server (format: Major.Minor.Subrelease-datestamp)  
   
 $interval (optional) - Time which may elapse (in s) between last check for content  
                        change in current course. (default: 600 s).  
   
 Returns: an array; first element is:  
   
 =over 4  
   
 'switch' - if content updates mean user's session  
            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)  
            on current server hosting user's session  
   
 ''       - if no action required.  
   
 =back  
   
 If first item element is 'switch':  
   
 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  
                               and current role.  
   
 otherwise: no other elements returned.  
   
 =back  
   
 =cut  
   
 sub needs_coursereinit {  
     my ($loncaparev,$interval) = @_;  
     return() unless ($env{'request.course.id'} && $env{'request.course.tied'});  
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};  
     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};  
     my $now = time;  
     if ($interval eq '') {  
         $interval = 600;  
     }  
     if (($now-$env{'request.course.timechecked'})>$interval) {  
         my $lastchange = &Apache::lonnet::get_coursechange($cdom,$cnum);  
         &Apache::lonnet::appenv({'request.course.timechecked'=>$now});  
         if ($lastchange > $env{'request.course.tied'}) {  
             my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');  
             if ($curr_reqd_hash{'internal.releaserequired'} ne '') {  
                 my $required = $env{'course.'.$cdom.'_'.$cnum.'.internal.releaserequired'};  
                 if ($curr_reqd_hash{'internal.releaserequired'} ne $required) {  
                     &Apache::lonnet::appenv({'course.'.$cdom.'_'.$cnum.'.internal.releaserequired' =>  
                                              $curr_reqd_hash{'internal.releaserequired'}});  
                     my ($switchserver,$switchwarning) =  
                         &check_release_required($loncaparev,$cdom.'_'.$cnum,$env{'request.role'},  
                                                 $curr_reqd_hash{'internal.releaserequired'});  
                     if ($switchwarning ne '' || $switchserver ne '') {  
                         return ('switch',$switchwarning,$switchserver);  
                     }  
                 }  
             }  
             return ('update');  
         }  
     }  
     return ();  
 }  
   
 sub update_content_constraints {  sub update_content_constraints {
     my ($cdom,$cnum,$chome,$cid) = @_;      my ($cdom,$cnum,$chome,$cid) = @_;
     my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');      my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');
Line 15728  sub parse_supplemental_title { Line 14241  sub parse_supplemental_title {
     return $title;      return $title;
 }  }
   
 sub recurse_supplemental {  
     my ($cnum,$cdom,$suppmap,$numfiles,$errors) = @_;  
     if ($suppmap) {  
         my ($errtext,$fatal) = &LONCAPA::map::mapread('/uploaded/'.$cdom.'/'.$cnum.'/'.$suppmap);  
         if ($fatal) {  
             $errors ++;  
         } else {  
             if ($#LONCAPA::map::resources > 0) {  
                 foreach my $res (@LONCAPA::map::resources) {  
                     my ($title,$src,$ext,$type,$status)=split(/\:/,$res);  
                     if (($src ne '') && ($status eq 'res')) {  
                         if ($src =~ m{^\Q/uploaded/$cdom/$cnum/\E(supplemental_\d+\.sequence)$}) {  
                             ($numfiles,$errors) = &recurse_supplemental($cnum,$cdom,$1,$numfiles,$errors);  
                         } else {  
                             $numfiles ++;  
                         }  
                     }  
                 }  
             }  
         }  
     }  
     return ($numfiles,$errors);  
 }  
   
 sub symb_to_docspath {  sub symb_to_docspath {
     my ($symb) = @_;      my ($symb) = @_;
     return unless ($symb);      return unless ($symb);
Line 15781  sub symb_to_docspath { Line 14270  sub symb_to_docspath {
                     my $thistitle = $res->title();                      my $thistitle = $res->title();
                     $path .= '&'.                      $path .= '&'.
                              &Apache::lonhtmlcommon::entity_encode($thisurl).'&'.                               &Apache::lonhtmlcommon::entity_encode($thisurl).'&'.
                              &escape($thistitle).                               &Apache::lonhtmlcommon::entity_encode($thistitle).
                              ':'.$res->randompick().                               ':'.$res->randompick().
                              ':'.$res->randomout().                               ':'.$res->randomout().
                              ':'.$res->encrypted().                               ':'.$res->encrypted().
Line 15793  sub symb_to_docspath { Line 14282  sub symb_to_docspath {
         $path =~ s/^\&//;          $path =~ s/^\&//;
         my $maptitle = $mapresobj->title();          my $maptitle = $mapresobj->title();
         if ($mapurl eq 'default') {          if ($mapurl eq 'default') {
             $maptitle = 'Main Content';              $maptitle = 'Main Course Documents';
         }          }
         $path .= (($path ne '')? '&' : '').          $path .= (($path ne '')? '&' : '').
                  &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.                   &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.
                  &escape($maptitle).                   &Apache::lonhtmlcommon::entity_encode($maptitle).
                  ':'.$mapresobj->randompick().                   ':'.$mapresobj->randompick().
                  ':'.$mapresobj->randomout().                   ':'.$mapresobj->randomout().
                  ':'.$mapresobj->encrypted().                   ':'.$mapresobj->encrypted().
Line 15807  sub symb_to_docspath { Line 14296  sub symb_to_docspath {
         my $maptitle = &Apache::lonnet::gettitle($mapurl);          my $maptitle = &Apache::lonnet::gettitle($mapurl);
         my $ispage = (($type eq 'page')? 1 : '');          my $ispage = (($type eq 'page')? 1 : '');
         if ($mapurl eq 'default') {          if ($mapurl eq 'default') {
             $maptitle = 'Main Content';              $maptitle = 'Main Course Documents';
         }          }
         $path = &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.          $path = &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.
                 &escape($maptitle).':::::'.$ispage;                  &Apache::lonhtmlcommon::entity_encode($maptitle).':::::'.$ispage;
     }      }
     unless ($mapurl eq 'default') {      unless ($mapurl eq 'default') {
         $path = 'default&'.          $path = 'default&'.
                 &escape('Main Content').                  &Apache::lonhtmlcommon::entity_encode('Main Course Documents').
                 ':::::&'.$path;                  ':::::&'.$path;
     }      }
     return $path;      return $path;
Line 15827  sub captcha_display { Line 14316  sub captcha_display {
     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);          $output = &create_recaptcha($pubkey);
         unless ($output) {          unless ($output) {
             $error = 'recaptcha';              $error = 'recaptcha'; 
         }          }
     }      }
     return ($output,$error,$captcha);      return ($output,$error);
 }  }
   
 sub captcha_response {  sub captcha_response {
Line 15911  sub create_captcha { Line 14400  sub create_captcha {
         if (-e $Apache::lonnet::perlvar{'lonCaptchaDir'}.'/'.$md5sum.'.png') {          if (-e $Apache::lonnet::perlvar{'lonCaptchaDir'}.'/'.$md5sum.'.png') {
             $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n".              $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n".
                       &mt('Type in the letters/numbers shown below').'&nbsp;'.                        &mt('Type in the letters/numbers shown below').'&nbsp;'.
                       '<input type="text" size="5" name="code" value="" autocomplete="off" />'.                       '<input type="text" size="5" name="code" value="" /><br />'.
                       '<br />'.                       '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" />';
                       '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" alt="captcha" />';  
             last;              last;
         }          }
     }      }
Line 15954  sub check_captcha { Line 14442  sub check_captcha {
   
 sub create_recaptcha {  sub create_recaptcha {
     my ($pubkey) = @_;      my ($pubkey) = @_;
     my $use_ssl;  
     if ($ENV{'SERVER_PORT'} == 443) {  
         $use_ssl = 1;  
     }  
     my $captcha = Captcha::reCAPTCHA->new;      my $captcha = Captcha::reCAPTCHA->new;
     return $captcha->get_options_setter({theme => 'white'})."\n".      return $captcha->get_options_setter({theme => 'white'})."\n".
            $captcha->get_html($pubkey,undef,$use_ssl).             $captcha->get_html($pubkey).
            &mt('If the text is hard to read, [_1] will replace them.',             &mt('If either word is hard to read, [_1] will replace them.',
                '<img src="/res/adm/pages/refresh.gif" alt="reCAPTCHA refresh" />').                 '<image src="/res/adm/pages/refresh.gif" alt="reCAPTCHA refresh" />').
            '<br /><br />';             '<br /><br />';
 }  }
   
Line 15983  sub check_recaptcha { Line 14467  sub check_recaptcha {
     return $captcha_chk;      return $captcha_chk;
 }  }
   
 sub emailusername_info {  =pod
     my @fields = ('firstname','lastname','institution','web','location','officialemail');  
     my %titles = &Apache::lonlocal::texthash (  
                      lastname      => 'Last Name',  
                      firstname     => 'First Name',  
                      institution   => 'School/college/university',  
                      location      => "School's city, state/province, country",  
                      web           => "School's web address",  
                      officialemail => 'E-mail address at institution (if different)',  
                  );  
     return (\@fields,\%titles);  
 }  
   
 sub cleanup_html {  =back
     my ($incoming) = @_;  
     my $outgoing;  
     if ($incoming ne '') {  
         $outgoing = $incoming;  
         $outgoing =~ s/;/&#059;/g;  
         $outgoing =~ s/\#/&#035;/g;  
         $outgoing =~ s/\&/&#038;/g;  
         $outgoing =~ s/</&#060;/g;  
         $outgoing =~ s/>/&#062;/g;  
         $outgoing =~ s/\(/&#040/g;  
         $outgoing =~ s/\)/&#041;/g;  
         $outgoing =~ s/"/&#034;/g;  
         $outgoing =~ s/'/&#039;/g;  
         $outgoing =~ s/\$/&#036;/g;  
         $outgoing =~ s{/}{&#047;}g;  
         $outgoing =~ s/=/&#061;/g;  
         $outgoing =~ s/\\/&#092;/g  
     }  
     return $outgoing;  
 }  
   
 # Checks for critical messages and returns a redirect url if one exists.  
 # $interval indicates how often to check for messages.  
 sub critical_redirect {  
     my ($interval) = @_;  
     if ((time-$env{'user.criticalcheck.time'})>$interval) {  
         my @what=&Apache::lonnet::dump('critical', $env{'user.domain'},  
                                         $env{'user.name'});  
         &Apache::lonnet::appenv({'user.criticalcheck.time'=>time});  
         my $redirecturl;  
         if ($what[0]) {  
             if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) {  
                 $redirecturl='/adm/email?critical=display';  
                 my $url=&Apache::lonnet::absolute_url().$redirecturl;  
                 return (1, $url);  
             }  
         }  
     }  
     return ();  
 }  
   
 # Use:  =cut
 #   my $answer=reply("encrypt:passwd:$udom:$uname:$upass",$tryserver);  
 #  
 ##################################################  
 #          password associated functions         #  
 ##################################################  
 sub des_keys {  
     # Make a new key for DES encryption.  
     # Each key has two parts which are returned separately.  
     # Please note:  Each key must be passed through the &hex function  
     # before it is output to the web browser.  The hex versions cannot  
     # be used to decrypt.  
     my @hexstr=('0','1','2','3','4','5','6','7',  
                 '8','9','a','b','c','d','e','f');  
     my $lkey='';  
     for (0..7) {  
         $lkey.=$hexstr[rand(15)];  
     }  
     my $ukey='';  
     for (0..7) {  
         $ukey.=$hexstr[rand(15)];  
     }  
     return ($lkey,$ukey);  
 }  
   
 sub des_decrypt {  
     my ($key,$cyphertext) = @_;  
     my $keybin=pack("H16",$key);  
     my $cypher;  
     if ($Crypt::DES::VERSION>=2.03) {  
         $cypher=new Crypt::DES $keybin;  
     } else {  
         $cypher=new DES $keybin;  
     }  
     my $plaintext=  
         $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,0,16))));  
     $plaintext.=  
         $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,16,16))));  
     $plaintext=substr($plaintext,1,ord(substr($plaintext,0,1)) );  
     return $plaintext;  
 }  
   
 1;  1;
 __END__;  __END__;

Removed from v.1.1075.2.92  
changed lines
  Added in v.1.1118


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