Diff for /loncom/interface/loncommon.pm between versions 1.1075.2.161.2.9 and 1.1075.2.161.2.28

version 1.1075.2.161.2.9, 2022/08/30 20:09:21 version 1.1075.2.161.2.28, 2024/09/07 18:47:20
Line 71  use Apache::lonuserutils(); Line 71  use Apache::lonuserutils();
 use Apache::lonuserstate();  use Apache::lonuserstate();
 use Apache::courseclassifier();  use Apache::courseclassifier();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
   use LONCAPA::map();
 use HTTP::Request;  use HTTP::Request;
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale;  use DateTime::Locale;
Line 430  sub studentbrowser_javascript { Line 431  sub studentbrowser_javascript {
 <script type="text/javascript" language="Javascript">  <script type="text/javascript" language="Javascript">
 // <![CDATA[  // <![CDATA[
     var stdeditbrowser;      var stdeditbrowser;
     function openstdbrowser(formname,uname,udom,clicker,roleflag,ignorefilter,courseadv) {      function openstdbrowser(formname,uname,udom,clicker,roleflag,ignorefilter,courseadv,uident) {
         var url = '/adm/pickstudent?';          var url = '/adm/pickstudent?';
         var filter;          var filter;
  if (!ignorefilter) {   if (!ignorefilter) {
Line 451  sub studentbrowser_javascript { Line 452  sub studentbrowser_javascript {
             }              }
         }          }
         if ((courseadv == 'only') || (courseadv == 'none')) { url+="&courseadv="+courseadv; }          if ((courseadv == 'only') || (courseadv == 'none')) { url+="&courseadv="+courseadv; }
           if (uident !== '') { url+="&identelement="+uident; }
         var title = 'Student_Browser';          var title = 'Student_Browser';
         var options = 'scrollbars=1,resizable=1,menubar=0';          var options = 'scrollbars=1,resizable=1,menubar=0';
         options += ',width=700,height=600';          options += ',width=700,height=600';
Line 482  ENDRESBRW Line 484  ENDRESBRW
 }  }
   
 sub selectstudent_link {  sub selectstudent_link {
    my ($form,$unameele,$udomele,$courseadv,$clickerid)=@_;     my ($form,$unameele,$udomele,$courseadv,$clickerid,$identelem)=@_;
    my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','".     my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','".
                       &Apache::lonhtmlcommon::entity_encode($unameele)."','".                        &Apache::lonhtmlcommon::entity_encode($unameele)."','".
                       &Apache::lonhtmlcommon::entity_encode($udomele)."'";                        &Apache::lonhtmlcommon::entity_encode($udomele)."'";
Line 499  sub selectstudent_link { Line 501  sub selectstudent_link {
            $callargs .= ",'','','$courseadv'";             $callargs .= ",'','','$courseadv'";
        } elsif ($courseadv eq 'condition') {         } elsif ($courseadv eq 'condition') {
            $callargs .= ",'','','$courseadv'";             $callargs .= ",'','','$courseadv'";
          } elsif ($identelem ne '') {
              $callargs .= ",'','',''";
          }
          if ($identelem ne '') {
              $callargs .= ",'".&Apache::lonhtmlcommon::entity_encode($identelem)."'";
        }         }
        return '<span class="LC_nobreak">'.         return '<span class="LC_nobreak">'.
               '<a href="javascript:openstdbrowser('.$callargs.');">'.                '<a href="javascript:openstdbrowser('.$callargs.');">'.
Line 950  ENDSCRT Line 957  ENDSCRT
 }  }
   
 sub select_timezone {  sub select_timezone {
    my ($name,$selected,$onchange,$includeempty,$disabled)=@_;     my ($name,$selected,$onchange,$includeempty,$id,$disabled)=@_;
    my $output='<select name="'.$name.'" '.$onchange.$disabled.'>'."\n";     my $output='<select name="'.$name.'" '.$id.$onchange.$disabled.'>'."\n";
    if ($includeempty) {     if ($includeempty) {
        $output .= '<option value=""';         $output .= '<option value=""';
        if (($selected eq '') || ($selected eq 'local')) {         if (($selected eq '') || ($selected eq 'local')) {
Line 1279  sub help_open_topic { Line 1286  sub help_open_topic {
     my $target = ' target="_top"';      my $target = ' target="_top"';
     if ($links_target) {      if ($links_target) {
         $target = ' target="'.$links_target.'"';          $target = ' target="'.$links_target.'"';
     } elsif (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self')) {      } elsif ((($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) ||
                (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self'))) {
         $target = '';          $target = '';
     }      }
     if ($text ne "") {      if ($text ne "") {
Line 1720  the id of the element to resize, second Line 1728  the id of the element to resize, second
 surrounds everything that comes after the textarea, this routine needs  surrounds everything that comes after the textarea, this routine needs
 to be attached to the <body> for the onload and onresize events.  to be attached to the <body> for the onload and onresize events.
   
 =back  
   
 =cut  =cut
   
 sub resize_textarea_js {  sub resize_textarea_js {
Line 2008  sub insert_folding_button { Line 2014  sub insert_folding_button {
             value=\"".&mt('Hide')."\" onclick=\"fold_box('$curDepth','$lastresource')\">";              value=\"".&mt('Hide')."\" onclick=\"fold_box('$curDepth','$lastresource')\">";
 }  }
   
   =pod
   
   =item * &iframe_wrapper_headjs()
   
   emits javascript containing two global vars to facilitate handling of resizing
   by code in iframe_wrapper_resizejs() used when an iframe is present in a page
   with standard LON-CAPA menus.
   
   =cut
   
   #
   # Where iframe is in use, if window.onload() executes before the custom resize function
   # has been defined (jQuery), two global javascript vars (LCnotready and LCresizedef)
   # are used to ensure document.ready() triggers a call to resize, so the iframe contents
   # do not obscure the Functions menu.
   #
   
   sub iframe_wrapper_headjs {
       return <<"ENDJS";
   <script type="text/javascript">
   // <![CDATA[
   var LCnotready = 0;
   var LCresizedef = 0;
   // ]]>
   </script>
   
   ENDJS
   
   }
   
   =pod
   
   =item * &iframe_wrapper_resizejs()
   
   emits javascript used to handle resizing for a page containing
   an iframe, to ensure that the iframe does not obscure any
   standard LON-CAPA menu items.
   
   =back
   
   =cut
   
   #
   # jQuery to use when iframe is in use and a page resize occurs.
   # This script will ensure that the iframe does not obscure any
   # standard LON-CAPA inline menus (primary, secondary, and/or
   # breadcrumbs and Functions menus. Expects javascript from
   # &iframe_wrapper_headjs() to be in head portion of the web page,
   # e.g., by inclusion in second arg passed to &start_page().
   #
   
   sub iframe_wrapper_resizejs {
       my $offset = 5;
       &get_unprocessed_cgi($ENV{'QUERY_STRING'},['inhibitmenu']);
       if (($env{'form.inhibitmenu'} eq 'yes') || ($env{'form.only_body'})) {
           $offset = 0;
       }
       return &Apache::lonhtmlcommon::scripttag(<<SCRIPT);
       \$(document).ready( function() {
           \$(window).unbind('resize').resize(function(){
               var header = null;
               var offset = $offset;
               var height = 0;
               var hdrtop = 0;
               if (\$('div.LC_menus_content:first').length) {
                   if (\$('div.LC_menus_content:first').hasClass ("shown")) {
                       header = \$('div.LC_menus_content:first');
                       offset = 12;
                   }
               } else if (\$('div.LC_head_subbox:first').length) {
                   header = \$('div.LC_head_subbox:first');
                   offset = 9;
               } else {
                   if (\$('#LC_breadcrumbs').length) {
                       header = \$('#LC_breadcrumbs');
                   }
               }
               if (header != null && header.length) {
                   height = header.height();
                   hdrtop = header.position().top;
               }
               var pos = height + hdrtop + offset;
               \$('.LC_iframecontainer').css('top', pos);
           });
           LCresizedef = 1;
           if (LCnotready == 1) {
               LCnotready = 0;
               \$(window).trigger('resize');
           }
       });
       window.onload = function(){
            if (LCresizedef) {
                LCnotready = 0;
                \$(window).trigger('resize');
            } else {
                LCnotready = 1;
            }
       };
   SCRIPT
   
   }
   
 =pod  =pod
   
Line 2728  This is not an optimal method, but it wo Line 2835  This is not an optimal method, but it wo
   
 =item * authform_filesystem  =item * authform_filesystem
   
   =item * authform_lti
   
 =back  =back
   
 See loncreateuser.pm for invocation and use examples.  See loncreateuser.pm for invocation and use examples.
Line 3152  sub authform_filesystem { Line 3261  sub authform_filesystem {
     return $result;      return $result;
 }  }
   
   sub authform_lti {
       my %in = (
                 formname => 'document.cu',
                 kerb_def_dom => 'MSU.EDU',
                 @_,
                 );
       my ($lticheck,$result,$authtype,$autharg,$jscall,$disabled);
       my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
       if ($in{'readonly'}) {
           $disabled = ' disabled="disabled"';
       }
       if (defined($in{'curr_authtype'})) {
           if ($in{'curr_authtype'} eq 'lti') {
               if ($can_assign{'lti'}) {
                   $lticheck = 'checked="checked" ';
                   if (defined($in{'mode'})) {
                       if ($in{'mode'} eq 'modifyuser') {
                           $lticheck = '';
                       }
                   }
               } else {
                   $result = &mt('Currently LTI Authenticated.');
                   return $result;
               }
           }
       } else {
           if ($authnum == 1) {
               $authtype = '<input type="hidden" name="login" value="lti" />';
           }
       }
       if (!$can_assign{'lti'}) {
           return;
       } elsif ($authtype eq '') {
           if (defined($in{'mode'})) {
               if ($in{'mode'} eq 'modifycourse') {
                   if ($authnum == 1) {
                       $authtype = '<input type="radio" name="login" value="lti"'.$disabled.' />';
                   }
               }
           }
       }
       $jscall = "javascript:changed_radio('lti',$in{'formname'});";
       if (($authtype eq '') && (($in{'mode'} eq 'modifycourse') || ($in{'curr_authtype'} ne 'lti'))) {
           $authtype = '<input type="radio" name="login" value="lti" '.
                       $lticheck.' onchange="'.$jscall.'" onclick="'.
                       $jscall.'"'.$disabled.' />';
       }
       $autharg = '<input type="hidden" name="ltiarg" value="" />';
       if ($authtype) {
           $result = &mt('[_1] LTI Authenticated',
                         '<label>'.$authtype.'</label>'.$autharg);
       } else {
           $result = '<b>'.&mt('LTI Authenticated').'</b>'.
                     $autharg;
       }
       return $result;
   }
   
 sub get_assignable_auth {  sub get_assignable_auth {
     my ($dom) = @_;      my ($dom) = @_;
     if ($dom eq '') {      if ($dom eq '') {
Line 3285  sub passwd_validation_js { Line 3452  sub passwd_validation_js {
         } else {          } else {
             $alertmsg = &mt('A secret did not satisfy requirement(s):').'\n\n';              $alertmsg = &mt('A secret did not satisfy requirement(s):').'\n\n';
         }          }
       } elsif ($context eq 'ltitools') {
           my %domconfig = &Apache::lonnet::get_dom('configuration',['toolsec'],$domain);
           if (ref($domconfig{'toolsec'}) eq 'HASH') {
               if (ref($domconfig{'toolsec'}{'rules'}) eq 'HASH') {
                   %passwdconf = %{$domconfig{'toolsec'}{'rules'}};
               }
           }
           if ($id eq 'add') {
               $alertmsg = &mt('Secret for added external tool did not satisfy requirement(s):').'\n\n';
           } elsif ($id =~ /^\d+$/) {
               my $pos = $id+1;
               $alertmsg = &mt('Secret for external tool [_1] did not satisfy requirement(s):','#'.$pos).'\n\n';
           } else {
               $alertmsg = &mt('A secret did not satisfy requirement(s):').'\n\n';
           }
     } else {      } else {
         %passwdconf = &Apache::lonnet::get_passwdconf($domain);          %passwdconf = &Apache::lonnet::get_passwdconf($domain);
         $alertmsg = &mt('Initial password did not satisfy requirement(s):').'\n\n';          $alertmsg = &mt('Initial password did not satisfy requirement(s):').'\n\n';
Line 3834  sub syllabuswrapper { Line 4016  sub syllabuswrapper {
     return qq{<a href="/public/$domain/$coursedir/syllabus">$linktext</a>};      return qq{<a href="/public/$domain/$coursedir/syllabus">$linktext</a>};
 }  }
   
   sub aboutme_on {
       my ($uname,$udom)=@_;
       unless ($uname) { $uname=$env{'user.name'}; }
       unless ($udom)  { $udom=$env{'user.domain'}; }
       return if ($udom eq 'public' && $uname eq 'public');
       my $hashkey=$uname.':'.$udom;
       my ($aboutme,$cached)=&Apache::lonnet::is_cached_new('aboutme',$hashkey);
       if ($cached) {
           return $aboutme;
       }
       $aboutme = &Apache::lonnet::usertools_access($uname,$udom,'aboutme');
       &Apache::lonnet::do_cache_new('aboutme',$hashkey,$aboutme,3600);
       return $aboutme;
   }
   
   sub devalidate_aboutme_cache {
       my ($uname,$udom)=@_;
       if (!$udom)  { $udom =$env{'user.domain'}; }
       if (!$uname) { $uname=$env{'user.name'};   }
       return if ($udom eq 'public' && $uname eq 'public');
       my $id=$uname.':'.$udom;
       &Apache::lonnet::devalidate_cache_new('aboutme',$id);
   }
   
 # -----------------------------------------------------------------------------  # -----------------------------------------------------------------------------
   
 sub track_student_link {  sub track_student_link {
Line 4437  sub get_previous_attempt { Line 4643  sub get_previous_attempt {
       }        }
       $prevattempts.= &end_data_table_row().&end_data_table();        $prevattempts.= &end_data_table_row().&end_data_table();
     } else {      } else {
         my $msg;
         if ($symb =~ /ext\.tool$/) {
             $msg = &mt('No grade passed back.');
         } else {
             $msg = &mt('Nothing submitted - no attempts.');
         }
       $prevattempts=        $prevattempts=
   &start_data_table().&start_data_table_row().    &start_data_table().&start_data_table_row().
   '<td>'.&mt('Nothing submitted - no attempts.').'</td>'.    '<td>'.$msg.'</td>'.
   &end_data_table_row().&end_data_table();    &end_data_table_row().&end_data_table();
     }      }
   } else {    } else {
Line 5771  Input: (optional) filename from which br Line 5983  Input: (optional) filename from which br
        If page header is being requested for use in a frameset, then         If page header is being requested for use in a frameset, then
        the second (option) argument -- frameset will be true, and         the second (option) argument -- frameset will be true, and
        the target attribute set for links should be target="_parent".         the target attribute set for links should be target="_parent".
          If $title is supplied as the third arg, that will be used to
          the left of the breadcrumbs tail for the current path.
   
 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 Authoring Space pages
Line 5778  Returns: HTML div with CSTR path and rec Line 5992  Returns: HTML div with CSTR path and rec
 =cut  =cut
   
 sub CSTR_pageheader {  sub CSTR_pageheader {
     my ($trailfile,$frameset) = @_;      my ($trailfile,$frameset,$title) = @_;
     if ($trailfile eq '') {      if ($trailfile eq '') {
         $trailfile = $env{'request.filename'};          $trailfile = $env{'request.filename'};
     }      }
Line 5801  sub CSTR_pageheader { Line 6015  sub CSTR_pageheader {
         $lastitem = $thisdisfn;          $lastitem = $thisdisfn;
     }      }
   
       if ($title eq '') {
           $title = &mt('Authoring Space');
       }
   
     my ($target,$crumbtarget) = (' target="_top"','_top');      my ($target,$crumbtarget) = (' target="_top"','_top');
     if ($frameset) {      if ($frameset) {
         $target = ' target="_parent"';          $target = ' target="_parent"';
         $crumbtarget = '_parent';          $crumbtarget = '_parent';
       } elsif (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) {
           $target = '';
           $crumbtarget = '';
     } elsif (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'})) {      } elsif (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'})) {
         $target = ' target="'.$env{'request.deeplink.target'}.'"';          $target = ' target="'.$env{'request.deeplink.target'}.'"';
         $crumbtarget = $env{'request.deeplink.target'};          $crumbtarget = $env{'request.deeplink.target'};
Line 5813  sub CSTR_pageheader { Line 6034  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>'.$title.'</b> '
         .'<form name="dirs" method="post" action="'.$formaction.'"'.$target.'>'          .'<form name="dirs" method="post" action="'.$formaction.'"'.$target.'>'
         .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,$crumbtarget,'/priv/'.$udom,undef,undef);          .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,$crumbtarget,'/priv/'.$udom,undef,undef);
   
Line 5834  sub CSTR_pageheader { Line 6055  sub CSTR_pageheader {
     return $output;      return $output;
 }  }
   
   ##############################################
   =pod
   
   =item * &nocodemirror()
   
   Input: None
   
   Returns: 1 if CodeMirror is deactivated based on
            user's preference, or domain default,
            if user indicated use of default.
   
   =cut
   
   sub nocodemirror {
       my $nocodem = $env{'environment.nocodemirror'};
       unless ($nocodem) {
           my %domdefs = &Apache::lonnet::get_domain_defaults($env{'user.domain'});
           if ($domdefs{'nocodemirror'}) {
               $nocodem = 'yes';
           }
       }
       if ($nocodem eq 'yes') {
           return 1;
       }
       return;
   }
   
   ##############################################
   =pod
   
   =item * &permitted_editors()
   
   Input: $uri (optional)
   
   Returns: %editors hash in which keys are editors
            permitted in current Authoring Space,
            or in current course for web pages
            created in a course.
   
            Value for each key is 1. Possible keys
            are: edit, xml, and daxe. 
   
            For a regular Authoring Space, if no specific
            set of editors has been set for the Author
            who owns the Authoring Space, then the
            domain default will be used.  If no domain
            default has been set, then the keys will be
            edit and xml.
   
            For a course author, or for web pages created
            in a course, if no specific set of editors has
            been set for the course, then the domain
            course default will be used. If no domain
            course default has been set, then the keys
            will be edit and xml.
   
   =cut
   
   sub permitted_editors {
       my ($uri) = @_;
       my ($is_author,$is_coauthor,$is_course,$auname,$audom,%editors);
       if ($env{'request.role'} =~ m{^au\./}) {
           $is_author = 1;
       } elsif ($env{'request.role'} =~ m{^(?:ca|aa)\./($match_domain)/($match_username)}) {
           ($audom,$auname) = ($1,$2);
           if (($audom ne '') && ($auname ne '')) {
               if (($env{'user.domain'} eq $audom) &&
                   ($env{'user.name'} eq $auname)) {
                   $is_author = 1;
               } else {
                   $is_coauthor = 1;
               }
           }
       } elsif ($env{'request.course.id'}) {
           my ($cdom,$cnum);
           $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           if (($env{'request.editurl'} =~ m{^/priv/\Q$cdom/$cnum\E/}) ||
               ($env{'request.editurl'} =~ m{^/uploaded/\Q$cdom/$cnum\E/(docs|supplemental)/}) ||
               ($uri =~ m{^/uploaded/\Q$cdom/$cnum\E/(docs|supplemental)/})) {
               $is_course = 1;
           } elsif ($env{'request.editurl'} =~ m{^/priv/($match_domain)/($match_username)/}) {
               ($audom,$auname) = ($1,$2);
           } elsif ($env{'request.uri'} =~ m{^/priv/($match_domain)/($match_username)/}) {
               ($audom,$auname) = ($1,$2);
           } elsif (($uri eq '/daxesave') &&
                    (($env{'form.path'} =~ m{^/daxeopen/priv/\Q$cdom/$cnum\E/}) ||
                     ($env{'form.path'} =~ m{^/daxeopen/uploaded/\Q$cdom/$cnum\E/(docs|supplemental)/}))) {
               $is_course = 1;
           } elsif (($uri eq '/daxesave') &&
                    ($env{'form.path'} =~ m{^/daxeopen/priv/($match_domain)/($match_username)/})) {
               ($audom,$auname) = ($1,$2);
           }
           unless ($is_course) {
               if (($audom ne '') && ($auname ne '')) {
                   if (($env{'user.domain'} eq $audom) &&
                       ($env{'user.name'} eq $auname)) {
                       $is_author = 1;
                   } else {
                       $is_coauthor = 1;
                   }
               }
           }
       }
       if ($is_author) {
           if (exists($env{'environment.editors'})) {
               map { $editors{$_} = 1; } split(/,/,$env{'environment.editors'});
           } else {
               %editors = ( edit => 1,
                            xml => 1,
                          );
           }
       } elsif ($is_coauthor) {
           if (exists($env{"environment.internal.editors./$audom/$auname"})) {
               map { $editors{$_} = 1; } split(/,/,$env{"environment.internal.editors./$audom/$auname"});
           } else {
               %editors = ( edit => 1,
                            xml => 1,
                          );
           }
       } elsif ($is_course) {
           if (exists($env{'course.'.$env{'request.course.id'}.'.internal.crseditors'})) {
               map { $editors{$_} = 1; } split(/,/,$env{'course.'.$env{'request.course.id'}.'.internal.crseditors'});
           } else {
               my %domdefaults = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'});
               if (exists($domdefaults{'crseditors'})) {
                   map { $editors{$_} = 1; } split(/,/,$domdefaults{'crseditors'});
               } else {
                   %editors = ( edit => 1,
                                xml => 1,
                              );
               }
           }
       } else {
           %editors = ( edit => 1,
                        xml => 1,
                      );
       }
       return %editors;
   }
   
 ###############################################  ###############################################
 ###############################################  ###############################################
   
Line 6076  sub bodytag { Line 6438  sub bodytag {
         $bodytag .= Apache::lonhtmlcommon::scripttag(          $bodytag .= Apache::lonhtmlcommon::scripttag(
             Apache::lonmenu::utilityfunctions($httphost), 'start');              Apache::lonmenu::utilityfunctions($httphost), 'start');
   
           my $collapsible;
           if ($args->{'collapsible_header'} ne '') {
               $collapsible = 1;
               my ($menustate,$tiptext,$divclass);
               if ($args->{'start_collapsed'}) {
                   $menustate = 'collapsed';
                   $tiptext = 'display';
                   $divclass = 'hidden';
               } else {
                   $menustate = 'expanded';
                   $tiptext = 'hide';
                   $divclass = 'shown';
               }
               my $alttext = &mt('menu state: '.$menustate);
               my $tooltip = &mt($tiptext.' standard menus');
               $bodytag .= <<"END";
   <div id="LC_expandingContainer" style="display:inline;">
   <div id="LC_collapsible" class="LC_collapse_trigger" style="position: absolute;top: -5px;left: 0px; z-index:101; display:inline;">
   <a href="#" style="text-decoration:none;"><img class="LC_collapsible_indicator" alt="$alttext" title="$tooltip" src="/res/adm/pages/$menustate.png" style="border:0;margin:0;padding:0;max-width:100%;height:auto" /></a></div>
   <div class="LC_menus_content $divclass">
   END
           }
         unless ($args->{'no_primary_menu'}) {          unless ($args->{'no_primary_menu'}) {
             my ($left,$right) = Apache::lonmenu::primary_menu($crstype,$ltimenu,$menucoll,$menuref,              my ($left,$right) = Apache::lonmenu::primary_menu($crstype,$ltimenu,$menucoll,$menuref,
                                                               $args->{'links_disabled'},                                                                $args->{'links_disabled'},
                                                               $args->{'links_target'});                                                                $args->{'links_target'},
                                                                 $collapsible);
             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>|;
Line 6141  sub bodytag { Line 6526  sub bodytag {
             $bodytag .= '<hr style="clear:both" />';              $bodytag .= '<hr style="clear:both" />';
             $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');               $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); 
         }          }
           if ($args->{'collapsible_header'} ne '') {
               $bodytag .= $args->{'collapsible_header'}.
                           '<div id="LC_collapsible_separator"></div>'.
                           '</div></div>';
           }
         return $bodytag;          return $bodytag;
     }      }
   
Line 6302  ENDJS Line 6691  ENDJS
         $endbodytag;          $endbodytag;
         }          }
     }      }
       if ((ref($args) eq 'HASH') && ($args->{'dashjs'})) {
           $endbodytag = &Apache::lonhtmlcommon::dash_to_minus_js().$endbodytag;
       }
     return $endbodytag;      return $endbodytag;
 }  }
   
Line 6386  form, .inline { Line 6778  form, .inline {
   display: inline;    display: inline;
 }  }
   
   .LC_menus_content.shown{
     display: block;
   }
   
   .LC_menus_content.hidden {
     display: none;
   }
   
 .LC_right {  .LC_right {
   text-align:right;    text-align:right;
 }  }
Line 6406  form, .inline { Line 6806  form, .inline {
   width:400px;    width:400px;
 }  }
   
   #LC_collapsible_separator {
       border: 1px solid black;
       width: 99.9%;
       height: 0px;
   }
   
 .LC_iframecontainer {  .LC_iframecontainer {
     width: 98%;      width: 98%;
     margin: 0;      margin: 0;
Line 7601  fieldset { Line 8007  fieldset {
   /* overflow: hidden; */    /* overflow: hidden; */
 }  }
   
   fieldset#LC_selectuser {
       margin: 0;
       padding: 0;
   }
   
 article.geogebraweb div {  article.geogebraweb div {
     margin: 0;      margin: 0;
 }  }
Line 8144  a#LC_content_toolbar_edittoplevel { Line 8555  a#LC_content_toolbar_edittoplevel {
   background-image:url(/res/adm/pages/edittoplevel.gif);    background-image:url(/res/adm/pages/edittoplevel.gif);
 }  }
   
   a#LC_content_toolbar_printout {
     background-image:url(/res/adm/pages/printout.gif);
   }
   
 ul#LC_toolbar li a:hover {  ul#LC_toolbar li a:hover {
   background-position: bottom center;    background-position: bottom center;
 }  }
Line 8282  pre.LC_wordwrap { Line 8697  pre.LC_wordwrap {
 }  }
   
 /*  /*
     styles used for response display
   */
   div.LC_radiofoil, div.LC_rankfoil {
     margin: .5em 0em .5em 0em;
   }
   table.LC_itemgroup {
     margin-top: 1em;
   }
   
   /*
   styles used by TTH when "Default set of options to pass to tth/m    styles used by TTH when "Default set of options to pass to tth/m
   when converting TeX" in course settings has been set    when converting TeX" in course settings has been set
   
Line 8302  span.roman {font-family: serif; font-sty Line 8727  span.roman {font-family: serif; font-sty
 span.overacc2 {position: relative;  left: .8em; top: -1.2ex;}  span.overacc2 {position: relative;  left: .8em; top: -1.2ex;}
 span.overacc1 {position: relative;  left: .6em; top: -1.2ex;}  span.overacc1 {position: relative;  left: .6em; top: -1.2ex;}
   
   /*
     sections with roles, for content only
   */
   section[class^="role-"] {
     padding-left: 10px;
     padding-right: 5px;
     margin-top: 8px;
     margin-bottom: 8px;
     border: 1px solid #2A4;
     border-radius: 5px;
     box-shadow: 0px 1px 1px #BBB;
   }
   section[class^="role-"]>h1 {
     position: relative;
     margin: 0px;
     padding-top: 10px;
     padding-left: 40px;
   }
   section[class^="role-"]>h1:before {
     position: absolute;
     left: -5px;
     top: 5px;
   }
   section.role-activity>h1:before {
     content:url('/adm/daxe/images/section_icons/activity.png');
   }
   section.role-advice>h1:before {
     content:url('/adm/daxe/images/section_icons/advice.png');
   }
   section.role-bibliography>h1:before {
     content:url('/adm/daxe/images/section_icons/bibliography.png');
   }
   section.role-citation>h1:before {
     content:url('/adm/daxe/images/section_icons/citation.png');
   }
   section.role-conclusion>h1:before {
     content:url('/adm/daxe/images/section_icons/conclusion.png');
   }
   section.role-definition>h1:before {
     content:url('/adm/daxe/images/section_icons/definition.png');
   }
   section.role-demonstration>h1:before {
     content:url('/adm/daxe/images/section_icons/demonstration.png');
   }
   section.role-example>h1:before {
     content:url('/adm/daxe/images/section_icons/example.png');
   }
   section.role-explanation>h1:before {
     content:url('/adm/daxe/images/section_icons/explanation.png');
   }
   section.role-introduction>h1:before {
     content:url('/adm/daxe/images/section_icons/introduction.png');
   }
   section.role-method>h1:before {
     content:url('/adm/daxe/images/section_icons/method.png');
   }
   section.role-more_information>h1:before {
     content:url('/adm/daxe/images/section_icons/more_information.png');
   }
   section.role-objectives>h1:before {
     content:url('/adm/daxe/images/section_icons/objectives.png');
   }
   section.role-prerequisites>h1:before {
     content:url('/adm/daxe/images/section_icons/prerequisites.png');
   }
   section.role-remark>h1:before {
     content:url('/adm/daxe/images/section_icons/remark.png');
   }
   section.role-reminder>h1:before {
     content:url('/adm/daxe/images/section_icons/reminder.png');
   }
   section.role-summary>h1:before {
     content:url('/adm/daxe/images/section_icons/summary.png');
   }
   section.role-syntax>h1:before {
     content:url('/adm/daxe/images/section_icons/syntax.png');
   }
   section.role-warning>h1:before {
     content:url('/adm/daxe/images/section_icons/warning.png');
   }
   
 #LC_minitab_header {  #LC_minitab_header {
   float:left;    float:left;
   width:100%;    width:100%;
Line 8361  Inputs: $title - optional title for the Line 8867  Inputs: $title - optional title for the
                                       window (side effect of setting                                        window (side effect of setting
                                       $env{'internal.head.to_opener'} to                                        $env{'internal.head.to_opener'} to
                                       1, if true.                                        1, if true.
                                      5- whether encrypt check should be skipped
             domain         -> force to color decorate a page for a specific              domain         -> force to color decorate a page for a specific
                                domain                                 domain
             function       -> force usage of a specific rolish color scheme              function       -> force usage of a specific rolish color scheme
Line 8423  sub headtag { Line 8930  sub headtag {
         }          }
     }      }
     if (ref($args->{'redirect'})) {      if (ref($args->{'redirect'})) {
  my ($time,$url,$inhibit_continue,$to_opener) = @{$args->{'redirect'}};   my ($time,$url,$inhibit_continue,$to_opener,$skip_enc_check) = @{$args->{'redirect'}};
  $url = &Apache::lonenc::check_encrypt($url);          if (!$skip_enc_check) {
       $url = &Apache::lonenc::check_encrypt($url);
           }
  if (!$inhibit_continue) {   if (!$inhibit_continue) {
     $env{'internal.head.redirect'} = $url;      $env{'internal.head.redirect'} = $url;
  }   }
Line 8596  OFFLOAD Line 9105  OFFLOAD
  $title = 'The LearningOnline Network with CAPA';   $title = 'The LearningOnline Network with CAPA';
     }      }
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }      if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
     $result .= '<title> LON-CAPA '.$title.'</title>'      if ($title =~ /^LON-CAPA\s+/) {
  .'<link rel="stylesheet" type="text/css" href="'.$url.'"';          $result .= '<title> '.$title.'</title>';
       } else {
           $result .= '<title> LON-CAPA '.$title.'</title>';  
       }
       $result .= "\n".'<link rel="stylesheet" type="text/css" href="'.$url.'"';
     if (!$args->{'frameset'}) {      if (!$args->{'frameset'}) {
         $result .= ' /';          $result .= ' /';
     }      }
Line 9106  sub symb_from_tinyurl { Line 9619  sub symb_from_tinyurl {
     }      }
 }  }
   
   sub usable_exttools {
       my %tooltypes;
       if ($env{'request.course.id'}) {
           if ($env{'course.'.$env{'request.course.id'}.'.internal.exttool'}) {
              if ($env{'course.'.$env{'request.course.id'}.'.internal.exttool'} eq 'both') {
                  %tooltypes = (
                                crs => 1,
                                dom => 1,
                               );
              } elsif ($env{'course.'.$env{'request.course.id'}.'.internal.exttool'} eq 'crs') {
                  $tooltypes{'crs'} = 1;
              } elsif ($env{'course.'.$env{'request.course.id'}.'.internal.exttool'} eq 'dom') {
                  $tooltypes{'dom'} = 1;
              }
           } else {
               my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
               my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
               my $crstype = lc($env{'course.'.$env{'request.course.id'}.'.type'});
               if ($crstype eq '') {
                   $crstype = 'course';
               }
               if ($crstype eq 'course') {
                   if ($env{'course.'.$env{'request.course.id'}.'internal.coursecode'}) {
                       $crstype = 'official';
                   } elsif ($env{'course.'.$env{'request.course.id'}.'.internal.textbook'}) {
                       $crstype = 'textbook';
                   } elsif ($env{'course.'.$env{'request.course.id'}.'.internal.lti'}) {
                       $crstype = 'lti';
                   } else {
                       $crstype = 'unofficial';
                   }
               }
               my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
               if ($domdefaults{$crstype.'domexttool'}) {
                   $tooltypes{'dom'} = 1;
               }
               if ($domdefaults{$crstype.'exttool'}) {
                   $tooltypes{'crs'} = 1;
               }
           }
       }
       return %tooltypes;
   }
   
 sub wishlist_window {  sub wishlist_window {
     return(<<'ENDWISHLIST');      return(<<'ENDWISHLIST');
 <script type="text/javascript">  <script type="text/javascript">
Line 13679  sub process_extracted_files { Line 14236  sub process_extracted_files {
                             my $url = '/uploaded/'.$docudom.'/'.$docuname.'/'.                              my $url = '/uploaded/'.$docudom.'/'.$docuname.'/'.
                                       $docstype.'/'.$mapinner{$outer}.'/'.$newidx.'/'.                                        $docstype.'/'.$mapinner{$outer}.'/'.$newidx.'/'.
                                       $title;                                        $title;
                             if (($outer !~ /\D/) && ($mapinner{$outer} !~ /\D/) && ($newidx !~ /\D/)) {                              if (($outer !~ /\D/) &&
                                   (($mapinner{$outer} eq 'default') || ($mapinner{$outer} !~ /\D/)) &&
                                   ($newidx !~ /\D/)) {
                                 if (!-e "$prefix$dir/$docstype/$mapinner{$outer}") {                                  if (!-e "$prefix$dir/$docstype/$mapinner{$outer}") {
                                     mkdir("$prefix$dir/$docstype/$mapinner{$outer}",0755);                                      mkdir("$prefix$dir/$docstype/$mapinner{$outer}",0755);
                                 }                                  }
Line 15718  sub commit_studentrole { Line 16277  sub commit_studentrole {
                 }                  }
                 $oldsecurl = $uurl;                  $oldsecurl = $uurl;
                 $expire_role_result =                   $expire_role_result = 
                     &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',$now,'','',$context);                      &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',$now,'','','',$context);
                 if ($env{'request.course.sec'} ne '') {                   if ($env{'request.course.sec'} ne '') { 
                     if ($expire_role_result eq 'refused') {                      if ($expire_role_result eq 'refused') {
                         my @roles = ('st');                          my @roles = ('st');
Line 16109  sub construct_course { Line 16668  sub construct_course {
     if ($args->{'crstype'}) {      if ($args->{'crstype'}) {
         $cenv{'type'}=$args->{'crstype'};          $cenv{'type'}=$args->{'crstype'};
     }      }
       if ($args->{'lti'}) {
           $cenv{'internal.lti'}=$args->{'lti'};
       }
     if ($args->{'crsid'}) {      if ($args->{'crsid'}) {
         $cenv{'courseid'}=$args->{'crsid'};          $cenv{'courseid'}=$args->{'crsid'};
     }      }
Line 16130  sub construct_course { Line 16692  sub construct_course {
         $cenv{'internal.defaultcredits'} = $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.
       my @oklcsecs = (); # Used to accumulate LON-CAPA sections for validated institutional sections.
     if ($args->{'crssections'}) {      if ($args->{'crssections'}) {
         $cenv{'internal.sectionnums'} = '';          $cenv{'internal.sectionnums'} = '';
         if ($args->{'crssections'} =~ m/,/) {          if ($args->{'crssections'} =~ m/,/) {
Line 16143  sub construct_course { Line 16706  sub construct_course {
                 my $class = $args->{'crscode'}.$sec;                  my $class = $args->{'crscode'}.$sec;
                 my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$class,$cenv{'internal.courseowner'});                  my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$class,$cenv{'internal.courseowner'});
                 $cenv{'internal.sectionnums'} .= $item.',';                  $cenv{'internal.sectionnums'} .= $item.',';
                 unless ($addcheck eq 'ok') {                  if ($addcheck eq 'ok') {
                       unless (grep(/^\Q$gp\E$/,@oklcsecs)) {
                           push(@oklcsecs,$gp);
                       }
                   } else {
                     push(@badclasses,$class);                      push(@badclasses,$class);
                 }                  }
             }              }
Line 16171  sub construct_course { Line 16738  sub construct_course {
                 my ($xl,$gp) = split/:/,$item;                  my ($xl,$gp) = split/:/,$item;
                 my $addcheck =  &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$xl,$cenv{'internal.courseowner'});                  my $addcheck =  &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$xl,$cenv{'internal.courseowner'});
                 $cenv{'internal.crosslistings'} .= $item.',';                  $cenv{'internal.crosslistings'} .= $item.',';
                 unless ($addcheck eq 'ok') {                  if ($addcheck eq 'ok') {
                       unless (grep(/^\Q$gp\E$/,@oklcsecs)) {
                           push(@oklcsecs,$gp);
                       }
                   } else {
                     push(@badclasses,$xl);                      push(@badclasses,$xl);
                 }                  }
             }              }
Line 16234  sub construct_course { Line 16805  sub construct_course {
     if ($args->{'no_end_date'}) {      if ($args->{'no_end_date'}) {
         $args->{'endaccess'} = 0;          $args->{'endaccess'} = 0;
     }      }
   #  If an official course with institutional sections is created by cloning
   #  an existing course, section-specific hiding of course totals in student's
   #  view of grades as copied from cloned course, will be checked for valid
   #  sections.
       if (($can_clone && $cloneid) &&
           ($cenv{'internal.coursecode'} ne '') &&
           ($cenv{'grading'} eq 'standard') &&
           ($cenv{'hidetotals'} ne '') &&
           ($cenv{'hidetotals'} ne 'all')) {
           my @hidesecs;
           my $deletehidetotals;
           if (@oklcsecs) {
               foreach my $sec (split(/,/,$cenv{'hidetotals'})) {
                   if (grep(/^\Q$sec$/,@oklcsecs)) {
                       push(@hidesecs,$sec);
                   }
               }
               if (@hidesecs) {
                   $cenv{'hidetotals'} = join(',',@hidesecs);
               } else {
                   $deletehidetotals = 1;
               }
           } else {
               $deletehidetotals = 1;
           }
           if ($deletehidetotals) {
               delete($cenv{'hidetotals'});
               &Apache::lonnet::del('environment',['hidetotals'],$$crsudom,$$crsunum);
           }
       }
     $cenv{'internal.autostart'}=$args->{'enrollstart'};      $cenv{'internal.autostart'}=$args->{'enrollstart'};
     $cenv{'internal.autoend'}=$args->{'enrollend'};      $cenv{'internal.autoend'}=$args->{'enrollend'};
     $cenv{'default_enrollment_start_date'}=$args->{'startaccess'};      $cenv{'default_enrollment_start_date'}=$args->{'startaccess'};
Line 16352  sub construct_course { Line 16953  sub construct_course {
 #  #
     unless (($args->{'nonstandard'}) || ($args->{'firstres'} eq 'blank')      unless (($args->{'nonstandard'}) || ($args->{'firstres'} eq 'blank')
     || ($cloneid)) {      || ($cloneid)) {
  use LONCAPA::map;  
  $outcome .= &mt('Setting first resource').': ';   $outcome .= &mt('Setting first resource').': ';
   
  my $map = '/uploaded/'.$$crsudom.'/'.$$crsunum.'/default.sequence';   my $map = '/uploaded/'.$$crsudom.'/'.$$crsunum.'/default.sequence';
Line 16459  sub group_term { Line 17059  sub group_term {
 }  }
   
 sub course_types {  sub course_types {
     my @types = ('official','unofficial','community','textbook');      my @types = ('official','unofficial','community','textbook','lti');
     my %typename = (      my %typename = (
                          official   => 'Official course',                           official   => 'Official course',
                          unofficial => 'Unofficial course',                           unofficial => 'Unofficial course',
                          community  => 'Community',                           community  => 'Community',
                          textbook   => 'Textbook course',                           textbook   => 'Textbook course',
                            lti        => 'LTI provider',
                    );                     );
     return (\@types,\%typename);      return (\@types,\%typename);
 }  }
Line 16571  sub init_user_environment { Line 17172  sub init_user_environment {
   
 # See if old ID present, if so, remove  # See if old ID present, if so, remove
   
     my ($filename,$cookie,$userroles,$firstaccenv,$timerintenv);      my ($filename,$cookie,$userroles,$firstaccenv,$timerintenv,
           $coauthorenv);
     my $now=time;      my $now=time;
   
     if ($public) {      if ($public) {
Line 16636  sub init_user_environment { Line 17238  sub init_user_environment {
           
 # Initialize roles  # Initialize roles
   
  ($userroles,$firstaccenv,$timerintenv) =    ($userroles,$firstaccenv,$timerintenv,$coauthorenv) = 
             &Apache::lonnet::rolesinit($domain,$username,$authhost);              &Apache::lonnet::rolesinit($domain,$username,$authhost);
     }      }
 # ------------------------------------ Check browser type and MathML capability  # ------------------------------------ Check browser type and MathML capability
Line 16715  sub init_user_environment { Line 17317  sub init_user_environment {
             my %is_adv = ( is_adv => $env{'user.adv'} );              my %is_adv = ( is_adv => $env{'user.adv'} );
             my %domdef = &Apache::lonnet::get_domain_defaults($domain);              my %domdef = &Apache::lonnet::get_domain_defaults($domain);
   
             foreach my $tool ('aboutme','blog','webdav','portfolio') {              foreach my $tool ('aboutme','blog','webdav','portfolio','portaccess','timezone') {
                 $userenv{'availabletools.'.$tool} =                   $userenv{'availabletools.'.$tool} =
                     &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',                      &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',
                                                       undef,\%userenv,\%domdef,\%is_adv);                                                        undef,\%userenv,\%domdef,\%is_adv);
             }              }
   
             foreach my $crstype ('official','unofficial','community','textbook') {              foreach my $crstype ('official','unofficial','community','textbook','lti') {
                 $userenv{'canrequest.'.$crstype} =                  $userenv{'canrequest.'.$crstype} =
                     &Apache::lonnet::usertools_access($username,$domain,$crstype,                      &Apache::lonnet::usertools_access($username,$domain,$crstype,
                                                       'reload','requestcourses',                                                        'reload','requestcourses',
                                                       \%userenv,\%domdef,\%is_adv);                                                        \%userenv,\%domdef,\%is_adv);
             }              }
   
               if ((ref($userroles) eq 'HASH') && ($userroles->{'user.author'}) &&
                   (exists($userroles->{"user.role.au./$domain/"}))) {
                   if ($userenv{'authoreditors'}) {
                       $userenv{'editors'} = $userenv{'authoreditors'};
                   } elsif ($domdef{'editors'} ne '') {
                       $userenv{'editors'} = $domdef{'editors'};
                   } else {
                       $userenv{'editors'} = 'edit,xml';
                   }
                   if ($userenv{'authorarchive'}) {
                       $userenv{'canarchive'} = 1;
                   } elsif (($userenv{'authorarchive'} eq '') &&
                            ($domdef{'archive'})) {
                       $userenv{'canarchive'} = 1;
                   }
               }
   
             $userenv{'canrequest.author'} =              $userenv{'canrequest.author'} =
                 &Apache::lonnet::usertools_access($username,$domain,'requestauthor',                  &Apache::lonnet::usertools_access($username,$domain,'requestauthor',
                                                   'reload','requestauthor',                                                    'reload','requestauthor',
Line 16756  sub init_user_environment { Line 17375  sub init_user_environment {
             if (ref($timerintenv) eq 'HASH') {              if (ref($timerintenv) eq 'HASH') {
                 &_add_to_env(\%disk_env,$timerintenv);                  &_add_to_env(\%disk_env,$timerintenv);
             }              }
               if (ref($coauthorenv) eq 'HASH') {
                   if (keys(%{$coauthorenv})) {
                       &_add_to_env(\%disk_env,$coauthorenv);
                   }
               }
     if (ref($args->{'extra_env'})) {      if (ref($args->{'extra_env'})) {
  &_add_to_env(\%disk_env,$args->{'extra_env'});   &_add_to_env(\%disk_env,$args->{'extra_env'});
     }      }
Line 17548  sub needs_coursereinit { Line 18172  sub needs_coursereinit {
         if ($blocked) {          if ($blocked) {
             return ();              return ();
         }          }
         my $lastchange = &Apache::lonnet::get_coursechange($cdom,$cnum);          my $update;
         if ($lastchange > $env{'request.course.tied'}) {          my $lastmainchange = &Apache::lonnet::get_coursechange($cdom,$cnum);
             my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');          my $lastsuppchange = &Apache::lonnet::get_suppchange($cdom,$cnum);
             if ($curr_reqd_hash{'internal.releaserequired'} ne '') {          if ($lastmainchange > $env{'request.course.tied'}) {
                 my $required = $env{'course.'.$cdom.'_'.$cnum.'.internal.releaserequired'};              my ($needswitch,$switchwarning,$switchserver) = &switch_for_update($loncaparev,$cdom,$cnum);
                 if ($curr_reqd_hash{'internal.releaserequired'} ne $required) {              if ($needswitch) {
                     &Apache::lonnet::appenv({'course.'.$cdom.'_'.$cnum.'.internal.releaserequired' =>                  return ('switch',$switchwarning,$switchserver);
                                              $curr_reqd_hash{'internal.releaserequired'}});              }
                     my ($switchserver,$switchwarning) =              $update = 'main';
                         &check_release_required($loncaparev,$cdom.'_'.$cnum,$env{'request.role'},          }
                                                 $curr_reqd_hash{'internal.releaserequired'});          if ($lastsuppchange > $env{'request.course.suppupdated'}) {
                     if ($switchwarning ne '' || $switchserver ne '') {              if ($update) {
                         return ('switch',$switchwarning,$switchserver);                  $update = 'both';
                     }              } else {
                   my ($needswitch,$switchwarning,$switchserver) = &switch_for_update($loncaparev,$cdom,$cnum);
                   if ($needswitch) {
                       return ('switch',$switchwarning,$switchserver);
                   } else {
                       $update = 'supp';
                 }                  }
             }              }
             return ('update');              return ($update);
           }
       }
       return ();
   }
   
   sub switch_for_update {
       my ($loncaparev,$cdom,$cnum) = @_;
       my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');
       if ($curr_reqd_hash{'internal.releaserequired'} ne '') {
           my $required = $env{'course.'.$cdom.'_'.$cnum.'.internal.releaserequired'};
           if ($curr_reqd_hash{'internal.releaserequired'} ne $required) {
               &Apache::lonnet::appenv({'course.'.$cdom.'_'.$cnum.'.internal.releaserequired' =>
                                       $curr_reqd_hash{'internal.releaserequired'}});
               my ($switchserver,$switchwarning) =
                   &check_release_required($loncaparev,$cdom.'_'.$cnum,$env{'request.role'},
                                           $curr_reqd_hash{'internal.releaserequired'});
               if ($switchwarning ne '' || $switchserver ne '') {
                   return ('switch',$switchwarning,$switchserver);
               }
         }          }
     }      }
     return ();      return ();
Line 17647  sub parse_supplemental_title { Line 18295  sub parse_supplemental_title {
         my $name =  &plainname($uname,$udom);          my $name =  &plainname($uname,$udom);
         $name = &HTML::Entities::encode($name,'"<>&\'');          $name = &HTML::Entities::encode($name,'"<>&\'');
         $renametitle = &HTML::Entities::encode($renametitle,'"<>&\'');          $renametitle = &HTML::Entities::encode($renametitle,'"<>&\'');
         $title='<i>'.&Apache::lonlocal::locallocaltime($time).'</i> '.          $title='<i>'.&Apache::lonlocal::locallocaltime($time).'</i> '.$name;
             $name.': <br />'.$foldertitle;          if ($foldertitle ne '') {
               $title .= ': <br />'.$foldertitle;
           }
     }      }
     if (wantarray) {      if (wantarray) {
         return ($title,$foldertitle,$renametitle);          return ($title,$foldertitle,$renametitle);
Line 17656  sub parse_supplemental_title { Line 18306  sub parse_supplemental_title {
     return $title;      return $title;
 }  }
   
   sub get_supplemental {
       my ($cnum,$cdom,$ignorecache,$possdel)=@_;
       my $hashid=$cnum.':'.$cdom;
       my ($supplemental,$cached,$set_httprefs);
       unless ($ignorecache) {
           ($supplemental,$cached) = &Apache::lonnet::is_cached_new('supplemental',$hashid);
       }
       unless (defined($cached)) {
           my $chome=&Apache::lonnet::homeserver($cnum,$cdom);
           unless ($chome eq 'no_host') {
               my @order = @LONCAPA::map::order;
               my @resources = @LONCAPA::map::resources;
               my @resparms = @LONCAPA::map::resparms;
               my @zombies = @LONCAPA::map::zombies;
               my ($errors,%ids,%hidden);
               $errors =
                   &recurse_supplemental($cnum,$cdom,'supplemental.sequence',
                                         $errors,$possdel,\%ids,\%hidden);
               @LONCAPA::map::order = @order;
               @LONCAPA::map::resources = @resources;
               @LONCAPA::map::resparms = @resparms;
               @LONCAPA::map::zombies = @zombies;
               $set_httprefs = 1;
               if ($env{'request.course.id'} eq $cdom.'_'.$cnum) {
                   &Apache::lonnet::appenv({'request.course.suppupdated' => time});
               }
               $supplemental = {
                                  ids => \%ids,
                                  hidden => \%hidden,
                               };
               &Apache::lonnet::do_cache_new('supplemental',$hashid,$supplemental,600);
           }
       }
       return ($supplemental,$set_httprefs);
   }
   
 sub recurse_supplemental {  sub recurse_supplemental {
     my ($cnum,$cdom,$suppmap,$numfiles,$errors) = @_;      my ($cnum,$cdom,$suppmap,$errors,$possdel,$suppids,$hiddensupp,$hidden) = @_;
     if ($suppmap) {      if (($suppmap) && (ref($suppids) eq 'HASH') && (ref($hiddensupp) eq 'HASH')) {
           my $mapnum;
           if ($suppmap eq 'supplemental.sequence') {
               $mapnum = 0;
           } else {
               ($mapnum) = ($suppmap =~ /^supplemental_(\d+)\.sequence$/);
           }
         my ($errtext,$fatal) = &LONCAPA::map::mapread('/uploaded/'.$cdom.'/'.$cnum.'/'.$suppmap);          my ($errtext,$fatal) = &LONCAPA::map::mapread('/uploaded/'.$cdom.'/'.$cnum.'/'.$suppmap);
         if ($fatal) {          if ($fatal) {
             $errors ++;              $errors ++;
         } else {          } else {
             if ($#LONCAPA::map::resources > 0) {              my @order = @LONCAPA::map::order;
                 foreach my $res (@LONCAPA::map::resources) {              if (@order > 0) {
                     my ($title,$src,$ext,$type,$status)=split(/\:/,$res);                  my @resources = @LONCAPA::map::resources;
                   my @resparms = @LONCAPA::map::resparms;
                   foreach my $idx (@order) {
                       my ($title,$src,$ext,$type,$status)=split(/\:/,$resources[$idx]);
                     if (($src ne '') && ($status eq 'res')) {                      if (($src ne '') && ($status eq 'res')) {
                           my $id = $mapnum.':'.$idx;
                           push(@{$suppids->{$src}},$id);
                           if (($hidden) || (&get_supp_parameter($resparms[$idx],'parameter_hiddenresource') =~ /^yes/i)) {
                               $hiddensupp->{$id} = 1;
                           }
                         if ($src =~ m{^\Q/uploaded/$cdom/$cnum/\E(supplemental_\d+\.sequence)$}) {                          if ($src =~ m{^\Q/uploaded/$cdom/$cnum/\E(supplemental_\d+\.sequence)$}) {
                             ($numfiles,$errors) = &recurse_supplemental($cnum,$cdom,$1,$numfiles,$errors);                              $errors = &recurse_supplemental($cnum,$cdom,$1,$errors,$possdel,$suppids,
                                                               $hiddensupp,$hiddensupp->{$id});
                         } else {                          } else {
                             $numfiles ++;                              my $allowed;
                               if (($env{'request.role.adv'}) || (!$hiddensupp->{$id})) {
                                   $allowed = 1;
                               } elsif ($possdel) {
                                   foreach my $item (@{$suppids->{$src}}) {
                                       next if ($item eq $id);
                                       unless ($hiddensupp->{$item}) {
                                          $allowed = 1;
                                          last;
                                       }
                                   }
                                   if ((!$allowed) && (exists($env{'httpref.'.$src}))) {
                                       &Apache::lonnet::delenv('httpref.'.$src);
                                   }
                               }
                               if ($allowed && (!exists($env{'httpref.'.$src}))) {
                                   &Apache::lonnet::allowuploaded('/adm/coursedoc',$src);
                               }
                         }                          }
                     }                      }
                 }                  }
             }              }
         }          }
     }      }
     return ($numfiles,$errors);      return $errors;
   }
   
   sub set_supp_httprefs {
       my ($cnum,$cdom,$supplemental,$possdel) = @_;
       if (ref($supplemental) eq 'HASH') {
           if ((ref($supplemental->{'ids'}) eq 'HASH') && (ref($supplemental->{'hidden'}) eq 'HASH')) {
               foreach my $src (keys(%{$supplemental->{'ids'}})) {
                   next if ($src =~ /\.sequence$/);
                   if (ref($supplemental->{'ids'}->{$src}) eq 'ARRAY') {
                       my $allowed;
                       if ($env{'request.role.adv'}) {
                           $allowed = 1;
                       } else {
                           foreach my $id (@{$supplemental->{'ids'}->{$src}}) {
                               unless ($supplemental->{'hidden'}->{$id}) {
                                   $allowed = 1;
                                   last;
                               }
                           }
                       }
                       if (exists($env{'httpref.'.$src})) {
                           if ($possdel) {
                               unless ($allowed) {
                                   &Apache::lonnet::delenv('httpref.'.$src);
                               }
                           }
                       } elsif ($allowed) {
                           &Apache::lonnet::allowuploaded('/adm/coursedoc',$src);
                       }
                   }
               }
               if ($env{'request.course.id'} eq $cdom.'_'.$cnum) {
                   &Apache::lonnet::appenv({'request.course.suppupdated' => time});
               }
           }
       }
   }
   
   sub get_supp_parameter {
       my ($resparm,$name)=@_;
       return if ($resparm eq '');
       my $value=undef;
       my $ptype=undef;
       foreach (split('&&&',$resparm)) {
           my ($thistype,$thisname,$thisvalue)=split('___',$_);
           if ($thisname eq $name) {
               $value=$thisvalue;
               $ptype=$thistype;
           }
       }
       return $value;
 }  }
   
 sub symb_to_docspath {  sub symb_to_docspath {
Line 17750  sub symb_to_docspath { Line 18519  sub symb_to_docspath {
     return $path;      return $path;
 }  }
   
   sub validate_folderpath {
       my ($supplementalflag,$allowed,$coursenum,$coursedom) = @_;
       if ($env{'form.folderpath'} ne '') {
           my @items = split(/\&/,$env{'form.folderpath'});
           my ($badpath,$changed,$got_supp,$supppath,%supphidden,%suppids);
           for (my $i=0; $i<@items; $i++) {
               my $odd = $i%2;
               if (($odd) && (!$supplementalflag) && ($items[$i] !~ /^[^:]*:(|\d+):(|1):(|1):(|1):(|1)$/)) {
                   $badpath = 1;
               } elsif ($odd && $supplementalflag) {
                   my $idx = $i-1;
                   if ($items[$i] =~ /^([^:]*)::(|1):::$/) {
                       my $esc_name = $1;
                       if ((!$allowed) || ($items[$idx] eq 'supplemental')) {
                           $supppath .= '&'.$esc_name;
                           $changed = 1;
                       } else {
                           $supppath .= '&'.$items[$i];
                       }
                   } elsif (($allowed) && ($items[$idx] ne 'supplemental')) {
                       $changed = 1;
                       my $is_hidden;
                       unless ($got_supp) {
                           my ($supplemental) = &get_supplemental($coursenum,$coursedom);
                           if (ref($supplemental) eq 'HASH') {
                               if (ref($supplemental->{'hidden'}) eq 'HASH') {
                                   %supphidden = %{$supplemental->{'hidden'}};
                               }
                               if (ref($supplemental->{'ids'}) eq 'HASH') {
                                   %suppids = %{$supplemental->{'ids'}};
                               }
                           }
                           $got_supp = 1;
                       }
                       if (ref($suppids{"/uploaded/$coursedom/$coursenum/$items[$idx].sequence"}) eq 'ARRAY') {
                           my $mapid = $suppids{"/uploaded/$coursedom/$coursenum/$items[$idx].sequence"}->[0];
                           if ($supphidden{$mapid}) {
                               $is_hidden = 1;
                           }
                       }
                       $supppath .= '&'.$items[$i].'::'.$is_hidden.':::';
                   } else {
                       $supppath .= '&'.$items[$i];
                   }
               } elsif ((!$odd) && ($items[$i] !~ /^(default|supplemental)(|_\d+)$/)) {
                   $badpath = 1;
               } elsif ($supplementalflag) {
                   $supppath .= '&'.$items[$i];
               }
               last if ($badpath);
           }
           if ($badpath) {
               delete($env{'form.folderpath'});
           } elsif ($changed && $supplementalflag) {
               $supppath =~ s/^\&//;
               $env{'form.folderpath'} = $supppath;
           }
       }
       return;
   }
   
 sub captcha_display {  sub captcha_display {
     my ($context,$lonhost,$defdom) = @_;      my ($context,$lonhost,$defdom) = @_;
     my ($output,$error);      my ($output,$error);
Line 17872  sub create_captcha { Line 18702  sub create_captcha {
             $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n".              $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n".
                       '<span class="LC_nobreak">'.                        '<span class="LC_nobreak">'.
                       &mt('Type in the letters/numbers shown below').'&nbsp;'.                        &mt('Type in the letters/numbers shown below').'&nbsp;'.
                       '<input type="text" size="5" name="code" value="" autocomplete="off" />'.                        '<input type="text" size="5" name="code" value="" autocomplete="new-password" />'.
                       '</span><br />'.                        '</span><br />'.
                       '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" alt="captcha" />';                        '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" alt="captcha" />';
             last;              last;

Removed from v.1.1075.2.161.2.9  
changed lines
  Added in v.1.1075.2.161.2.28


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