Diff for /loncom/auth/lonroles.pm between versions 1.346 and 1.353

version 1.346, 2021/04/19 20:09:07 version 1.353, 2021/11/03 01:04:02
Line 148  use HTML::Entities; Line 148  use HTML::Entities;
 my $registered_cleanup;  my $registered_cleanup;
 my $rosterupdates;  my $rosterupdates;
   
   sub start_loading_course {
       my ($r,$title) = @_;
       &Apache::loncommon::content_type($r,'text/html');
       &Apache::loncommon::no_cache($r);
       $r->send_http_header;
       my $swinfo=&Apache::lonmenu::rawconfig();
       # Breadcrumbs
       my $brcrum = [{'href' => '',
                      'text' => $title},];
       my $start_page = &Apache::loncommon::start_page($title,undef,
                                                       {'bread_crumbs' => $brcrum,});
       $r->print(<<ENDREDIR);
   $start_page
   <script type="text/javascript">
   // <![CDATA[
   $swinfo
   // ]]>
   </script>
   ENDREDIR
       return;
   }
   
   sub finish_loading_course {
       my ($r,$msg,$url) = @_;
   #FIXME add continue link, and add jquery to enable menu links when page is loaded
       my $link;
       my $end_page = &Apache::loncommon::end_page();
       my $js_url = &js_escape($url);
       $r->print(<<END);
   $msg
   <script type="text/javascript">
   // <![CDATA[
   \$(document).ready(function() {
       var url = "$js_url";
       \$(location).attr('href',url);
   });
   </script>
   $link
   $end_page
   END
       return;
   }
   
 sub redirect_user {  sub redirect_user {
     my ($r,$title,$url,$msg) = @_;      my ($r,$title,$url,$msg) = @_;
     $msg = $title if (! defined($msg));      $msg = $title if (! defined($msg));
Line 182  ENDREDIR Line 225  ENDREDIR
   
 sub error_page {  sub error_page {
     my ($r,$error,$dest)=@_;      my ($r,$error,$dest)=@_;
     &Apache::loncommon::content_type($r,'text/html');      my %lt = &Apache::lonlocal::texthash(
     &Apache::loncommon::no_cache($r);          pdc => 'Problems during Course Initialization',
     $r->send_http_header;          tfp => 'The following problems occurred:',
     return OK if $r->header_only;          con => 'Continue',
     # Breadcrumbs  
     my $brcrum = [{'href' => $dest,  
                    'text' => 'Problems during Course Initialization'},];  
     $r->print(&Apache::loncommon::start_page('Problems during Course Initialization',  
                                              undef,  
                                              {'bread_crumbs' => $brcrum,})  
     );      );
     $r->print(      my $end_page = &Apache::loncommon::end_page();
         '<script type="text/javascript">'.      $dest = &HTML::Entities::encode($dest,'"<>&');
         '// <![CDATA['.      $r->print(<<END);
         &Apache::lonmenu::rawconfig().  <h3>$lt{'pdc'}</h3>
         '// ]]>'.  <p class="LC_error">$lt{'tfp'}
         '</script>'.  <br />
       '<p class="LC_error">'.&mt('The following problems occurred:').  $error
           '<br />'.  </p><br /><a href="$dest">$lt{'con'}</a>
       $error.  $end_page
       '</p><br /><a href="'.$dest.'">'.&mt('Continue').'</a>'  END
     );      return;
     $r->print(&Apache::loncommon::end_page());  
 }  }
   
 sub handler {  sub handler {
Line 230  sub handler { Line 266  sub handler {
         $update = $then;          $update = $then;
     }      }
   
       my $norolelist;
       if (($env{'request.course.id'}) && ($env{'request.deeplink.login'})) {
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
           my $deeplink_symb = &Apache::loncommon::deeplink_login_symb($cnum,$cdom);
           if ($deeplink_symb) {
               my ($menucoll,$deeplinkmenu,$menuref) = &Apache::loncommon::menucoll_in_effect();
               if (ref($menuref) eq 'HASH') {
                   unless (($menuref->{'role'}) || ($env{'request.role.adv'})) {
                       foreach my $envkey (keys(%env)) {
                           next unless ($envkey =~ /^form\./);
                           if ($envkey =~ m{\./($match_domain)/($match_courseid)(?:/(\w+)|$)}) {
                               unless (($1 eq $cdom) && ($2 eq $cnum)) {
                                   delete($env{$envkey});
                               }
                           }
                       }
                       if ($env{'form.selectrole'}) {
                           if ($env{'form.switchrole'} =~ m{\./($match_domain)/($match_courseid)(?:/(\w+)|$)}) {
                               unless (($1 eq $cdom) && ($2 eq $cnum)) {
                                   delete($env{'form.selectrole'});
                                   delete($env{'form.switchrole'});
                               }
                           } elsif ($env{'form.newrole'} =~ m{\./($match_domain)/($match_courseid)(?:/(\w+)|$)}) {
                               unless (($1 eq $cdom) && ($2 eq $cnum)) {
                                   delete($env{'form.selectrole'});
                                   delete($env{'form.newrole'});
                               }
                           }
                       }
                       $norolelist = 1;
                   }
               }
           }
       }
   
     $registered_cleanup=0;      $registered_cleanup=0;
     @{$rosterupdates}=();      @{$rosterupdates}=();
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
   
 # -------------------------------------------------- Check if setting hot list   # -------------------------------------------------- Check if setting hot list
     my $hotlist;      my $hotlist;
     if ($env{'form.action'} eq 'verify_and_change_rolespref') {      if ($env{'form.action'} eq 'verify_and_change_rolespref') {
         $hotlist = &Apache::lonpreferences::verify_and_change_rolespref($r);          $hotlist = &Apache::lonpreferences::verify_and_change_rolespref($r);
Line 591  ENDENTERKEY Line 664  ENDENTERKEY
                                 }                                  }
                             }                              }
                         }                          }
                         my ($msg,$blockcrit,$critmsg_check);                           my $crstype = &Apache::loncommon::course_type($cdom.'_'.$cnum);
                           $crstype = lc($crstype);
                           my $preamble = '<div id="LC_update_'.$cdom.'_'.$cnum.'" class="LC_info">'.
                                          '<br />'.
                                          &mt("Please be patient while your $crstype loads").
                                          '<br /></div>'.
                                          '<div style="padding:0;clear:both;margin:0;border:0"></div>';
                           my $closure = <<ENDCLOSE;
   <script type="text/javascript">
   // <![CDATA[
   \$("#LC_update_${cdom}_${cnum}").hide('slow');
   // ]]>
   </script>
   ENDCLOSE
                           my $title = &mt("Loading $crstype");
                           &start_loading_course($r,$title);
                           my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($r,undef,$preamble);
                           &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,&mt('Loading ...'));
                           $r->rflush();
                           my ($msg,$blockcrit,$critmsg_check);
                         $critmsg_check = 1;                          $critmsg_check = 1;
                         $blockcrit = &Apache::loncommon::blocking_status('alert',$cnum,$cdom,undef,1);                          $blockcrit = &Apache::loncommon::blocking_status('alert',$cnum,$cdom,undef,1);
                         if ($blockcrit) {                          if ($blockcrit) {
Line 604  ENDENTERKEY Line 696  ENDENTERKEY
                                 $critmsg_check = 0;                                  $critmsg_check = 0;
                             }                              }
                         }                          }
  my ($furl,$ferr)=                          my ($furl,$ferr)=
     &Apache::lonuserstate::readmap($cdom.'/'.$cnum,$critmsg_check);                              &Apache::lonuserstate::readmap($cdom.'/'.$cnum,$critmsg_check);
                         unless ($ferr) {                          &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,&mt('Finished!'));
                           &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                           $r->print($closure);
                           $r->rflush();
                           if ($ferr) {
                               $furl = '/adm/roles?tryagain=1';
                           } else {
                             &Apache::lonnet::appenv({'request.course.timechecked'=>$now});                              &Apache::lonnet::appenv({'request.course.timechecked'=>$now});
                             unless (($env{'form.switchrole'}) ||                               unless (($env{'form.switchrole'}) || 
                                     ($env{"environment.internal.$cdom.$cnum.$role.adhoc"})) {                                      ($env{"environment.internal.$cdom.$cnum.$role.adhoc"})) {
Line 662  ENDENTERKEY Line 760  ENDENTERKEY
                             }                              }
     if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; }      if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; }
     &Apache::lonnet::appenv({'request.role.adv'=>$tadv});      &Apache::lonnet::appenv({'request.role.adv'=>$tadv});
                               if ($ferr) {
                                   if ($env{'form.orgurl'}) {
                                       $furl .= '&orgurl='.&HTML::Entities::encode($env{'form.orgurl'},'<>&"');
                                   }
                                   if ($env{'form.symb'}) {
                                       $furl .= '&symb='.&HTML::Entities::encode($env{'form.symb'},'<>&"');
                                   }
                               }
                             if (($ferr) && ($tadv)) {                              if (($ferr) && ($tadv)) {
  &error_page($r,$ferr,$dest);   &error_page($r,$ferr,$furl);
     } else {      } else {
                                 if ($env{'request.course.id'} eq $cdom.'_'.$cnum) {                                  if ($env{'request.course.id'} eq $cdom.'_'.$cnum) {
                                     if (($env{'form.orgurl'} ne '') && ($env{'form.symb'} ne '')) {                                      if (($env{'form.orgurl'} ne '') && ($env{'form.symb'} ne '')) {
                                         unless (&Apache::lonnet::symbverify($env{'form.symb'},$env{'form.orgurl'}) {                                          unless (&Apache::lonnet::symbverify($env{'form.symb'},$env{'form.orgurl'})) {
                                             $dest=$env{'form.orgurl'};                                              $dest=$env{'form.orgurl'};
                                         }                                          }
                                     }                                       } 
Line 679  ENDENTERKEY Line 785  ENDENTERKEY
                                                                                        $cdom.'_'.$cnum);                                                                                         $cdom.'_'.$cnum);
                                     }                                      }
                                 }                                  }
                                 if (($env{'request.lti.login'}) &&                                  if ($ferr) {
                                     ($env{'request.lti.rosterid'} || $env{'request.lti.passbackid'})) {                                      if (!$env{'request.course.id'}) {
                                     &process_lti($r,$cdom,$cnum);                                          &Apache::lonnet::appenv(
                                              {"request.course.id"  => $cdom.'_'.$cnum});
                                           $r->print('<p class="LC_error">'.
                                                     &mt('Could not initialize [_1] at this time.',
                                                         $env{'course.'.$cdom.'_'.$cnum.'.description'}).
                                                     '</p>'.
                                                     '<p><a href="'.$furl.'">'.
                                                     &mt('Please try again.').'</a></p>'.
                                                     &Apache::loncommon::end_page());
                                       }
                                   } else {
                                       if (($env{'request.lti.login'}) &&
                                           ($env{'request.lti.rosterid'} || $env{'request.lti.passbackid'})) {
                                           &process_lti($r,$cdom,$cnum);
                                       }
                                       $msg = '<p>'.&mt('Entering [_1] ...',
                                                        $env{'course.'.$cdom.'_'.$cnum.'.description'}).
                                              '</p>';
                                       &finish_loading_course($r,$msg,$dest);
                                 }                                  }
  $r->internal_redirect($dest);  
     }      }
                               $r->rflush();
     return OK;      return OK;
  } else {   } else {
     if (!$env{'request.course.id'}) {      if (!$env{'request.course.id'}) {
  &Apache::lonnet::appenv(   &Apache::lonnet::appenv(
       {"request.course.id"  => $cdom.'_'.$cnum});        {"request.course.id"  => $cdom.'_'.$cnum});
  $furl='/adm/roles?tryagain=1';  
                 $msg='<p><span class="LC_error">'  
                     .&mt('Could not initialize [_1] at this time.',  
                          $env{'course.'.$cdom.'_'.$cnum.'.description'})  
                     .'</span></p>'  
                     .'<p>'.&mt('Please try again.').'</p>'  
                     .'<p>'.$ferr.'</p>';  
     }      }
     if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; }      if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; }
     &Apache::lonnet::appenv({'request.role.adv'=>$tadv});      &Apache::lonnet::appenv({'request.role.adv'=>$tadv});
       if ($ferr) {
     if (($ferr) && ($tadv)) {                                  if ($tadv) {
  &error_page($r,$ferr,$furl);      &error_page($r,$ferr,$furl);
                                   } else {
                                       $r->print('<p class="LC_error">'.
                                                 &mt('Could not initialize [_1] at this time.',
                                                     $env{'course.'.$cdom.'_'.$cnum.'.description'}).
                                                 '</p>'.
                                                 '<p><a href="'.$furl.'">'.&mt('Please try again.').'</a></p>'.
                                                 &Apache::loncommon::end_page());
                                   }
     } else {      } else {
                                 if (($env{'request.lti.login'}) &&                                  if (($env{'request.lti.login'}) &&
                                     ($env{'request.lti.rosterid'} || $env{'request.lti.passbackid'})) {                                      ($env{'request.lti.rosterid'} || $env{'request.lti.passbackid'})) {
Line 720  ENDENTERKEY Line 845  ENDENTERKEY
                                         my ($score,$incomplete) =                                           my ($score,$incomplete) = 
                                             &Apache::lonplacementtest::check_completion(undef,undef,1);                                              &Apache::lonplacementtest::check_completion(undef,undef,1);
                                         if (($incomplete) && ($incomplete < 100)) {                                          if (($incomplete) && ($incomplete < 100)) {
                                             &redirect_user($r, &mt('Entering [_1]',                                              $msg = '<p>'.&mt('Entering [_1] ...',
                                                           $env{'course.'.$cdom.'_'.$cnum.'.description'}),                                                               $env{'course.'.$cdom.'_'.$cnum.'.description'}).
                                                           '/adm/placement', $msg);                                                     '</p>';
                                               &finish_loading_course($r,$msg,'/adm/placement');
                                               $r->rflush();
                                             return OK;                                              return OK;
                                         }                                          }
                                     }                                      }
Line 741  ENDENTERKEY Line 868  ENDENTERKEY
                                             if (($dest =~ m{^\Q/public/$cdom/$cnum/syllabus\E.*(\?|\&)usehttp=1}) ||                                              if (($dest =~ m{^\Q/public/$cdom/$cnum/syllabus\E.*(\?|\&)usehttp=1}) ||
                                                 ($dest =~ m{^\Q/adm/wrapper/ext/\E(?!https:)})) {                                                  ($dest =~ m{^\Q/adm/wrapper/ext/\E(?!https:)})) {
                                                 if ($ENV{'SERVER_PORT'} == 443) {                                                  if ($ENV{'SERVER_PORT'} == 443) {
                                                     unless (&Apache::lonnet::uses_sts()) {                                                      my $hostname = $r->hostname();
                                                         my $hostname = $r->hostname();                                                      unless ((&Apache::lonnet::uses_sts()) ||
                                                               (&Apache::lonnet::waf_allssl($hostname))) {
                                                         if ($hostname ne '') {                                                          if ($hostname ne '') {
                                                             $dest = 'http://'.$hostname.$dest;                                                              $dest = 'http://'.$hostname.$dest;
                                                         }                                                          }
Line 784  ENDENTERKEY Line 912  ENDENTERKEY
                                                 $dest .= (($dest =~/\?/)? '&':'?').'symb='.$esc_symb;                                                  $dest .= (($dest =~/\?/)? '&':'?').'symb='.$esc_symb;
                                             }                                              }
                                         }                                          }
                                         my $title;                                          if ($env{'form.ttoken'}) {
                                               $dest .= (($dest =~/\?/)? '&':'?').'ttoken='.$env{'form.ttoken'};
                                           }
                                         unless ($env{'request.lti.login'}) {                                          unless ($env{'request.lti.login'}) {
                                             $title = &mt('Entering [_1]',                                              $msg = '<p>'.&mt('Entering [_1] ...',
                                                          $env{'course.'.$cdom.'_'.$cnum.'.description'});                                                               $env{'course.'.$cdom.'_'.$cnum.'.description'}).
                                                      '</p>';
                                         }                                          }
                                         &redirect_user($r,$title,$dest,$msg);                                          &finish_loading_course($r,$msg,$dest);
                                           $r->rflush();
                                         return OK;                                          return OK;
                                     }                                      }
     if (&Apache::lonnet::allowed('whn',      if (&Apache::lonnet::allowed('whn',
Line 800  ENDENTERKEY Line 932  ENDENTERKEY
  ) {   ) {
  my $startpage = &courseloadpage($env{'request.course.id'});   my $startpage = &courseloadpage($env{'request.course.id'});
  unless ($startpage eq 'firstres') {            unless ($startpage eq 'firstres') {         
     $msg = &mt('Entering [_1] ...',      $msg = '<p>'.&mt('Entering [_1] ...',
        $env{'course.'.$env{'request.course.id'}.'.description'});               $env{'course.'.$cdom.'_'.$cnum.'.description'}).
     &redirect_user($r, &mt('New in course'),                                                     '</p>';
                                        '/adm/whatsnew?refpage=start', $msg);                                              &finish_loading_course($r,$msg,'/adm/whatsnew?refpage=start');
                                               $r->rflush();
     return OK;      return OK;
  }   }
     }      }
  }   }
                                 # Are we allowed to look at the first resource?                                  # Are we allowed to look at the first resource?
                                 my $access;                                  #
                                 if ($furl =~ m{^(/adm/wrapper|)/ext/}) {                                  # $furl returned by lonuserstate::readmap() has format:
                                     # If it's an external resource,                                  # $url?symb=escaped($symb). If the resource has the 
                                     # strip off the symb argument and possible query                                  # encrypturl parameter in effect, the entire string
                                     my ($exturl,$symb) = ($furl =~ m{^(.+)(?:\?|\&)symb=(.+)$});                                  # $url?symb=escaped($symb) is encrypted as a string
                                     # Unencode $symb                                  # beginning /enc/.
                                     $symb = &unescape($symb);                                  # 
                                     # Then check for permission                                  my ($access,$unencfurl,$unencsymb);
                                     $access = &Apache::lonnet::allowed('bre',$exturl,$symb);                                  if ($furl =~ m{^(.+)(?:\?|\&)symb=([^&]+)(?:$|&)}) {
                                 # For other resources just check for permission                                      my ($poss_url,$poss_symb) = ($1,$2);
                                       $unencsymb = &unescape($poss_symb);
                                       $unencfurl = $poss_url;
                                   } elsif ($furl =~ m{^/enc/}) {
                                       my $unenc = &Apache::lonenc::unencrypted($furl);
                                       if ($unenc =~ m{^(.+)(?:\?|\&)symb=([^&]+)(?:$|&)}) {
                                           ($unencfurl,$unencsymb) = ($1,$2);
                                           $unencsymb = &unescape($unencsymb);
                                       } else {
                                           $unencfurl = $unenc;
                                       }
                                   } else {
                                       $unencfurl = $furl;
                                   }
                                   if ($unencsymb) {
                                       my $symb = &Apache::lonnet::symbclean($unencsymb);
                                       if (($symb ne '') && (&Apache::lonnet::symbverify($symb,$unencfurl))) {
                                           $access = &Apache::lonnet::allowed('bre',$unencfurl,$symb);
                                       } else {
                                           $access = &Apache::lonnet::allowed('bre',$unencfurl);
                                       }
                                 } else {                                  } else {
                                     $access = &Apache::lonnet::allowed('bre',$furl);                                      $access = &Apache::lonnet::allowed('bre',$unencfurl);
                                 }                                  }
                                 if (!$access) {                                  if ((!$access) || ($access eq 'B') || ($access eq 'D')) {
                                     $furl = &Apache::lonpageflip::first_accessible_resource();                                      $furl = &Apache::lonpageflip::first_accessible_resource();
                                 } elsif ($access eq 'B') {                                      if ($furl eq '') {
                                     $furl = '/adm/navmaps?showOnlyHomework=1';                                          $furl = '/adm/navmaps?showOnlyHomework=1';
                                       }
                                 }                                  }
                                 my $title;  
                                 if ($env{'request.lti.login'}) {                                  if ($env{'request.lti.login'}) {
                                     undef($msg);                                      undef($msg);
                                       &finish_loading_course($r,$msg,$furl);
                                 } else {                                  } else {
                                     $title = &mt('Entering [_1]',                                      $msg = '<p>'.&mt('Entering [_1] ...',
                                                  $env{'course.'.$cdom.'_'.$cnum.'.description'});                $env{'course.'.$cdom.'_'.$cnum.'.description'}).
                                     $msg = &mt('Entering [_1] ...',                                             '</p>';
        $env{'course.'.$cdom.'_'.$cnum.'.description'});                                      &finish_loading_course($r,$msg,$furl);
                                 }                                  }
  &redirect_user($r,$title,$furl,$msg);  
     }      }
                               $r->rflush();
     return OK;      return OK;
  }   }
     }      }
Line 901  ENDENTERKEY Line 1055  ENDENTERKEY
         $crumbtext = 'Courses';          $crumbtext = 'Courses';
         $pagetitle = 'My Courses';          $pagetitle = 'My Courses';
         $recent = &mt('Recent Courses');          $recent = &mt('Recent Courses');
         $standby = &mt('Course selected. Please stand by.');           $standby = &mt('Course selected. Please stand by.');
     }      }
     my $brcrum =[{href=>"/adm/roles",text=>$crumbtext}];      my $brcrum =[{href=>"/adm/roles",text=>$crumbtext}];
   
Line 1126  ENDHEADER Line 1280  ENDHEADER
         }          }
     }      }
   
       if ($norolelist) {
           if ($env{'request.role'}) {
               my ($roletext,$role_text_end) = &display_curr_role($env{'request.role'});
               if ($roletext) {
                   $r->print(&Apache::loncommon::start_data_table('LC_textsize_mobile').
                             &Apache::loncommon::start_data_table_row().
                             $roletext.
                             &Apache::loncommon::end_data_table_row());
                   if ($role_text_end) {
                       $r->print(&Apache::loncommon::continue_data_table_row().
                                 $role_text_end.
                                 &Apache::loncommon::end_data_table_row());
                   }
                   $r->print(&Apache::loncommon::end_data_table());
               }
           }
           $r->print(&Apache::loncommon::end_page());
           return OK;
       }
   
 # No active roles  # No active roles
     if ($countactive==0) {      if ($countactive==0) {
         my $elapsed = 0;          my $elapsed = 0;
Line 2159  sub display_cc_role { Line 2333  sub display_cc_role {
         }          }
     }      }
     return ($roletext,$roletext_end);      return ($roletext,$roletext_end);
   }
   
   sub display_curr_role {
       my ($currentrole) = @_;
       my ($roletext,$roletext_end);
       my $advanced = $env{'user.adv'};
       my $tryagain = $env{'form.tryagain'};
       my ($role,$rest) = split(m{\./},$currentrole,2);
       unless (!defined($role) || $role eq '') {
           if ($rest =~ m{^($match_domain)/($match_courseid)(?:/(\w+)|$)}) {
               my $cdom = $1;
               my $cnum = $2;
               my $csec = $3;
               my $cid = $cdom.'_'.$cnum;
               my $ttype = $env{'course.'.$cid.'.type'};
               my $skipcal = 1;
               my $tbg='LC_roles_is';
               my $twhere = $env{'course.'.$cid.'.description'}. 
                           ' <span class="LC_fontsize_small">'.
                           &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$cnum,$cdom).
                           '</span>';
               my $trole = &Apache::lonnet::plaintext($role,$ttype,$cid);
               if ($csec) {
                   $twhere.= '&nbsp; '.&mt('Section').':&nbsp;'.$csec;
               }
               if ($role ne 'st') {
                   $twhere.= '&nbsp; '.&mt('Domain').':&nbsp;'.$cdom;
               }
               ($roletext,$roletext_end) = &build_roletext($currentrole,$cdom,$cnum,'is',$tryagain,$advanced,'',$tbg,$trole,$twhere,'','','',1,'','','',$skipcal);
           }
       }
       return ($roletext,$roletext_end);
 }  }
   
 sub adhoc_roles_row {  sub adhoc_roles_row {

Removed from v.1.346  
changed lines
  Added in v.1.353


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