Diff for /loncom/interface/loncommon.pm between versions 1.1075.2.65 and 1.1096

version 1.1075.2.65, 2014/02/17 17:14:30 version 1.1096, 2012/11/08 20:46:42
Line 67  use Apache::lonhtmlcommon(); Line 67  use Apache::lonhtmlcommon();
 use Apache::loncoursedata();  use Apache::loncoursedata();
 use Apache::lontexconvert();  use Apache::lontexconvert();
 use Apache::lonclonecourse();  use Apache::lonclonecourse();
 use Apache::lonuserutils();  
 use Apache::lonuserstate();  
 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 160  sub ssi_with_retries { Line 157  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 194  BEGIN { Line 192  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 530  ENDAUTHORBRW Line 529  ENDAUTHORBRW
 }  }
   
 sub coursebrowser_javascript {  sub coursebrowser_javascript {
     my ($domainfilter,$sec_element,$formname,$role_element,$crstype,      my ($domainfilter,$sec_element,$formname,$role_element,$crstype) = @_;
         $credits_element) = @_;  
     my $wintitle = 'Course_Browser';      my $wintitle = 'Course_Browser';
     if ($crstype eq 'Community') {      if ($crstype eq 'Community') {
         $wintitle = 'Community_Browser';          $wintitle = 'Community_Browser';
Line 594  sub coursebrowser_javascript { Line 592  sub coursebrowser_javascript {
     }      }
 $id_functions  $id_functions
 ENDSTDBRW  ENDSTDBRW
     if (($sec_element ne '') || ($role_element ne '') || ($credits_element ne '')) {      if (($sec_element ne '') || ($role_element ne '')) {
         $output .= &setsec_javascript($sec_element,$formname,$role_element,          $output .= &setsec_javascript($sec_element,$formname,$role_element);
                                       $credits_element);  
     }      }
     $output .= '      $output .= '
 // ]]>  // ]]>
Line 665  if (!Array.prototype.indexOf) { Line 662  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 753  ENDUSERBRW Line 750  ENDUSERBRW
 }  }
   
 sub setsec_javascript {  sub setsec_javascript {
     my ($sec_element,$formname,$role_element,$credits_element) = @_;      my ($sec_element,$formname,$role_element) = @_;
     my (@courserolenames,@communityrolenames,$rolestr,$courserolestr,      my (@courserolenames,@communityrolenames,$rolestr,$courserolestr,
         $communityrolestr);          $communityrolestr);
     if ($role_element ne '') {      if ($role_element ne '') {
Line 848  function setRole(crstype) { Line 845  function setRole(crstype) {
 }  }
 |;  |;
     }      }
     if ($credits_element) {  
         $setsections .= qq|  
 function setCredits(defaultcredits) {  
     document.$formname.$credits_element.value = defaultcredits;  
     return;  
 }  
 |;  
     }  
     return $setsections;      return $setsections;
 }  }
   
Line 901  sub check_uncheck_jscript { Line 890  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 1010  sub select_language { Line 999  sub select_language {
             $langchoices{$code} = &plainlanguagedescription($id);              $langchoices{$code} = &plainlanguagedescription($id);
         }          }
     }      }
     %langchoices = &Apache::lonlocal::texthash(%langchoices);  
     return &select_form($selected,$name,\%langchoices);      return &select_form($selected,$name,\%langchoices);
 }  }
   
 =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 1042  linked_select_forms takes the following Line 1057  linked_select_forms takes the following
   
 =item * $menuorder, the order of values in the first menu  =item * $menuorder, the order of values in the first menu
   
 =item * $onchangefirst, additional javascript call to execute for an onchange  
         event for the first <select> tag  
   
 =item * $onchangesecond, additional javascript call to execute for an onchange  
         event for the second <select> tag  
   
 =back   =back 
   
 Below is an example of such a hash.  Only the 'text', 'default', and   Below is an example of such a hash.  Only the 'text', 'default', and 
Line 1101  sub linked_select_forms { Line 1110  sub linked_select_forms {
         $secondselectname,           $secondselectname, 
         $hashref,          $hashref,
         $menuorder,          $menuorder,
         $onchangefirst,  
         $onchangesecond  
         ) = @_;          ) = @_;
     my $second = "document.$formname.$secondselectname";      my $second = "document.$formname.$secondselectname";
     my $first = "document.$formname.$firstselectname";      my $first = "document.$formname.$firstselectname";
Line 1159  function select1_changed() { Line 1166  function select1_changed() {
 </script>  </script>
 END  END
     # output the initial values for the selection lists      # output the initial values for the selection lists
     $result .= "<select size=\"1\" name=\"$firstselectname\" onchange=\"select1_changed();$onchangefirst\">\n";      $result .= "<select size=\"1\" name=\"$firstselectname\" onchange=\"select1_changed()\">\n";
     my @order = sort(keys(%{$hashref}));      my @order = sort(keys(%{$hashref}));
     if (ref($menuorder) eq 'ARRAY') {      if (ref($menuorder) eq 'ARRAY') {
         @order = @{$menuorder};          @order = @{$menuorder};
Line 1172  END Line 1179  END
     $result .= "</select>\n";      $result .= "</select>\n";
     my %select2 = %{$hashref->{$firstdefault}->{'select2'}};      my %select2 = %{$hashref->{$firstdefault}->{'select2'}};
     $result .= $middletext;      $result .= $middletext;
     $result .= "<select size=\"1\" name=\"$secondselectname\"";      $result .= "<select size=\"1\" name=\"$secondselectname\">\n";
     if ($onchangesecond) {  
         $result .= ' onchange="'.$onchangesecond.'"';  
     }  
     $result .= ">\n";  
     my $seconddefault = $hashref->{$firstdefault}->{'default'};      my $seconddefault = $hashref->{$firstdefault}->{'default'};
           
     my @secondorder = sort(keys(%select2));      my @secondorder = sort(keys(%select2));
Line 1236  sub help_open_topic { Line 1239  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 1354  sub help_open_menu { Line 1353  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 1419  function helpMenu(target) { Line 1410  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 1734  RESIZE Line 1724  RESIZE
   
 =head1 Excel and CSV file utility routines  =head1 Excel and CSV file utility routines
   
   =over 4
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 1741  RESIZE Line 1733  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 2176  sub select_level_form { Line 2166  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 2189  If the $showdomdesc flag is set, the dom Line 2179  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 2334  Outputs: Line 2318  Outputs:
   
 =item * $clientos  =item * $clientos
   
 =item * $clientmobile  
   
 =item * $clientinfo  
   
 =back  =back
   
 =back   =back 
Line 2356  sub decode_user_agent { Line 2336  sub decode_user_agent {
     my $clientversion='0';      my $clientversion='0';
     my $clientmathml='';      my $clientmathml='';
     my $clientunicode='0';      my $clientunicode='0';
     my $clientmobile=0;  
     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)) {
Line 2368  sub decode_user_agent { Line 2347  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 2380  sub decode_user_agent { Line 2358  sub decode_user_agent {
         ($httpbrowser=~/powerpc/i)) { $clientos='mac'; }          ($httpbrowser=~/powerpc/i)) { $clientos='mac'; }
     if ($httpbrowser=~/win/i) { $clientos='win'; }      if ($httpbrowser=~/win/i) { $clientos='win'; }
     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,);
 }  }
   
 ###############################################################  ###############################################################
Line 2541  END Line 2511  END
     return $result;      return $result;
 }  }
   
 sub authform_authorwarning {  sub authform_authorwarning{
     my $result='';      my $result='';
     $result='<i>'.      $result='<i>'.
         &mt('As a general rule, only authors or co-authors should be '.          &mt('As a general rule, only authors or co-authors should be '.
Line 2550  sub authform_authorwarning { Line 2520  sub authform_authorwarning {
     return $result;      return $result;
 }  }
   
 sub authform_nochange {  sub authform_nochange{  
     my %in = (      my %in = (
               formname => 'document.cu',                formname => 'document.cu',
               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 (keys(%can_assign) == 0) {
         $result = &mt('Under your current role you are not permitted to change login settings for this user');          $result = &mt('Under you current role you are not permitted to change login settings for this user');  
     } else {      } else {
         $result = '<label>'.&mt('[_1] Do not change login data',          $result = '<label>'.&mt('[_1] Do not change login data',
                   '<input type="radio" name="login" value="nochange" '.                    '<input type="radio" name="login" value="nochange" '.
Line 2579  sub authform_kerberos { Line 2549  sub authform_kerberos {
               );                );
     my ($check4,$check5,$krbcheck,$krbarg,$krbver,$result,$authtype,      my ($check4,$check5,$krbcheck,$krbarg,$krbver,$result,$authtype,
         $autharg,$jscall);          $autharg,$jscall);
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});      my ($authnum,%can_assign) =  &get_assignable_auth($in{'domain'});
     if ($in{'kerb_def_auth'} eq 'krb5') {      if ($in{'kerb_def_auth'} eq 'krb5') {
        $check5 = ' checked="checked"';         $check5 = ' checked="checked"';
     } else {      } else {
Line 2629  sub authform_kerberos { Line 2599  sub authform_kerberos {
         if (defined($in{'mode'})) {          if (defined($in{'mode'})) {
             if ($in{'mode'} eq 'modifycourse') {              if ($in{'mode'} eq 'modifycourse') {
                 if ($authnum == 1) {                  if ($authnum == 1) {
                     $authtype = '<input type="radio" name="login" value="krb" />';                      $authtype = '<input type="hidden" name="login" value="krb" />';
                 }                  }
             }              }
         }          }
Line 2641  sub authform_kerberos { Line 2611  sub authform_kerberos {
                     $krbcheck.' />';                      $krbcheck.' />';
     }      }
     if (($can_assign{'krb4'} && $can_assign{'krb5'}) ||      if (($can_assign{'krb4'} && $can_assign{'krb5'}) ||
         ($can_assign{'krb4'} && !$can_assign{'krb5'} &&          ($can_assign{'krb4'} && !$can_assign{'krb5'} && 
          $in{'curr_authtype'} eq 'krb5') ||           $in{'curr_authtype'} eq 'krb5') ||
         (!$can_assign{'krb4'} && $can_assign{'krb5'} &&          (!$can_assign{'krb4'} && $can_assign{'krb5'} && 
          $in{'curr_authtype'} eq 'krb4')) {           $in{'curr_authtype'} eq 'krb4')) {
         $result .= &mt          $result .= &mt
         ('[_1] Kerberos authenticated with domain [_2] '.          ('[_1] Kerberos authenticated with domain [_2] '.
Line 2679  sub authform_kerberos { Line 2649  sub authform_kerberos {
     return $result;      return $result;
 }  }
   
 sub authform_internal {  sub authform_internal{  
     my %in = (      my %in = (
                 formname => 'document.cu',                  formname => 'document.cu',
                 kerb_def_dom => 'MSU.EDU',                  kerb_def_dom => 'MSU.EDU',
                 @_,                  @_,
                 );                  );
     my ($intcheck,$intarg,$result,$authtype,$autharg,$jscall);      my ($intcheck,$intarg,$result,$authtype,$autharg,$jscall);
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});      my ($authnum,%can_assign) =  &get_assignable_auth($in{'domain'});
     if (defined($in{'curr_authtype'})) {      if (defined($in{'curr_authtype'})) {
         if ($in{'curr_authtype'} eq 'int') {          if ($in{'curr_authtype'} eq 'int') {
             if ($can_assign{'int'}) {              if ($can_assign{'int'}) {
Line 2715  sub authform_internal { Line 2685  sub authform_internal {
         if (defined($in{'mode'})) {          if (defined($in{'mode'})) {
             if ($in{'mode'} eq 'modifycourse') {              if ($in{'mode'} eq 'modifycourse') {
                 if ($authnum == 1) {                  if ($authnum == 1) {
                     $authtype = '<input type="radio" name="login" value="int" />';                      $authtype = '<input type="hidden" name="login" value="int" />';
                 }                  }
             }              }
         }          }
Line 2734  sub authform_internal { Line 2704  sub authform_internal {
     return $result;      return $result;
 }  }
   
 sub authform_local {  sub authform_local{  
     my %in = (      my %in = (
               formname => 'document.cu',                formname => 'document.cu',
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
               );                );
     my ($loccheck,$locarg,$result,$authtype,$autharg,$jscall);      my ($loccheck,$locarg,$result,$authtype,$autharg,$jscall);
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});      my ($authnum,%can_assign) =  &get_assignable_auth($in{'domain'});
     if (defined($in{'curr_authtype'})) {      if (defined($in{'curr_authtype'})) {
         if ($in{'curr_authtype'} eq 'loc') {          if ($in{'curr_authtype'} eq 'loc') {
             if ($can_assign{'loc'}) {              if ($can_assign{'loc'}) {
Line 2770  sub authform_local { Line 2740  sub authform_local {
         if (defined($in{'mode'})) {          if (defined($in{'mode'})) {
             if ($in{'mode'} eq 'modifycourse') {              if ($in{'mode'} eq 'modifycourse') {
                 if ($authnum == 1) {                  if ($authnum == 1) {
                     $authtype = '<input type="radio" name="login" value="loc" />';                      $authtype = '<input type="hidden" name="login" value="loc" />';
                 }                  }
             }              }
         }          }
Line 2788  sub authform_local { Line 2758  sub authform_local {
     return $result;      return $result;
 }  }
   
 sub authform_filesystem {  sub authform_filesystem{  
     my %in = (      my %in = (
               formname => 'document.cu',                formname => 'document.cu',
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
               );                );
     my ($fsyscheck,$result,$authtype,$autharg,$jscall);      my ($fsyscheck,$result,$authtype,$autharg,$jscall);
     my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});      my ($authnum,%can_assign) =  &get_assignable_auth($in{'domain'});
     if (defined($in{'curr_authtype'})) {      if (defined($in{'curr_authtype'})) {
         if ($in{'curr_authtype'} eq 'fsys') {          if ($in{'curr_authtype'} eq 'fsys') {
             if ($can_assign{'fsys'}) {              if ($can_assign{'fsys'}) {
Line 2821  sub authform_filesystem { Line 2791  sub authform_filesystem {
         if (defined($in{'mode'})) {          if (defined($in{'mode'})) {
             if ($in{'mode'} eq 'modifycourse') {              if ($in{'mode'} eq 'modifycourse') {
                 if ($authnum == 1) {                  if ($authnum == 1) {
                     $authtype = '<input type="radio" name="login" value="fsys" />';                      $authtype = '<input type="hidden" name="login" value="fsys" />';
                 }                  }
             }              }
         }          }
Line 3052  sub get_related_words { Line 3022  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 3059  sub get_related_words { Line 3068  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 3249  sub screenname { Line 3283  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 4867  sub designparm { Line 4901  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 4930  Input: (optional) filename from which br Line 4964  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 4945  sub CSTR_pageheader { Line 4979  sub CSTR_pageheader {
   
     my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};      my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
     my ($udom,$uname,$thisdisfn)=      my ($udom,$uname,$thisdisfn)=
         ($trailfile =~ m{^\Q$londocroot\E/priv/([^/]+)/([^/]+)(?:|/(.*))$});          ($trailfile =~ m{^\Q$londocroot\E/priv/([^/]+)/([^/]+)/(.*)$});
     my $formaction = "/priv/$udom/$uname/$thisdisfn";      my $formaction = "/priv/$udom/$uname/$thisdisfn";
     $formaction =~ s{/+}{/}g;      $formaction =~ s{/+}{/}g;
   
Line 4961  sub CSTR_pageheader { Line 4995  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 5020  Inputs: Line 5054  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 5044  other decorations will be returned. Line 5075  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 5052  sub bodytag { Line 5083  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 5094  sub bodytag { Line 5124  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 5117  sub bodytag { Line 5149  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 5198  sub bodytag { Line 5212  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 5277  sub make_attr_string { Line 5243  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 5420  form, .inline { Line 5379  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 5466  form, .inline { Line 5417  form, .inline {
   
 .LC_error {  .LC_error {
   color: red;    color: red;
     font-size: larger;
 }  }
   
 .LC_warning {  .LC_warning,
   color: darkorange;  
 }  
   
 .LC_diff_removed {  .LC_diff_removed {
   color: red;    color: red;
 }  }
Line 5634  td.LC_table_cell_checkbox { Line 5583  td.LC_table_cell_checkbox {
   text-align: left;    text-align: left;
 }  }
   
 .LC_head_subbox, .LC_actionbox {  .LC_head_subbox {
   clear:both;    clear:both;
   background: #F8F8F8; /* $sidebg; */    background: #F8F8F8; /* $sidebg; */
   border: 1px solid $sidebg;    border: 1px solid $sidebg;
   margin: 0 0 10px 0;    margin: 0 0 10px 0;      
   padding: 3px;    padding: 3px;
   text-align: left;    text-align: left;
 }  }
Line 5771  table.LC_nested tr.LC_empty_row td { Line 5720  table.LC_nested tr.LC_empty_row td {
   padding: 8px;    padding: 8px;
 }  }
   
 table.LC_data_table tr.LC_empty_row td,  table.LC_data_table tr.LC_empty_row td {
 table.LC_data_table tr.LC_footer_row td {  
   background-color: $sidebg;    background-color: $sidebg;
 }  }
   
Line 6334  div.LC_docs_entry_move { Line 6282  div.LC_docs_entry_move {
   
 table.LC_data_table tr > td.LC_docs_entry_commands,  table.LC_data_table tr > td.LC_docs_entry_commands,
 table.LC_data_table tr > td.LC_docs_entry_parameter {  table.LC_data_table tr > td.LC_docs_entry_parameter {
     background: #DDDDDD;
   font-size: x-small;    font-size: x-small;
 }  }
   
Line 6498  div.LC_edit_problem_saves { Line 6447  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 6525  div.LC_createcourse { Line 6461  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 6623  fieldset > legend { Line 6558  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 6719  ol.LC_docs_parameters li.LC_docs_paramet Line 6655  ol.LC_docs_parameters li.LC_docs_paramet
 }  }
   
 ul#LC_secondary_menu {  ul#LC_secondary_menu {
   clear: right;    clear: both;
   color: $fontmenu;    color: $fontmenu;
   background: $tabbg;    background: $tabbg;
   list-style: none;    list-style: none;
Line 6727  ul#LC_secondary_menu { Line 6663  ul#LC_secondary_menu {
   margin: 0;    margin: 0;
   width: 100%;    width: 100%;
   text-align: left;    text-align: left;
   float: left;  
 }  }
   
 ul#LC_secondary_menu li {  ul#LC_secondary_menu li {
   font-weight: bold;    font-weight: bold;
   line-height: 1.8em;    line-height: 1.8em;
   border-right: 1px solid black;  
   vertical-align: middle;  
   float: left;  
 }  
   
 ul#LC_secondary_menu li.LC_hoverable:hover, ul#LC_secondary_menu li.hover {  
   background-color: $data_table_light;  
 }  
   
 ul#LC_secondary_menu li a {  
   padding: 0 0.8em;    padding: 0 0.8em;
 }  
   
 ul#LC_secondary_menu li ul {  
   display: none;  
 }  
   
 ul#LC_secondary_menu li:hover ul, ul#LC_secondary_menu li.hover ul {  
   display: block;  
   position: absolute;  
   margin: 0;  
   padding: 0;  
   list-style:none;  
   float: none;  
   background-color: $data_table_light;  
   z-index: 2;  
   margin-left: -1px;  
 }  
   
 ul#LC_secondary_menu li ul li {  
   font-size: 90%;  
   vertical-align: top;  
   border-left: 1px solid black;  
   border-right: 1px solid black;    border-right: 1px solid black;
   background-color: $data_table_light;    display: inline;
   list-style:none;    vertical-align: middle;
   float: none;  
 }  
   
 ul#LC_secondary_menu li ul li:hover, ul#LC_secondary_menu li ul li.hover {  
   background-color: $data_table_dark;  
 }  }
   
 ul.LC_TabContent {  ul.LC_TabContent {
Line 7220  ul.LC_funclist li { Line 7118  ul.LC_funclist li {
  cursor:pointer;   cursor:pointer;
 }  }
   
 /*  
   styles used by TTH when "Default set of options to pass to tth/m  
   when converting TeX" in course settings has been set  
   
   option passed: -t  
   
 */  
   
 td div.comp { margin-top: -0.6ex; margin-bottom: -1ex;}  
 td div.comb { margin-top: -0.6ex; margin-bottom: -.6ex;}  
 td div.hrcomp { line-height: 0.9; margin-top: -0.8ex; margin-bottom: -1ex;}  
 td div.norm {line-height:normal;}  
   
 /*  
   option passed -y3  
 */  
   
 span.roman {font-family: serif; font-style: normal; font-weight: normal;}  
 span.overacc2 {position: relative;  left: .8em; top: -1.2ex;}  
 span.overacc1 {position: relative;  left: .6em; top: -1.2ex;}  
   
 END  END
 }  }
   
Line 7277  sub headtag { Line 7154  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 7288  sub headtag { Line 7164  sub headtag {
   
     my $result =      my $result =
  '<head>'.   '<head>'.
  &font_settings($args);   &font_settings();
   
     my $inhibitprint = &print_suppression();      my $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 7336  ADDMETA Line 7212  ADDMETA
     }      }
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }      if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
     $result .= '<title> LON-CAPA '.$title.'</title>'      $result .= '<title> LON-CAPA '.$title.'</title>'
  .'<link rel="stylesheet" type="text/css" href="'.$url.'"';   .'<link rel="stylesheet" type="text/css" href="'.$url.'" />'
     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 7357  ADDMETA Line 7224  ADDMETA
   
 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 7463  Inputs: none Line 7324  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 7475  sub xml_begin { Line 7335  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 7524  $args - additional optional args support Line 7381  $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 7549  sub start_page { Line 7404  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 7563  sub start_page { Line 7418  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 7604  sub start_page { Line 7459  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 7655  function set_wishlistlink(title, path) { Line 7505  function set_wishlistlink(title, path) {
         title = document.title;          title = document.title;
         title = title.replace(/^LON-CAPA /,'');          title = title.replace(/^LON-CAPA /,'');
     }      }
     title = encodeURIComponent(title);  
     if (!path) {      if (!path) {
         path = location.pathname;          path = location.pathname;
     }      }
     path = encodeURIComponent(path);  
     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 7700  var modalWindow = { Line 7548  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)
  {   {
  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+"'>&lt/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 -->
Line 7715  ENDMODAL Line 7563  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 7754  sub modal_adhoc_inner { Line 7600  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 7876  sub LCprogressbar { Line 7722  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 7974  sub validate_page { Line 7822  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 8002  sub end_scrollbox { Line 7843  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>'.   '<span class="LC_warning">'.&mt($msg).'</span>'.
  &Apache::loncommon::end_page();   &Apache::loncommon::end_page();
     if (ref($r)) {      if (ref($r)) {
  $r->print($page);   $r->print($page);
Line 8386  sub get_sections { Line 8140  sub get_sections {
     my %sectioncount;      my %sectioncount;
     my $now = time;      my $now = time;
   
     my $check_students = 1;      if (!defined($possible_roles) || (grep(/^st$/,@$possible_roles))) {
     my $only_students = 0;  
     if (ref($possible_roles) eq 'ARRAY') {  
         if (grep(/^st$/,@{$possible_roles})) {  
             if (@{$possible_roles} == 1) {  
                 $only_students = 1;  
             }  
         } else {  
             $check_students = 0;  
         }  
     }  
   
     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 8425  sub get_sections { Line 8167  sub get_sections {
     }      }
  }   }
     }      }
     if ($only_students) {  
         return %sectioncount;  
     }  
     my %courseroles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);      my %courseroles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
     foreach my $user (sort(keys(%courseroles))) {      foreach my $user (sort(keys(%courseroles))) {
  if ($user !~ /^(\w{2})/) { next; }   if ($user !~ /^(\w{2})/) { next; }
Line 8575  sub get_course_users { Line 8314  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 8585  sub get_course_users { Line 8324  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 8624  sub get_course_users { Line 8359  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 8712  sub get_user_info { Line 8447  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 8735  Returns: Line 8465  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 8743  defined for the user's institutional sta Line 8473  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 8758  sub get_user_quota { Line 8488  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 8829  Retrieves default quota assigned for sto Line 8528  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 8896  sub default_quota { Line 8589  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 8923  sub default_quota { Line 8607  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><span class="LC_warning">'.  
                 &mt("Unable to $action [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.",  
                     '<span class="LC_filename">'.$filename.'</span>',$filesize).'</span>'.  
                '<br />'.&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 9336  sub user_rule_formats { Line 8964  sub user_rule_formats {
     my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($domain,$check);      my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($domain,$check);
     if ((ref($rules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {      if ((ref($rules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {
         if (@{$ruleorder} > 0) {          if (@{$ruleorder} > 0) {
             $output = '<br />'.              $output = '<br />'.&mt("$text{$check} with the following format(s) may <span class=\"LC_cusr_emph\">only</span> be used for verified users at [_1]:",$domdesc).' <ul>';
                       &mt($text{$check}.' with the following format(s) may [_1]only[_2] be used for verified users at [_3]:',  
                           '<span class="LC_cusr_emph">','</span>',$domdesc).  
                       ' <ul>';  
             foreach my $rule (@{$ruleorder}) {              foreach my $rule (@{$ruleorder}) {
                 if (ref($curr_rules) eq 'ARRAY') {                  if (ref($curr_rules) eq 'ARRAY') {
                     if (grep(/^\Q$rule\E$/,@{$curr_rules})) {                      if (grep(/^\Q$rule\E$/,@{$curr_rules})) {
Line 9818  sub ask_for_embedded_content { Line 9443  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 9861  sub ask_for_embedded_content { Line 9482  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 {  
                     ($path) =  
                         ($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{^/}{};
                 ($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 9933  sub ask_for_embedded_content { Line 9535  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 9943  sub ask_for_embedded_content { Line 9545  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 9960  sub ask_for_embedded_content { Line 9561  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 10016  sub ask_for_embedded_content { Line 9611  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 10033  sub ask_for_embedded_content { Line 9627  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 10069  sub ask_for_embedded_content { Line 9662  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 10085  sub ask_for_embedded_content { Line 9676  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 10145  sub ask_for_embedded_content { Line 9726  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 10242  sub ask_for_embedded_content { Line 9822  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 10285  sub ask_for_embedded_content { Line 9865  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 10298  sub ask_for_embedded_content { Line 9878  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 10473  sub upload_embedded { Line 10013  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 10509  sub upload_embedded { Line 10046  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 10523  sub upload_embedded { Line 10059  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 10657  sub modify_html_form { Line 10190  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 10666  sub modify_html_refs { Line 10199  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 10681  sub modify_html_refs { Line 10212  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 10737  sub modify_html_refs { Line 10268  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 10747  sub modify_html_refs { Line 10276  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 10764  sub modify_html_refs { Line 10292  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 10784  sub modify_html_refs { Line 10307  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 11032  sub decompress_form { Line 10514  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 = ("$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 @diffs = &compare_arrays(\@paths,\@camtasia6);  
         if (@diffs == 0) {          if (@diffs == 0) {
             $is_camtasia = 6;              $is_camtasia = 1;
         } else {  
             @diffs = &compare_arrays(\@paths,\@camtasia8);  
             if (@diffs == 0) {  
                 $is_camtasia = 8;  
             }  
         }          }
     }      }
     my $output;      my $output;
Line 11080  sub decompress_form { Line 10535  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 11142  ENDCAM Line 10598  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 11266  sub process_decompression { Line 10722  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)$/) {      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 11375  sub process_decompression { Line 10831  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 11394  sub process_decompression { Line 10849  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 11845  sub process_extracted_files { Line 11297  sub process_extracted_files {
     if ($env{'form.folderpath'}) {      if ($env{'form.folderpath'}) {
         my @items = split('&',$env{'form.folderpath'});          my @items = split('&',$env{'form.folderpath'});
         $folders{'0'} = $items[-2];          $folders{'0'} = $items[-2];
         if ($env{'form.folderpath'} =~ /\:1$/) {          $containers{'0'}='sequence';
             $containers{'0'}='page';      } elsif ($env{'form.pagepath'}) {
         } else {          my @items = split('&',$env{'form.pagepath'});
             $containers{'0'}='sequence';          $folders{'0'} = $items[-2];
         }          $containers{'0'}='page';
     }      }
     my @archdirs = &get_env_multiple('form.archive_directory');      my @archdirs = &get_env_multiple('form.archive_directory');
     if ($numitems) {      if ($numitems) {
Line 11967  sub process_extracted_files { Line 11419  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 11989  sub process_extracted_files { Line 11441  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 12036  sub process_extracted_files { Line 11488  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 12051  sub process_extracted_files { Line 11503  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 12110  sub cleanup_empty_dirs { Line 11562  sub cleanup_empty_dirs {
             my $numitems = 0;              my $numitems = 0;
             foreach my $item (@dircontents) {              foreach my $item (@dircontents) {
                 if (-d "$path/$item") {                  if (-d "$path/$item") {
                     &cleanup_empty_dirs("$path/$item");                      &recurse_dirs("$path/$item");
                     if (-e "$path/$item") {                      if (-e "$path/$item") {
                         $numitems ++;                          $numitems ++;
                     }                      }
Line 12129  sub cleanup_empty_dirs { Line 11581  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 12157  sub get_folder_hierarchy { Line 11609  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 12172  sub get_folder_hierarchy { Line 11624  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 12239  sub get_turnedin_filepath { Line 11691  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 12250  sub get_turnedin_filepath { Line 11699  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 12293  sub get_turnedin_filepath { Line 11739  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 13233  sub restore_settings { Line 12676  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 13442  sub extract_categories { Line 12881  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 13513  sub recurse_categories { Line 12952  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 13590  sub assign_categories_table { Line 13029  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 13624  sub assign_category_rows { Line 13063  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 13672  sub commit_customrole { Line 13111  sub commit_customrole {
 }  }
   
 sub commit_standardrole {  sub commit_standardrole {
     my ($udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context,$credits) = @_;      my ($udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context) = @_;
     my ($output,$logmsg,$linefeed);      my ($output,$logmsg,$linefeed);
     if ($context eq 'auto') {      if ($context eq 'auto') {
         $linefeed = "\n";          $linefeed = "\n";
Line 13681  sub commit_standardrole { Line 13120  sub commit_standardrole {
     }        }  
     if ($three eq 'st') {      if ($three eq 'st') {
         my $result = &commit_studentrole(\$logmsg,$udom,$uname,$url,$three,$start,$end,          my $result = &commit_studentrole(\$logmsg,$udom,$uname,$url,$three,$start,$end,
                                          $one,$two,$sec,$context,$credits);                                           $one,$two,$sec,$context);
         if (($result =~ /^error/) || ($result eq 'not_in_class') ||           if (($result =~ /^error/) || ($result eq 'not_in_class') || 
             ($result eq 'unknown_course') || ($result eq 'refused')) {              ($result eq 'unknown_course') || ($result eq 'refused')) {
             $output = $logmsg.' '.&mt('Error: ').$result."\n";               $output = $logmsg.' '.&mt('Error: ').$result."\n"; 
Line 13712  sub commit_standardrole { Line 13151  sub commit_standardrole {
 }  }
   
 sub commit_studentrole {  sub commit_studentrole {
     my ($logmsg,$udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context,      my ($logmsg,$udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context) = @_;
         $credits) = @_;  
     my ($result,$linefeed,$oldsecurl,$newsecurl);      my ($result,$linefeed,$oldsecurl,$newsecurl);
     if ($context eq 'auto') {      if ($context eq 'auto') {
         $linefeed = "\n";          $linefeed = "\n";
Line 13760  sub commit_studentrole { Line 13198  sub commit_studentrole {
             }              }
         }          }
         if (($expire_role_result eq 'ok') || ($secchange == 0)) {          if (($expire_role_result eq 'ok') || ($secchange == 0)) {
             $modify_section_result =               $modify_section_result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,'','',$cid,'',$context);
                 &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,  
                                                            undef,undef,undef,$sec,  
                                                            $end,$start,'','',$cid,  
                                                            '',$context,$credits);  
             if ($modify_section_result =~ /^ok/) {              if ($modify_section_result =~ /^ok/) {
                 if ($secchange == 1) {                  if ($secchange == 1) {
                     if ($sec eq '') {                      if ($sec eq '') {
Line 13795  sub commit_studentrole { Line 13229  sub commit_studentrole {
             $result = $modify_section_result;              $result = $modify_section_result;
         } elsif ($secchange == 1) {          } elsif ($secchange == 1) {
             if ($oldsec eq '') {              if ($oldsec eq '') {
                 $$logmsg .= &mt('Error when attempting to expire existing role without a section for [_1] in course [_2] -error: ',$uname,$cid).' '.$expire_role_result.$linefeed;                  $$logmsg .= &mt('Error when attempting to expire existing role without a section for [_1] in course [_3] -error: ',$uname,$cid).' '.$expire_role_result.$linefeed;
             } else {              } else {
                 $$logmsg .= &mt('Error when attempting to expire existing role for [_1] in section [_2] in course [_3] -error: ',$uname,$oldsec,$cid).' '.$expire_role_result.$linefeed;                  $$logmsg .= &mt('Error when attempting to expire existing role for [_1] in section [_2] in course [_3] -error: ',$uname,$oldsec,$cid).' '.$expire_role_result.$linefeed;
             }              }
Line 13821  sub commit_studentrole { Line 13255  sub commit_studentrole {
     return $result;      return $result;
 }  }
   
 sub show_role_extent {  
     my ($scope,$context,$role) = @_;  
     $scope =~ s{^/}{};  
     my @courseroles = &Apache::lonuserutils::roles_by_context('course',1);  
     push(@courseroles,'co');  
     my @authorroles = &Apache::lonuserutils::roles_by_context('author');  
     if (($context eq 'course') || (grep(/^\Q$role\E/,@courseroles))) {  
         $scope =~ s{/}{_};  
         return '<span class="LC_cusr_emph">'.$env{'course.'.$scope.'.description'}.'</span>';  
     } elsif (($context eq 'author') || (grep(/^\Q$role\E/,@authorroles))) {  
         my ($audom,$auname) = split(/\//,$scope);  
         return &mt('[_1] Author Space','<span class="LC_cusr_emph">'.  
                    &Apache::loncommon::plainname($auname,$audom).'</span>');  
     } else {  
         $scope =~ s{/$}{};  
         return &mt('Domain: [_1]','<span class="LC_cusr_emph">'.  
                    &Apache::lonnet::domain($scope,'description').'</span>');  
     }  
 }  
   
 ############################################################  ############################################################
 ############################################################  ############################################################
   
Line 13908  sub check_clone { Line 13322  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 14004  sub construct_course { Line 13418  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 14038  sub construct_course { Line 13447  sub construct_course {
     } else {      } else {
         $cenv{'internal.courseowner'} = $args->{'curruser'};          $cenv{'internal.courseowner'} = $args->{'curruser'};
     }      }
     if ($args->{'defaultcredits'}) {  
         $cenv{'internal.defaultcredits'} = $args->{'defaultcredits'};  
     }  
     my @badclasses = (); # Used to accumulate sections/crosslistings that did not pass classlist access check for course owner.      my @badclasses = (); # Used to accumulate sections/crosslistings that did not pass classlist access check for course owner.
     if ($args->{'crssections'}) {      if ($args->{'crssections'}) {
         $cenv{'internal.sectionnums'} = '';          $cenv{'internal.sectionnums'} = '';
Line 14065  sub construct_course { Line 13471  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 14194  sub construct_course { Line 13595  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 14281  sub construct_course { Line 13663  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 14362  sub group_term { Line 13690  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 14500  sub init_user_environment { Line 13827  sub init_user_environment {
 # ------------------------------------ Check browser type and MathML capability  # ------------------------------------ Check browser type and MathML capability
   
     my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,      my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
         $clientunicode,$clientos,$clientmobile,$clientinfo) = &decode_user_agent($r);          $clientunicode,$clientos) = &decode_user_agent($r);
   
 # ------------------------------------------------------------- Get environment  # ------------------------------------------------------------- Get environment
   
Line 14531  sub init_user_environment { Line 13858  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,  
      "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 14552  sub init_user_environment { Line 13877  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 14570  sub init_user_environment { Line 13889  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 14584  sub init_user_environment { Line 13903  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 14742  sub update_content_constraints { Line 14061  sub update_content_constraints {
     return;      return;
 }  }
   
 sub allmaps_incourse {  
     my ($cdom,$cnum,$chome,$cid) = @_;  
     if ($cdom eq '' || $cnum eq '' || $chome eq '' || $cid eq '') {  
         $cid = $env{'request.course.id'};  
         $cdom = $env{'course.'.$cid.'.domain'};  
         $cnum = $env{'course.'.$cid.'.num'};  
         $chome = $env{'course.'.$cid.'.home'};  
     }  
     my %allmaps = ();  
     my $lastchange =  
         &Apache::lonnet::get_coursechange($cdom,$cnum);  
     if ($lastchange > $env{'request.course.tied'}) {  
         my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum");  
         unless ($ferr) {  
             &update_content_constraints($cdom,$cnum,$chome,$cid);  
         }  
     }  
     my $navmap = Apache::lonnavmaps::navmap->new();  
     if (defined($navmap)) {  
         foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_map() },1,0,1)) {  
             $allmaps{$res->src()} = 1;  
         }  
     }  
     return \%allmaps;  
 }  
   
 sub parse_supplemental_title {  sub parse_supplemental_title {
     my ($title) = @_;      my ($title) = @_;
   
Line 14791  sub parse_supplemental_title { Line 14084  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 {  
     my ($symb) = @_;  
     return unless ($symb);  
     my ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($symb);  
     if ($resurl=~/\.(sequence|page)$/) {  
         $mapurl=$resurl;  
     } elsif ($resurl eq 'adm/navmaps') {  
         $mapurl=$env{'course.'.$env{'request.course.id'}.'.url'};  
     }  
     my $mapresobj;  
     my $navmap = Apache::lonnavmaps::navmap->new();  
     if (ref($navmap)) {  
         $mapresobj = $navmap->getResourceByUrl($mapurl);  
     }  
     $mapurl=~s{^.*/([^/]+)\.(\w+)$}{$1};  
     my $type=$2;  
     my $path;  
     if (ref($mapresobj)) {  
         my $pcslist = $mapresobj->map_hierarchy();  
         if ($pcslist ne '') {  
             foreach my $pc (split(/,/,$pcslist)) {  
                 next if ($pc <= 1);  
                 my $res = $navmap->getByMapPc($pc);  
                 if (ref($res)) {  
                     my $thisurl = $res->src();  
                     $thisurl=~s{^.*/([^/]+)\.\w+$}{$1};  
                     my $thistitle = $res->title();  
                     $path .= '&'.  
                              &Apache::lonhtmlcommon::entity_encode($thisurl).'&'.  
                              &escape($thistitle).  
                              ':'.$res->randompick().  
                              ':'.$res->randomout().  
                              ':'.$res->encrypted().  
                              ':'.$res->randomorder().  
                              ':'.$res->is_page();  
                 }  
             }  
         }  
         $path =~ s/^\&//;  
         my $maptitle = $mapresobj->title();  
         if ($mapurl eq 'default') {  
             $maptitle = 'Main Content';  
         }  
         $path .= (($path ne '')? '&' : '').  
                  &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.  
                  &escape($maptitle).  
                  ':'.$mapresobj->randompick().  
                  ':'.$mapresobj->randomout().  
                  ':'.$mapresobj->encrypted().  
                  ':'.$mapresobj->randomorder().  
                  ':'.$mapresobj->is_page();  
     } else {  
         my $maptitle = &Apache::lonnet::gettitle($mapurl);  
         my $ispage = (($type eq 'page')? 1 : '');  
         if ($mapurl eq 'default') {  
             $maptitle = 'Main Content';  
         }  
         $path = &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.  
                 &escape($maptitle).':::::'.$ispage;  
     }  
     unless ($mapurl eq 'default') {  
         $path = 'default&'.  
                 &escape('Main Content').  
                 ':::::&'.$path;  
     }  
     return $path;  
 }  
   
 sub captcha_display {  sub captcha_display {
     my ($context,$lonhost) = @_;      my ($context,$lonhost) = @_;
     my ($output,$error);      my ($output,$error);
Line 14890  sub captcha_display { Line 14091  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);      return ($output,$error);
Line 15001  sub check_captcha { Line 14202  sub check_captcha {
                       output_folder => $captcha_params{'output_dir'},                        output_folder => $captcha_params{'output_dir'},
                       data_folder   => $captcha_params{'db_dir'},                        data_folder   => $captcha_params{'db_dir'},
                   );                    );
     $captcha_chk = $captcha->check_code($code,$md5sum);      my $captcha_chk = $captcha->check_code($code,$md5sum);
     my %captcha_hash = (      my %captcha_hash = (
                         0       => 'Code not checked (file error)',                          0       => 'Code not checked (file error)',
                        -1      => 'Failed: code expired',                         -1      => 'Failed: code expired',
Line 15016  sub check_captcha { Line 14217  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 either word 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 15045  sub check_recaptcha { Line 14242  sub check_recaptcha {
     return $captcha_chk;      return $captcha_chk;
 }  }
   
 sub emailusername_info {  
     my @fields = ('lastname','firstname','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 {  
     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;  
 }  
   
 # Use:  
 #   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;  
 }  
   
 =pod  =pod
   
 =back  =back

Removed from v.1.1075.2.65  
changed lines
  Added in v.1.1096


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