--- loncom/interface/loncommon.pm	2006/05/09 14:38:09	1.365
+++ loncom/interface/loncommon.pm	2006/07/20 04:17:55	1.435
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.365 2006/05/09 14:38:09 albertel Exp $
+# $Id: loncommon.pm,v 1.435 2006/07/20 04:17:55 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -64,6 +64,7 @@ use HTML::Entities;
 use Apache::lonhtmlcommon();
 use Apache::loncoursedata();
 use Apache::lontexconvert();
+use LONCAPA;
 
 my $readit;
 
@@ -284,7 +285,7 @@ sub browser_and_searcher_javascript {
 	}
         url += 'element=' + elementname + '';
         var title = 'Browser';
-        var options = 'scrollbars=1,resizable=1,menubar=1,location=1';
+        var options = 'scrollbars=1,resizable=1,menubar=0,toolbar=1,location=1';
         options += ',width=700,height=600';
         editbrowser = open(url,title,options,'1');
         editbrowser.focus();
@@ -305,7 +306,7 @@ sub browser_and_searcher_javascript {
 	}
         url += 'element=' + elementname + '';
         var title = 'Search';
-        var options = 'scrollbars=1,resizable=1,menubar=0';
+        var options = 'scrollbars=1,resizable=1,menubar=0,toolbar=1,location=1';
         options += ',width=700,height=600';
         editsearcher = open(url,title,options,'1');
         editsearcher.focus();
@@ -385,10 +386,11 @@ sub selectstudent_link {
 
 sub coursebrowser_javascript {
     my ($domainfilter)=@_;
+    my $crs_or_grp_alert = &mt('Please select the type of LON-CAPA entity - Course or Group - for which you wish to add/modify a user role');
    return (<<ENDSTDBRW);
 <script type="text/javascript" language="Javascript" >
     var stdeditbrowser;
-    function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag) {
+    function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag,crstype) {
         var url = '/adm/pickcourse?';
         var filter;
         if (filter != null) {
@@ -414,6 +416,18 @@ sub coursebrowser_javascript {
         if (multflag !=null && multflag != '') {
             url += '&multiple='+multflag;
         }
+        if (crstype == 'Course/Group') {
+            if (formname == 'cu') {
+                crstype = document.cu.crstype.options[document.cu.crstype.selectedIndex].value; 
+                if (crstype == "") {
+                    alert("$crs_or_grp_alert");
+                    return;
+                }
+            }
+        }
+        if (crstype !=null && crstype != '') {
+            url += '&type='+crstype;
+        }
         var title = 'Course_Browser';
         var options = 'scrollbars=1,resizable=1,menubar=0';
         options += ',width=700,height=600';
@@ -425,9 +439,9 @@ ENDSTDBRW
 }
 
 sub selectcourse_link {
-   my ($form,$unameele,$udomele,$desc,$extra_element,$multflag)=@_;
+   my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype)=@_;
     return "<a href='".'javascript:opencrsbrowser("'.$form.'","'.$unameele.
-        '","'.$udomele.'","'.$desc.'","'.$extra_element.'","'.$multflag.'");'."'>".&mt('Select Course')."</a>";
+        '","'.$udomele.'","'.$desc.'","'.$extra_element.'","'.$multflag.'","'.$selecttype.'");'."'>".&mt('Select [_1]',$selecttype)."</a>";
 }
 
 sub check_uncheck_jscript {
@@ -692,8 +706,68 @@ sub helpLatexCheatsheet {
 	.'</td></tr></table>';
 }
 
+sub general_help {
+    my $helptopic='Student_Intro';
+    if ($env{'request.role'}=~/^(ca|au)/) {
+	$helptopic='Authoring_Intro';
+    } elsif ($env{'request.role'}=~/^cc/) {
+	$helptopic='Course_Coordination_Intro';
+    }
+    return $helptopic;
+}
+
+sub update_help_link {
+    my ($topic,$component_help,$faq,$bug,$stayOnPage) = @_;
+    my $origurl = $ENV{'REQUEST_URI'};
+    $origurl=~s|^/~|/priv/|;
+    my $timestamp = time;
+    foreach my $datum (\$topic,\$component_help,\$faq,\$bug,\$origurl) {
+        $$datum = &escape($$datum);
+    }
+
+    my $banner_link = "/adm/helpmenu?page=banner&amp;topic=$topic&amp;component_help=$component_help&amp;faq=$faq&amp;bug=$bug&amp;origurl=$origurl&amp;stamp=$timestamp&amp;stayonpage=$stayOnPage";
+    my $output .= <<"ENDOUTPUT";
+<script type="text/javascript">
+// <!-- BEGIN LON-CAPA Internal
+banner_link = '$banner_link';
+// END LON-CAPA Internal -->
+</script>
+ENDOUTPUT
+    return $output;
+}
+
+# now just updates the help link and generates a blue icon
 sub help_open_menu {
-    my ($color,$topic,$component_help,$function,$faq,$bug,$stayOnPage,$width,$height,$text) = @_;
+    my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text) 
+	= @_;
+    
+    $stayOnPage = 0 if (not defined $stayOnPage);
+    if ($env{'browser.interface'} eq 'textual' ||
+	$env{'environment.remote'} eq 'off' ) {
+	$stayOnPage=1;
+    }
+    my $output;
+    if ($component_help) {
+	if (!$text) {
+	    $output=&help_open_topic($component_help,undef,$stayOnPage,
+				       $width,$height);
+	} else {
+	    my $help_text;
+	    $help_text=&unescape($topic);
+	    $output='<table><tr><td>'.
+		&help_open_topic($component_help,$help_text,$stayOnPage,
+				 $width,$height).'</td></tr></table>';
+	}
+    }
+    my $banner_link = &update_help_link($topic,$component_help,$faq,$bug,$stayOnPage);
+    return $output.$banner_link;
+}
+
+sub top_nav_help {
+    my ($text) = @_;
+
+    my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height);
+   
     $text = "" if (not defined $text);
     $stayOnPage = 0 if (not defined $stayOnPage);
     if ($env{'browser.interface'} eq 'textual' ||
@@ -704,26 +778,15 @@ sub help_open_menu {
     $height = 600 if (not defined $height);
     my $link='';
     my $title = &mt('Get help');
-    my $origurl = $ENV{'REQUEST_URI'};
-    $origurl=~s|^/~|/priv/|;
-    my $timestamp = time;
-    foreach my $datum (\$color,\$function,\$topic,\$component_help,\$faq,
-		       \$bug,\$origurl) {
-        $$datum = &Apache::lonnet::escape($$datum);
-    }
-    if (!$stayOnPage) {
-         $link = "javascript:helpMenu('open')";
+    if ($stayOnPage) {
+	$link = "javascript:helpMenu('display')";
     } else {
-        $link = "javascript:helpMenu('display')";
+        $link = "javascript:helpMenu('open')";
     }
-    my $banner_link = "/adm/helpmenu?page=banner&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage";
-    my $details_link = "/adm/helpmenu?page=body&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp";
+    my $helptopic=&general_help();
+    my $banner_link = &update_help_link($topic,$component_help,$faq,$bug,$stayOnPage);
+    my $details_link = '/adm/help/'.$helptopic.'.hlp';
     my $template;
-    if ($text ne "") {
-	$template .= 
-  "<table bgcolor='#CC3300' cellspacing='1' cellpadding='1' border='0'><tr>".
-  "<td bgcolor='#CC6600'><a href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
-    }
     my $nothing=&Apache::lonhtmlcommon::javascript_nothing();
     my $helpicon=&lonhttpdurl("/adm/lonIcons/helpgateway.gif");
     my $start_page =
@@ -741,6 +804,7 @@ sub help_open_menu {
  <script type="text/javascript">
 // <!-- BEGIN LON-CAPA Internal
 // <![CDATA[
+var banner_link = '';
 function helpMenu(target) {
     var caller = this;
     if (target == 'open') {
@@ -760,29 +824,16 @@ function helpMenu(target) {
     return;
 }
 function writeHelp(caller) {
-    caller.document.writeln('$start_page<frame name="bannerframe"  src="$banner_link" /><frame name="bodyframe" src="$details_link" /> $end_page')
+    caller.document.writeln('$start_page<frame name="bannerframe"  src="'+banner_link+'" /><frame name="bodyframe" src="$details_link" /> $end_page')
     caller.document.close()
     caller.focus()
 }
 // ]]>
 // END LON-CAPA Internal -->
  </script>
- <a href="$link" title="$title"><img src="$helpicon" border="0" alt="(Help Menu)" /></a>
+$banner_link
+ <a href="$link" title="$title">$text</a>
 ENDTEMPLATE
-    if ($component_help) {
-	if (!$text) {
-	    $template=&help_open_topic($component_help,undef,$stayOnPage,
-				       $width,$height).' '.$template;
-	} else {
-	    my $help_text;
-	    $help_text=&Apache::lonnet::unescape($topic);
-	    $template='<table><tr><td>'.
-		&help_open_topic($component_help,$help_text,$stayOnPage,
-				 $width,$height).'</td><td>'.$template.
-				 '</td></tr></table>';
-	}
-    }
-    if ($text ne '') { $template.='</td></tr></table>' };
     return $template;
 }
 
@@ -802,8 +853,8 @@ sub help_open_bug {
     $topic=~s/\W+/\+/g;
     my $link='';
     my $template='';
-    my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='.
-	&Apache::lonnet::escape($ENV{'REQUEST_URI'}).'&component='.$topic;
+    my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&amp;bug_file_loc='.
+	&escape($ENV{'REQUEST_URI'}).'&amp;component='.$topic;
     if (!$stayOnPage)
     {
 	$link = "javascript:void(open('$url', 'Bugzilla', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
@@ -1905,12 +1956,20 @@ sub get_related_words {
         return ();
     } 
     my @Words=();
+    my $count=0;
     if (exists($thesaurus_db{$keyword})) {
 	# The first element is the number of times
 	# the word appears.  We do not need it now.
-	(undef,@Words) = (split(/:/,$thesaurus_db{$keyword}));
-        for (my $i=0;$i<=$#Words;$i++) {
-            ($Words[$i],undef)= split(/\,/,$Words[$i]);
+	my (undef,@RelatedWords) = (split(/:/,$thesaurus_db{$keyword}));
+	my (undef,$mostfrequentcount)=split(/\,/,$RelatedWords[0]);
+	my $threshold=$mostfrequentcount/10;
+        foreach my $possibleword (@RelatedWords) {
+            my ($word,$wordcount)=split(/\,/,$possibleword);
+            if ($wordcount>$threshold) {
+		push(@Words,$word);
+                $count++;
+                if ($count>10) { last; }
+	    }
         }
     }
     untie %thesaurus_db;
@@ -1989,6 +2048,9 @@ sub nickname {
 
 sub getnames {
     my ($uname,$udom)=@_;
+    if ($udom eq 'public' && $uname eq 'public') {
+	return ('lastname' => &mt('Public'));
+    }
     my $id=$uname.':'.$udom;
     my ($names,$cached)=&Apache::lonnet::is_cached_new('namescache',$id);
     if ($cached) {
@@ -2024,10 +2086,11 @@ sub screenname {
 # ------------------------------------------------------------- Message Wrapper
 
 sub messagewrapper {
-    my ($link,$username,$domain)=@_;
+    my ($link,$username,$domain,$subject,$text)=@_;
     return 
         '<a href="/adm/email?compose=individual&'.
-        'recname='.$username.'&recdom='.$domain.'" '.
+        'recname='.$username.'&recdom='.$domain.
+	'&subject='.&escape($subject).'&text='.&escape($text).'" '.
         'title="'.&mt('Send message').'">'.$link.'</a>';
 }
 # --------------------------------------------------------------- Notes Wrapper
@@ -2394,7 +2457,7 @@ sub get_previous_attempt {
 	       } else {
 		  $value=$returnhash{$version.':'.$key};
 	       }
-	       $prevattempts.='<td>'.&Apache::lonnet::unescape($value).'&nbsp;</td>';   
+	       $prevattempts.='<td>'.&unescape($value).'&nbsp;</td>';   
 	    }
 	 }
       }
@@ -2406,7 +2469,7 @@ sub get_previous_attempt {
 	} else {
 	  $value=$lasthash{$key};
 	}
-	$value=&Apache::lonnet::unescape($value);
+	$value=&unescape($value);
 	if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
 	$prevattempts.='<td>'.$value.'&nbsp;</td>';
       }
@@ -2528,7 +2591,7 @@ sub submlink {
 	if (!$symb) { $symb=$cursymb; }
     }
     if (!$symb) { $symb=&Apache::lonnet::symbread(); }
-    $symb=&Apache::lonnet::escape($symb);
+    $symb=&escape($symb);
     if ($target) { $target="target=\"$target\""; }
     return '<a href="/adm/grades?&command=submission&'.
 	'symb='.$symb.'&student='.$uname.
@@ -2574,7 +2637,7 @@ sub pprmlink {
 	if (!$symb) { $symb=$cursymb; }
     }
     if (!$symb) { $symb=&Apache::lonnet::symbread(); }
-    $symb=&Apache::lonnet::escape($symb);
+    $symb=&escape($symb);
     if ($target) { $target="target=\"$target\""; }
     return '<a href="/adm/parmset?&command=set&'.
 	'symb='.$symb.'&uname='.$uname.
@@ -2604,6 +2667,11 @@ sub timehash {
              'dlsav'   => $ltime[8] );
 }
 
+sub utc_string {
+    my ($date)=@_;
+    return strftime("%Y%m%dT%H%M%SZ",gmtime($date));
+}
+
 sub maketime {
     my %th=@_;
     return POSIX::mktime(
@@ -2705,6 +2773,7 @@ Returns: value of designparamter $which
 
 =cut
 
+
 ##############################################
 sub designparm {
     my ($which,$domain)=@_;
@@ -2719,11 +2788,11 @@ sub designparm {
 	    return '#CCCCCC';
 	}
     }
-    if ($env{'environment.color.'.$which}) {
+    if (exists($env{'environment.color.'.$which})) {
 	return $env{'environment.color.'.$which};
     }
     $domain=&determinedomain($domain);
-    if ($designhash{$domain.'.'.$which}) {
+    if (exists($designhash{$domain.'.'.$which})) {
 	return $designhash{$domain.'.'.$which};
     } else {
         return $designhash{'default.'.$which};
@@ -2776,7 +2845,6 @@ Inputs:
 =item * $no_inline_link, if true and in remote mode, don't show the 
          'Switch To Inline Menu' link
 
-
 =back
 
 Returns: A uniform header for LON-CAPA web pages.  
@@ -2806,12 +2874,21 @@ sub bodytag {
     @$addentries{keys(%design)} = @design{keys(%design)};
 
  # role and realm
-    my ($role,$realm) =
-	&Apache::lonnet::plaintext((split(/\./,$env{'request.role'}))[0]);
+    my ($role,$realm) = split(/\./,$env{'request.role'},2);
+    if ($role  eq 'ca') {
+        my ($rdom,$rname) = ($realm =~ m-^/(\w+)/(\w+)$-);
+        $realm = &plainname($rname,$rdom).':'.$rdom;
+    } 
 # realm
     if ($env{'request.course.id'}) {
+        if ($env{'request.role'} !~ /^cr/) {
+            $role = &Apache::lonnet::plaintext($role,&course_type());
+        }
 	$realm = $env{'course.'.$env{'request.course.id'}.'.description'};
+    } else {
+        $role = &Apache::lonnet::plaintext($role);
     }
+
     if (!$realm) { $realm='&nbsp;'; }
 # Set messages
     my $messages=&domainlogo($domain);
@@ -2839,15 +2916,17 @@ sub bodytag {
 	return $bodytag;
     }
 
-
+    my $name = &plainname($env{'user.name'},$env{'user.domain'});
+    if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {
+	undef($role);
+    } else {
+	$name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});
+    }
     
     my $roleinfo=(<<ENDROLE);
 <td class="LC_title_bar_who">
 <div class="LC_title_bar_name">
-    $env{'environment.firstname'}
-    $env{'environment.middlename'}
-    $env{'environment.lastname'}
-    $env{'environment.generation'}
+    $name
     &nbsp;
 </div>
 <div class="LC_title_bar_role">
@@ -2871,6 +2950,7 @@ ENDROLE
                                  '.domain'}.'/'})) {
         my $cid = $env{'request.course.id'};
         $dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
+        $dc_info =~ s/\s+$//;
         $dc_info = '('.$dc_info.')';
     }
 
@@ -2897,7 +2977,7 @@ ENDROLE
 		$lastitem = $thisdisfn;
 	    }
 	    $titleinfo = 
-		&Apache::loncommon::help_open_menu('','','','',3,'Authoring').
+		&Apache::loncommon::help_open_menu('','',3,'Authoring').
 		'<b>Construction Space</b>:&nbsp;'. 
 		'<form name="dirs" method="post" action="'.$formaction
 		.'" target="_top"><tt><b>'
@@ -2945,11 +3025,12 @@ ENDROLE
     return(<<ENDBODY);
 $bodytag
 <table id="LC_title_bar" class="LC_with_remote">
-<tr><td>$upperleft</td>
+<tr><td class="LC_title_bar_role_logo">$upperleft</td>
     <td class="LC_title_bar_domain_logo">$messages&nbsp;</td>
 </tr>
 <tr><td>$titleinfo $dc_info $menu</td>
 $roleinfo
+</tr>
 </table>
 ENDBODY
 }
@@ -3068,16 +3149,20 @@ sub standard_css {
     my $tabbg  = &designparm($function.'.tabbg', $domain);
     my $font   = &designparm($function.'.font',  $domain);
     my $sidebg = &designparm($function.'.sidebg',$domain);
-    my $pgbg   = $bgcolor ||
+    my $pgbg_or_bgcolor =
+	         $bgcolor ||
 	         &designparm($function.'.pgbg',  $domain);
+    my $pgbg   = &designparm($function.'.pgbg',  $domain);
     my $alink  = &designparm($function.'.alink', $domain);
     my $vlink  = &designparm($function.'.vlink', $domain);
     my $link   = &designparm($function.'.link',  $domain);
 
     my $sans                 = 'Arial,Helvetica,sans-serif';
+    my $mono                 = 'monospace';
     my $data_table_head      = $tabbg;
     my $data_table_light     = '#EEEEEE';
     my $data_table_dark      = '#DDD';
+    my $data_table_darker    = '#CCC';
     my $data_table_highlight = '#FFFF00';
     my $mail_new             = '#FFBB77';
     my $mail_new_hover       = '#DD9955';
@@ -3087,71 +3172,88 @@ sub standard_css {
     my $mail_replied_hover   = '#888855';
     my $mail_other           = '#99BBBB';
     my $mail_other_hover     = '#669999';
+    my $table_header         = '#DDDDDD';
 
+    my $border = ($env{'browser.type'} eq 'explorer') ? '0px 2px 0px 2px'
+	                                              : '0px 3px 0px 4px';
     return <<END;
 h1, h2, h3, th { font-family: $sans }
 a:focus { color: red; background: yellow } 
 table.thinborder { border-collapse: collapse; }
-table.thinborder tr th, table.thinborder tr td { border-style: solid; border-width: 1px}
+table.thinborder tr th {  border-style: solid; border-width: 1px; background: $tabbg;}
+table.thinborder tr td { border-style: solid; border-width: 1px}
+
 form, .inline { display: inline; }
 .center { text-align: center; }
-.filename {font-family: monospace;}
+.LC_filename {font-family: $mono;}
 .LC_error {
   color: red;
   font-size: larger;
 }
+.LC_warning {
+  color: red;
+}
 .LC_success {
   color: green;
 }
 
-table#LC_top_nav, table#LC_menubuttons, table#LC_nav_location, table#LC_breadcrumbs {
+table#LC_top_nav, table#LC_menubuttons {
   width: 100%;
   background: $pgbg;
-  border: 0px;
-  border-spacing: 2px 1px;
-  padding: 0px;
-  margin: 0px;
+  border: 2px;
   border-collapse: separate;
+  padding: 0px;
 }
-table#LC_title_bar {
+
+table#LC_title_bar, table.LC_breadcrumbs, table#LC_nav_location,
+table#LC_title_bar.LC_with_remote {
   width: 100%;
-  border: 0;
-  border-spacing: 0px 1px;
+  border-color: $pgbg;
+  border-style: solid;
+  border-width: $border;
+
   background: $pgbg;
   font-family: $sans;
   border-collapse: collapse;
+  padding: 0px;
 }
-table#LC_title_bar.LC_with_remote {
+
+table.LC_docs_path {
   width: 100%;
   border: 0;
-  border-spacing: 0;
   background: $pgbg;
   font-family: $sans;
   border-collapse: collapse;
+  padding: 0px;
 }
+
 table#LC_title_bar td {
-  padding: 3px;
   background: $tabbg;
 }
 table#LC_title_bar td.LC_title_bar_who {
   background: $tabbg;
   color: $font;
-  font: medium $sans;
+  font: small $sans;
   text-align: right;
 }
 span.LC_title_bar_title {
-  font: bold xx-large $sans;
+  font: bold x-large $sans;
 }
 table#LC_title_bar td.LC_title_bar_domain_logo {
   background: $sidebg;
   text-align: right;
+  padding: 0px;
+}
+table#LC_title_bar td.LC_title_bar_role_logo {
+  background: $sidebg;
+  padding: 0px;
 }
 
 table#LC_menubuttons_mainmenu {
   background: $pgbg;
   border: 0px;
   border-spacing: 1px;
-  padding: 0px;
+  padding: 0px 1px;
   margin: 0px;
   border-collapse: separate;
 }
@@ -3160,6 +3262,8 @@ table#LC_menubuttons img, table#LC_menub
 }
 table#LC_top_nav td {
   background: $tabbg;
+  border: 0px;
+  font-size: small;
 }
 table#LC_top_nav td a, div#LC_top_nav a {
   color: $font;
@@ -3167,21 +3271,36 @@ table#LC_top_nav td a, div#LC_top_nav a
 }
 table#LC_top_nav td.LC_top_nav_logo {
   background: $tabbg;
-  text-align: right;
+  text-align: left;
+  white-space: nowrap;
+  width: 31px;
 }
-table#LC_breadcrumbs td {
+table#LC_top_nav td.LC_top_nav_logo img {
+  border: 0px;
+  vertical-align: bottom;
+}
+table#LC_top_nav td.LC_top_nav_exit,
+table#LC_top_nav td.LC_top_nav_help {
+  width: 2.0em;
+}
+table.LC_breadcrumbs td, table.LC_docs_path td  {
   background: $tabbg;
   color: $font;
   font-family: $sans;
   font-size: smaller;
 }
-table#LC_breadcrumbs td.LC_breadcrumb_component {
+table.LC_breadcrumbs td.LC_breadcrumbs_component,
+table.LC_docs_path td.LC_docs_path_component {
   background: $tabbg;
   color: $font;
   font-family: $sans;
   font-size: larger;
   text-align: right;
 }
+td.LC_table_cell_checkbox {
+  text-align: center;
+}
+
 .LC_menubuttons_inline_text {
   color: $font;
   font-family: $sans;
@@ -3206,20 +3325,33 @@ td.LC_menubuttons_img {
 
 table.LC_data_table, table.LC_mail_list {
   border: 1px solid #000000;
-  border-collapse: seperate;
+  border-collapse: separate;
+  border-spacing: 1px;
+}
+.LC_data_table_dense {
+  font-size: small;
 }
 table.LC_data_table tr th, table.LC_calendar tr th, table.LC_mail_list tr th {
   font-weight: bold;
   background-color: $data_table_head;
+  font-size: smaller;
 }
 table.LC_data_table tr td {
   background-color: $data_table_light;
+  padding: 2px;
 }
 table.LC_data_table tr.LC_even_row td {
   background-color: $data_table_dark;
 }
-table.LC_data_table tr.LC_empty td {
+table.LC_data_table tr.LC_data_table_highlight td {
+  background-color: $data_table_darker;
+}
+table.LC_data_table tr.LC_empty_row td {
   background-color: #FFFFFF;
+  font-weight: bold;
+  font-style: italic;
+  text-align: center;
+  padding: 8px;
 }
 
 table.LC_calendar {
@@ -3264,6 +3396,250 @@ table.LC_mail_list tr.LC_mail_other {
 table.LC_mail_list tr.LC_mail_other:hover {
   background-color: $mail_other_hover;
 }
+
+table#LC_portfolio_actions {
+  width: auto;
+  background: $pgbg;
+  border: 0px;
+  border-spacing: 2px 2px;
+  padding: 0px;
+  margin: 0px;
+  border-collapse: separate;
+}
+table#LC_portfolio_actions td.LC_label {
+  background: $tabbg;
+  text-align: right;
+}
+table#LC_portfolio_actions td.LC_value {
+  background: $tabbg;
+}
+
+table#LC_cstr_controls {
+  width: 100%;
+  border-collapse: collapse;
+}
+table#LC_cstr_controls tr td {
+  border: 4px solid $pgbg;
+  padding: 4px;
+  text-align: center;
+  background: $tabbg;
+}
+table#LC_cstr_controls tr th {
+  border: 4px solid $pgbg;
+  background: $table_header;
+  text-align: center;
+  font-family: $sans;
+  font-size: smaller;
+}
+
+table#LC_browser {
+ 
+}
+table#LC_browser tr th {
+  background: $table_header;
+}
+table#LC_browser tr td {
+  padding: 2px;
+}
+table#LC_browser tr.LC_browser_file,
+table#LC_browser tr.LC_browser_file_published {
+  background: #CCFF88;
+}
+table#LC_browser tr.LC_browser_file_locked,
+table#LC_browser tr.LC_browser_file_unpublished {
+  background: #FFAA99;
+}
+table#LC_browser tr.LC_browser_file_obsolete {
+  background: #AAAAAA;
+}
+table#LC_browser tr.LC_browser_file_modified {
+  background: #FFFF77;
+}
+table#LC_browser tr.LC_browser_folder {
+  background: #CCCCFF;
+}
+span.LC_current_location {
+  font-size: x-large;
+  background: $pgbg;
+}
+
+span.LC_parm_menu_item {
+  font-size: larger;
+  font-family: $sans;
+}
+span.LC_parm_scope_all {
+  color: red;
+}
+span.LC_parm_scope_folder {
+  color: green;
+}
+span.LC_parm_scope_resource {
+  color: orange;
+}
+span.LC_parm_part {
+  color: blue;
+}
+span.LC_parm_folder, span.LC_parm_symb {
+  font-size: x-small;
+  font-family: $mono;
+  color: #AAAAAA;
+}
+
+td.LC_parm_overview_level_menu, td.LC_parm_overview_map_menu,
+td.LC_parm_overview_parm_selectors, td.LC_parm_overview_parm_restrictions {
+  border: 1px solid black;
+  border-collapse: collapse;
+}
+table.LC_parm_overview_restrictions td {
+  border-width: 1px 4px 1px 4px;
+  border-style: solid;
+  border-color: $pgbg;
+  text-align: center;
+}
+table.LC_parm_overview_restrictions th {
+  background: $tabbg;
+  border-width: 1px 4px 1px 4px;
+  border-style: solid;
+  border-color: $pgbg;
+}
+table#LC_helpmenu {
+  border: 0px;
+  height: 55px;
+  border-spacing: 0px;
+}
+
+table#LC_helpmenu fieldset legend {
+  font-size: larger;
+  font-weight: bold;
+}
+table#LC_helpmenu_links {
+  width: 100%;
+  border: 1px solid black;
+  background: $pgbg;
+  padding: 0px;
+  border-spacing: 1px;
+}
+table#LC_helpmenu_links tr td {
+  padding: 1px;
+  background: $tabbg;
+  text-align: center;
+  font-weight: bold;
+}
+
+table#LC_helpmenu_links a:link, table#LC_helpmenu_links a:visited,
+table#LC_helpmenu_links a:active {
+  text-decoration: none;
+  color: $font;
+}
+table#LC_helpmenu_links a:hover {
+  text-decoration: underline;
+  color: $vlink;
+}
+
+.LC_chrt_popup_exists {
+  border: 1px solid #339933;
+  margin: -1px;
+}
+.LC_chrt_popup_up {
+  border: 1px solid yellow;
+  margin: -1px;
+}
+.LC_chrt_popup {
+  border: 1px solid #8888FF;
+  background: #CCCCFF;
+}
+
+table.LC_pick_box {
+  width: 100%;
+  border-collapse: separate;
+  background: white;
+  border: 1px solid black;
+  border-spacing: 1px;
+}
+table.LC_pick_box td.LC_pick_box_title {
+  background: $tabbg;
+  font-weight: bold;
+  text-align: right;
+  width: 184px;
+  padding: 8px;
+}
+table.LC_pick_box td.LC_pick_box_separator {
+  padding: 0px;
+  height: 1px;
+  background: black;
+}
+table.LC_pick_box td.LC_pick_box_submit {
+  text-align: right;
+}
+
+table.LC_group_priv_box {
+  background: white;
+  border: 1px solid black;
+  border-spacing: 1px;
+}
+table.LC_group_priv_box td.LC_pick_box_title {
+  background: $tabbg;
+  font-weight: bold;
+  text-align: right;
+  width: 184px;
+}
+table.LC_group_priv_box td.LC_groups_fixed {
+  background: $data_table_light;
+  text-align: center;
+}
+table.LC_group_priv_box td.LC_groups_optional {
+  background: $data_table_dark;
+  text-align: center;
+}
+table.LC_group_priv_box td.LC_groups_functionality {
+  background: $data_table_darker;
+  text-align: center;
+  font-weight: bold;
+}
+table.LC_group_priv td {
+  text-align: left;
+  padding: 0px;
+}
+
+table.LC_notify_front_page {
+  background: white;
+  border: 1px solid black;
+  padding: 8px;
+}
+table.LC_notify_front_page td {
+  padding: 8px;
+}
+.LC_navbuttons {
+  margin: 2ex 0ex 2ex 0ex;
+}
+.LC_topic_bar {
+  font-family: $sans;
+  font-weight: bold;
+  width: 100%;
+  background: $tabbg;
+  vertical-align: middle;
+  margin: 2ex 0ex 2ex 0ex;
+}
+.LC_topic_bar span {
+  vertical-align: middle;
+}
+.LC_topic_bar img {
+  vertical-align: bottom;
+}
+table.LC_course_group_status {
+  margin: 20px;
+}
+table.LC_status_selector td {
+  vertical-align: top;
+  text-align: center;
+  padding: 4px;
+}
+table.LC_descriptive_input td.LC_description {
+  vertical-align: top;
+  text-align: right;
+  font-weight: bold;
+}
+
 END
 }
 
@@ -3280,8 +3656,10 @@ Inputs: $title - optional title for the
         $args - optional arguments
             force_register - if is true call registerurl so the remote is 
                              informed
-            redirect       -> array ref of seconds before redirect occurs
-                                    url to redirect to
+            redirect       -> array ref of
+                                   1- seconds before redirect occurs
+                                   2- url to redirect to
+                                   3- whether the side effect should occur
                            (side effect of setting 
                                $env{'internal.head.redirect'} to the url 
                                redirected too)
@@ -3301,14 +3679,14 @@ sub headtag {
     my $domain   = $args->{'domain'}   || &determinedomain();
     my $bgcolor  = $args->{'bgcolor'}  || &designparm($function.'.pgbg',$domain);
     my $url = join(':',$env{'user.name'},$env{'user.domain'},
+		   #time(),
 		   $env{'environment.color.timestamp'},
 		   $function,$domain,$bgcolor);
 
-    $url = '/adm/css/'.&Apache::lonnet::escape($url).'.css';
+    $url = '/adm/css/'.&escape($url).'.css';
 
     my $result =
 	'<head>'.
-	'<link rel="stylesheet" type="text/css" href="'.$url.'" />'.
 	&font_settings().
 	&Apache::lonhtmlcommon::htmlareaheaders();
 
@@ -3317,9 +3695,11 @@ sub headtag {
     }
 
     if (ref($args->{'redirect'})) {
-	my ($time,$url) = @{$args->{'redirect'}};
+	my ($time,$url,$inhibit_continue) = @{$args->{'redirect'}};
 	$url = &Apache::lonenc::check_encrypt($url);
-	$env{'internal.head.redirect'} = $url;
+	if (!$inhibit_continue) {
+	    $env{'internal.head.redirect'} = $url;
+	}
 	$result.=<<ADDMETA
 <meta http-equiv="pragma" content="no-cache" />
 <meta http-equiv="Refresh" content="$time; url=$url" />
@@ -3329,7 +3709,9 @@ ADDMETA
 	$title = 'The LearningOnline Network with CAPA';
     }
     
-    $result .= '<title> LON-CAPA '.&mt($title).'</title>'.$head_extra;
+    $result .= '<title> LON-CAPA '.&mt($title).'</title>'
+	.'<link rel="stylesheet" type="text/css" href="'.$url.'" />'
+	.$head_extra;
     return $result;
 }
 
@@ -3421,6 +3803,7 @@ Returns a uniform complete <head>..</hea
 
 Inputs: $title - optional title for the page
         $head_extra - optional extra HTML to put inside the <head>
+
 =back
 
 =cut
@@ -3534,13 +3917,11 @@ Inputs:         $args - additional optio
                                  a html attribute
                  frameset     -> if true will start with a <frameset>
                                  rather than <body>
-=back
 
 =cut
 
 sub end_page {
     my ($args) = @_;
-    #&Apache::lonnet::logthis("end_page ".join(':',caller(0)));
     $env{'internal.end_page'}++;
     my $result;
     if ($args->{'discussion'}) {
@@ -3583,7 +3964,7 @@ sub js_ready {
     $result =~ s/[\n\r]/ /xmsg;
     $result =~ s/\\/\\\\/xmsg;
     $result =~ s/'/\\'/xmsg;
-    $result =~ s{</script>}{</scrip'+'t>}xmsg;
+    $result =~ s{</}{<\\/}xmsg;
     
     return $result;
 }
@@ -3629,22 +4010,44 @@ sub simple_error_page {
 {
     my $row_count;
     sub start_data_table {
+	my ($add_class) = @_;
+	my $css_class = (join(' ','LC_data_table',$add_class));
 	undef($row_count);
-	return '<table class="LC_data_table">';
+	return '<table class="'.$css_class.'">'."\n";
     }
 
     sub end_data_table {
 	undef($row_count);
-	return '</table>';
+	return '</table>'."\n";;
     }
 
     sub start_data_table_row {
+	my ($add_class) = @_;
 	$row_count++;
-	return  '<tr '.(($row_count % 2)?'':'class="LC_even_row"').'>';
+	my $css_class = ($row_count % 2)?'':'LC_even_row';
+	$css_class = (join(' ',$css_class,$add_class));
+	return  '<tr class="'.$css_class.'">'."\n";;
     }
 
     sub end_data_table_row {
-	return '</tr>';
+	return '</tr>'."\n";;
+    }
+
+    sub start_data_table_empty_row {
+	$row_count++;
+	return  '<tr class="LC_empty_row" >'."\n";;
+    }
+
+    sub end_data_table_empty_row {
+	return '</tr>'."\n";;
+    }
+
+    sub start_data_table_header_row {
+	return  '<tr class="LC_header_row">'."\n";;
+    }
+
+    sub end_data_table_header_row {
+	return '</tr>'."\n";;
     }
 }
 
@@ -3652,9 +4055,7 @@ sub simple_error_page {
 
 =pod
 
-=over 4
-
-=item get_users_function
+=item * &get_users_function()
 
 Used by &bodytag to determine the current users primary role.
 Returns either 'student','coordinator','admin', or 'author'.
@@ -3681,14 +4082,14 @@ sub get_users_function {
 
 =pod
 
-=item check_user_status
+=item * &check_user_status
 
 Determines current status of supplied role for a
 specific user. Roles can be active, previous or future.
 
 Inputs: 
 user's domain, user's username, course's domain,
-course's number, optional section/group.
+course's number, optional section ID.
 
 Outputs:
 role status: active, previous or future. 
@@ -3696,33 +4097,35 @@ role status: active, previous or future.
 =cut
 
 sub check_user_status {
-    my ($udom,$uname,$cdom,$crs,$role,$secgrp) = @_;
+    my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
     my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
     my @uroles = keys %userinfo;
     my $srchstr;
     my $active_chk = 'none';
+    my $now = time;
     if (@uroles > 0) {
-        if (($role eq 'cc') || ($secgrp eq '') || (!defined($secgrp))) {
+        if (($role eq 'cc') || ($sec eq '') || (!defined($sec))) {
             $srchstr = '/'.$cdom.'/'.$crs.'_'.$role;
         } else {
-            $srchstr = '/'.$cdom.'/'.$crs.'/'.$secgrp.'_'.$role;         }
-        if (grep/^$srchstr$/,@uroles) {
+            $srchstr = '/'.$cdom.'/'.$crs.'/'.$sec.'_'.$role;
+        }
+        if (grep/^\Q$srchstr\E$/,@uroles) {
             my $role_end = 0;
             my $role_start = 0;
             $active_chk = 'active';
-            if ($userinfo{$srchstr} =~ m/^($role)_(\d+)/) {
-                $role_end = $2;
-                if ($userinfo{$srchstr} =~ m/^($role)_($role_end)_(\d+)$/) {
-                    $role_start = $3;
+            if ($userinfo{$srchstr} =~ m/^\Q$role\E_(\d+)/) {
+                $role_end = $1;
+                if ($userinfo{$srchstr} =~ m/^\Q$role\E_\Q$role_end\E_(\d+)$/) {
+                    $role_start = $1;
                 }
             }
             if ($role_start > 0) {
-                if (time < $role_start) {
+                if ($now < $role_start) {
                     $active_chk = 'future';
                 }
             }
             if ($role_end > 0) {
-                if (time > $role_end) {
+                if ($now > $role_end) {
                     $active_chk = 'previous';
                 }
             }
@@ -3735,36 +4138,68 @@ sub check_user_status {
 
 =pod
 
-=item get_sections
+=item * &get_sections()
 
 Determines all the sections for a course including
 sections with students and sections containing other roles.
-Incoming parameters: domain, course number, reference to 
-section hash (keys to be section/group IDs), reference to 
-array containing roles for which sections should be gathered
-(optional). If the fourth argument is undefined, sections
-are gathered for any role.
+Incoming parameters: 
+
+1. domain
+2. course number 
+3. reference to array containing roles for which sections should 
+be gathered (optional).
+4. reference to array containing status types for which sections 
+should be gathered (optional).
+
+If the third argument is undefined, sections are gathered for any role. 
+If the fourth argument is undefined, sections are gathered for any status.
+Permissible values are 'active' or 'future' or 'previous'.
  
-Returns number of sections.
+Returns section hash (keys are section IDs, values are
+number of users in each section), subject to the
+optional roles filter, optional status filter 
 
 =cut
 
 ###############################################
 sub get_sections {
-    my ($cdom,$cnum,$sectioncount,$possible_roles) = @_;
-    if (!($cdom && $cnum)) { return 0; }
-    my $numsections = 0;
+    my ($cdom,$cnum,$possible_roles,$possible_status) = @_;
+    if (!defined($cdom) || !defined($cnum)) {
+        my $cid =  $env{'request.course.id'};
+
+	return if (!defined($cid));
+
+        $cdom = $env{'course.'.$cid.'.domain'};
+        $cnum = $env{'course.'.$cid.'.num'};
+    }
 
-    if (!defined($possible_roles) || (grep/^st$/,@$possible_roles)) {
+    my %sectioncount;
+    my $now = time;
+
+    if (!defined($possible_roles) || (grep(/^st$/,@$possible_roles))) {
 	my ($classlist) = &Apache::loncoursedata::get_classlist($cdom,$cnum);
 	my $sec_index = &Apache::loncoursedata::CL_SECTION();
 	my $status_index = &Apache::loncoursedata::CL_STATUS();
-	while (my ($student,$data) = each %$classlist) {
-	    my ($section,$status) = ($data->[$sec_index],
-				     $data->[$status_index]);
-	    unless ($section eq '-1' || $section =~ /^\s*$/) {
-		if (!defined($$sectioncount{$section})) { $numsections++; }
-		$$sectioncount{$section}++;
+        my $start_index = &Apache::loncoursedata::CL_START();
+        my $end_index = &Apache::loncoursedata::CL_END();
+        my $status;
+	while (my ($student,$data) = each(%$classlist)) {
+	    my ($section,$stu_status,$start,$end) = ($data->[$sec_index],
+				                     $data->[$status_index],
+                                                     $data->[$start_index],
+                                                     $data->[$end_index]);
+            if ($stu_status eq 'Active') {
+                $status = 'active';
+            } elsif ($end < $now) {
+                $status = 'previous';
+            } elsif ($start > $now) {
+                $status = 'future';
+            } 
+	    if ($section ne '-1' && $section !~ /^\s*$/) {
+                if ((!defined($possible_status)) || (($status ne '') && 
+                    (grep/^\Q$status\E$/,@{$possible_status}))) { 
+		    $sectioncount{$section}++;
+                }
 	    }
 	}
     }
@@ -3773,171 +4208,41 @@ sub get_sections {
 	if ($user !~ /^(\w{2})/) { next; }
 	my ($role) = ($user =~ /^(\w{2})/);
 	if ($possible_roles && !(grep(/^$role$/,@$possible_roles))) { next; }
-	my $section;
+	my ($section,$status);
 	if ($role eq 'cr' &&
 	    $user =~ m-^$role/[^/]*/[^/]*/[^/]*:[^:]*:[^:]*:(\w+)-) {
 	    $section=$1;
 	}
 	if ($user =~ /^$role:[^:]*:[^:]*:(\w+)/) { $section=$1; }
 	if (!defined($section) || $section eq '-1') { next; }
-	if (!defined($$sectioncount{$section})) { $numsections++; } 
-	$$sectioncount{$section}++;
-    }
-    return $numsections;
-}
-
-###############################################
-                                                                                  
-=pod
-                                                                                  
-=item coursegroups
-
-Retrieve information about groups in a course,
-
-Input:
-1. Reference to hash to populate with group information. 
-2. Optional course domain
-3. Optional course number
-4. Optional group name
-
-Course domain and number will be taken from user's
-environment if not supplied. Optional group name will'
-be passed to lonnet::get_coursegroups() as a regexp to
-use in the call to the dump function.
-
-Output
-Returns number of groups in the course (subject to the
-optional group name filter).
-
-Side effects:
-Populates the referenced curr_groups hash, with key,
-value pairs. Keys are group names, corresponding values
-are scalars containing group information in XML. This
-can be sent to &get_group_settings() to be parsed.     
-
-=cut 
-
-###############################################
-
-sub coursegroups {
-    my ($cdom,$cnum,$group) = @_;
-    if (!defined($cdom) || !defined($cnum)) {
-        my $cid =  $env{'request.course.id'};
-
-	return if (!defined($cid));
-
-        $cdom = $env{'course.'.$cid.'.domain'};
-        $cnum = $env{'course.'.$cid.'.num'};
-    }
-    my %curr_groups = &Apache::lonnet::get_coursegroups($cdom,$cnum,$group);
-    my ($tmp) = keys(%curr_groups);
-    if ($tmp=~/^(con_lost|no_such_host|error: [^2] )/) {
-	undef(%curr_groups);
-	&logthis('Error retrieving groups: '.$tmp.' in '.$cnum.':'.$cdom);
-    } elsif ($tmp=~/^error: 2 /) {
-	undef(%curr_groups);
-    }
-    return %curr_groups;
-}
-
-###############################################
-
-=pod
-
-=item get_group_settings
-
-Uses TokeParser to extract group information from the
-XML used to describe course groups.
-
-Input:
-Scalar containing XML  - as retrieved from &coursegroups().
-
-Output:
-Hash containing group information as key=values for (a), and
-hash of hashes for (b)
-
-Keys (in two categories):
-(a) groupname, creator, creation, modified, startdate,enddate.
-Corresponding values are name of the group, creator of the group
-(username:domain), UNIX time for date group was created, and
-settings were last modified, and default start and end access
-times for group members.
-
-(b) functions returned in hash of hashes.
-Outer hash key is functions.
-Inner hash keys are chat,discussion,email,files,homepage,roster.
-Corresponding values are either on or off, depending on
-whether this type of functionality is available for the group.
-
-=cut
-                                                                                 
-###############################################
-
-sub get_group_settings {
-    my ($groupinfo)=@_;
-    my $parser=HTML::TokeParser->new(\$groupinfo);
-    my $token;
-    my $tool = '';
-    my $role = '';
-    my %content=();
-    while ($token=$parser->get_token) {
-        if ($token->[0] eq 'S')  {
-            my $entry=$token->[1];
-            if ($entry eq 'functions' || $entry eq 'autosec') {
-                %{$content{$entry}} = ();
-                $tool = $entry;
-            } elsif ($entry eq 'role') {
-                if ($tool eq 'autosec') {
-                    $role = $token->[2]{id};
-                }
-            } else {
-                my $value=$parser->get_text('/'.$entry);
-                if ($entry eq 'name') {
-                    if ($tool eq 'functions') {
-                        my $function = $token->[2]{id};
-                        $content{$tool}{$function} = $value;
-                    }
-                } elsif ($entry eq 'groupname') {
-                    $content{$entry}=&Apache::lonnet::unescape($value);
-                } elsif (($entry eq 'roles') || ($entry eq 'types') ||
-                         ($entry eq 'sectionpick') || ($entry eq 'defpriv')) {
-                    push(@{$content{$entry}},$value);
-                } elsif ($entry eq 'section') {
-                    if ($tool eq 'autosec'  && $role ne '') {
-                        push(@{$content{$tool}{$role}},$value);
-                    }
-                } else {
-                    $content{$entry}=$value;
-                }
+        my ($end,$start) = ($courseroles{$user} =~ /^([^:]*):([^:]*)$/);
+        if ($end == -1 && $start == -1) {
+            next; #deleted role
+        }
+        if (!defined($possible_status)) { 
+            $sectioncount{$section}++;
+        } else {
+            if ((!$end || $end >= $now) && (!$start || $start <= $now)) {
+                $status = 'active';
+            } elsif ($end < $now) {
+                $status = 'future';
+            } elsif ($start > $now) {
+                $status = 'previous';
             }
-        } elsif ($token->[0] eq 'E') {
-            if ($token->[1] eq 'functions' || $token->[1] eq 'autosec') {
-                $tool = '';
-            } elsif ($token->[1] eq 'role') {
-                $role = '';
+            if (($status ne '') && (grep/^\Q$status\E$/,@{$possible_status})) {
+                $sectioncount{$section}++;
             }
-
         }
     }
-    return %content;
-}
-
-sub check_group_access {
-    my ($group) = @_;
-    my $access = 1;
-    my $now = time;
-    my ($start,$end) = split(/\./,$env{'user.role.gr/'.$env{'request.course,id'}.'/'.$group});
-    if (($end!=0) && ($end<$now)) { $access = 0; }
-    if (($start!=0) && ($start>$now)) { $access=0; }
-    return $access;
+    return %sectioncount;
 }
 
 ###############################################
 
 =pod
-                                                                                
-=item get_course_users
-                                                                                
+
+=item * &get_course_users()
+
 Retrieves usernames:domains for users in the specified course
 with specific role(s), and access status. 
 
@@ -3960,12 +4265,13 @@ Entries for end, start, section and stat
 of the possibility of multiple values for non-student roles.
 
 =cut
-                                                                                
+
 ###############################################
-                                                                                
+
 sub get_course_users {
     my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata) = @_;
     my %idx = ();
+    my %seclists;
 
     $idx{udom} = &Apache::loncoursedata::CL_SDOM();
     $idx{uname} =  &Apache::loncoursedata::CL_SNAME();
@@ -3981,12 +4287,28 @@ sub get_course_users {
         my $now = time;
         foreach my $student (keys(%{$classlist})) {
             my $match = 0;
+            my $secmatch = 0;
+            my $section = $$classlist{$student}[$idx{section}];
+            if ($section eq '') {
+                $section = 'none';
+            }
             if ((ref($sections) eq 'ARRAY') && (@{$sections} > 0)) {
-		unless(grep(/^\Q$$classlist{$student}[$idx{section}]\E$/,
-			    @{$sections})) {
-		    next;
+                if (grep(/^all$/,@{$sections})) {
+                    $secmatch = 1;
+                } elsif ($$classlist{$student}[$idx{section}] eq '') {
+                    if (grep(/^none$/,@{$sections})) {
+                        $secmatch = 1;
+                    }
+                } else {  
+		    if (grep(/^\Q$section\E$/,@{$sections})) {
+		        $secmatch = 1;
+                    }
 		}
-            } 
+                if (!$secmatch) {
+                    next;
+                }
+            }
+            push(@{$seclists{$student}},$section); 
             if (defined($$types{'active'})) {
                 if ($$classlist{$student}[$idx{status}] eq 'Active') {
                     push(@{$$users{st}{$student}},'active');
@@ -4005,36 +4327,57 @@ sub get_course_users {
                     $match = 1;
                 }
             }
-            if ($match && defined($userdata)) {
+            if ($match && ref($userdata) eq 'HASH') {
                 $$userdata{$student} = $$classlist{$student};
             }
         }
     }
-    if ((@{$roles} > 0) && (@{$roles} ne "st")) {
+    if ((@{$roles} > 1) || ((@{$roles} == 1) && ($$roles[0] ne "st"))) {
         my @coursepersonnel = &Apache::lonnet::getkeys('nohist_userroles',$cdom,$cnum);
         foreach my $person (@coursepersonnel) {
             my $match = 0;
-            my ($role,$user) = ($person =~ /^([^:]*):([^:]+:[^:]+)/);
+            my $secmatch = 0;
+            my ($role,$user,$usec) = ($person =~ /^([^:]*):([^:]+:[^:]+):([^:]*)/);
             $user =~ s/:$//;
             if (($role) && (grep(/^\Q$role\E$/,@{$roles}))) {
-                my ($uname,$udom,$usec) = split(/:/,$user);
-                if ($usec ne '' && (ref($sections) eq 'ARRAY') && 
-		    @{$sections} > 0) {
-		    unless(grep(/^\Q$usec\E$/,@{$sections})) {
-			next;
-		    }
+                my ($uname,$udom) = split(/:/,$user);
+                if ((ref($sections) eq 'ARRAY') && (@{$sections} > 0)) {
+                    if (grep(/^all$/,@{$sections})) {
+                        $secmatch = 1;
+                    } elsif ($usec eq '') {
+                        if (grep(/^none$/,@{$sections})) {
+                            $secmatch = 1;
+                        }
+                    } else {
+                        if (grep(/^\Q$usec\E$/,@{$sections})) {
+                            $secmatch = 1;
+                        }
+                    }
+                    if (!$secmatch) {
+                        next;
+                    }
+                }
+                if ($usec eq '') {
+                    $usec = 'none';
                 }
                 if ($uname ne '' && $udom ne '') {
-                    my $status = &check_user_status($udom,$uname,$cdom,$cnum,$role);
+                    my $status = &check_user_status($udom,$uname,$cdom,$cnum,$role,
+                                                    $usec);
                     foreach my $type (keys(%{$types})) { 
                         if ($status eq $type) {
-                            @{$$users{$role}{$user}} = $type;
+                            if (!grep(/^\Q$type\E$/,@{$$users{$role}{$user}})) {
+                                push(@{$$users{$role}{$user}},$type);
+                            }
                             $match = 1;
                         }
                     }
-                    if ($match && defined($userdata) &&
-                        !exists($$userdata{$uname.':'.$udom})) {
-			&get_user_info($udom,$uname,\%idx,$userdata);
+                    if (($match) && (ref($userdata) eq 'HASH')) {
+                        if (!exists($$userdata{$uname.':'.$udom})) {
+			    &get_user_info($udom,$uname,\%idx,$userdata);
+                        }
+                        if (!grep(/^\Q$usec\E$/,@{$seclists{$uname.':'.$udom}})) {
+                            push(@{$seclists{$uname.':'.$udom}},$usec);
+                        }
                     }
                 }
             }
@@ -4048,10 +4391,17 @@ sub get_course_users {
                     if (defined($userdata) && 
 			!exists($$userdata{$owner.':'.$cdom})) {
 			&get_user_info($cdom,$owner,\%idx,$userdata);
+                        if (!grep(/^none$/,@{$seclists{$owner.':'.$cdom}})) {
+                            push(@{$seclists{$owner.':'.$cdom}},'none');
+                        }
 		    }
                 }
             }
         }
+        foreach my $user (keys(%seclists)) {
+            @{$seclists{$user}} = (sort {$a <=> $b} @{$seclists{$user}});
+            $$userdata{$user}[$idx{section}] = join(',',@{$seclists{$user}});
+        }
     }
     return;
 }
@@ -4065,6 +4415,43 @@ sub get_user_info {
     return;
 }
 
+sub get_secgrprole_info {
+    my ($cdom,$cnum,$needroles,$type)  = @_;
+    my %sections_count = &get_sections($cdom,$cnum);
+    my @sections =  (sort {$a <=> $b} keys(%sections_count));
+    my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
+    my @groups = sort(keys(%curr_groups));
+    my $allroles = [];
+    my $rolehash;
+    my $accesshash = {
+                     active => 'Currently has access',
+                     future => 'Will have future access',
+                     previous => 'Previously had access',
+                  };
+    if ($needroles) {
+        $rolehash = {'all' => 'all'};
+        my %user_roles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
+	if (&Apache::lonnet::error(%user_roles)) {
+	    undef(%user_roles);
+	}
+        foreach my $item (keys(%user_roles)) {
+            my ($role)=split(/\:/,$item,2);
+            if ($role eq 'cr') { next; }
+            if ($role =~ /^cr/) {
+                $$rolehash{$role} = (split('/',$role))[3];
+            } else {
+                $$rolehash{$role} = &Apache::lonnet::plaintext($role,$type);
+            }
+        }
+        foreach my $key (sort(keys(%{$rolehash}))) {
+            push(@{$allroles},$key);
+        }
+        push (@{$allroles},'st');
+        $$rolehash{'st'} = &Apache::lonnet::plaintext('st',$type);
+    }
+    return (\@sections,\@groups,$allroles,$rolehash,$accesshash);
+}
+
 =pod
 
 =item * get_unprocessed_cgi($query,$possible_names)
@@ -4085,7 +4472,7 @@ sub get_unprocessed_cgi {
   # $Apache::lonxml::debug=1;
   foreach my $pair (split(/&/,$query)) {
     my ($name, $value) = split(/=/,$pair);
-    $name = &Apache::lonnet::unescape($name);
+    $name = &unescape($name);
     if (!defined($possible_names) || (grep {$_ eq $name} @$possible_names)) {
       $value =~ tr/+/ /;
       $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
@@ -4714,9 +5101,9 @@ sub DrawBarGraph {
     $Title  = '' if (! defined($Title));
     $xlabel = '' if (! defined($xlabel));
     $ylabel = '' if (! defined($ylabel));
-    $ValuesHash{$id.'.title'}    = &Apache::lonnet::escape($Title);
-    $ValuesHash{$id.'.xlabel'}   = &Apache::lonnet::escape($xlabel);
-    $ValuesHash{$id.'.ylabel'}   = &Apache::lonnet::escape($ylabel);
+    $ValuesHash{$id.'.title'}    = &escape($Title);
+    $ValuesHash{$id.'.xlabel'}   = &escape($xlabel);
+    $ValuesHash{$id.'.ylabel'}   = &escape($ylabel);
     $ValuesHash{$id.'.y_max_value'} = $Max;
     $ValuesHash{$id.'.NumBars'}  = $NumBars;
     $ValuesHash{$id.'.NumSets'}  = $NumSets;
@@ -4796,9 +5183,9 @@ sub DrawXYGraph {
     $ylabel = '' if (! defined($ylabel));
     my %ValuesHash = 
         (
-         $id.'.title'  => &Apache::lonnet::escape($Title),
-         $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
-         $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
+         $id.'.title'  => &escape($Title),
+         $id.'.xlabel' => &escape($xlabel),
+         $id.'.ylabel' => &escape($ylabel),
          $id.'.y_max_value'=> $Max,
          $id.'.labels'     => join(',',@$Xlabels),
          $id.'.PlotType'   => 'XY',
@@ -4893,9 +5280,9 @@ sub DrawXYYGraph {
     $ylabel = '' if (! defined($ylabel));
     my %ValuesHash = 
         (
-         $id.'.title'  => &Apache::lonnet::escape($Title),
-         $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
-         $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
+         $id.'.title'  => &escape($Title),
+         $id.'.xlabel' => &escape($xlabel),
+         $id.'.ylabel' => &escape($ylabel),
          $id.'.labels' => join(',',@$Xlabels),
          $id.'.PlotType' => 'XY',
          $id.'.NumSets' => 2,
@@ -4967,7 +5354,7 @@ Inputs:
 sub chartlink {
     my ($linktext, $sname, $sdomain) = @_;
     my $link = '<a href="/adm/statistics?reportSelected=student_assessment'.
-        '&amp;SelectedStudent='.&Apache::lonnet::escape($sname.':'.$sdomain).
+        '&amp;SelectedStudent='.&escape($sname.':'.$sdomain).
         '&amp;chartoutputmode='.HTML::Entities::encode('html, with all links').
        '">'.$linktext.'</a>';
 }
@@ -4997,6 +5384,7 @@ a hash ref describing the data to be sto
     'chartoutputmode' => 'scalar',
     'chartoutputdata' => 'scalar',
     'Section' => 'array',
+    'Group' => 'array',
     'StudentData' => 'array',
     'Maps' => 'array');
 
@@ -5030,11 +5418,11 @@ sub store_course_settings {
                 if (ref($env{'form.'.$setting})) {
                     $stored_form = join(',',
                                         map {
-                                            &Apache::lonnet::escape($_);
+                                            &escape($_);
                                         } sort(@{$env{'form.'.$setting}}));
                 } else {
                     $stored_form = 
-                        &Apache::lonnet::escape($env{'form.'.$setting});
+                        &escape($env{'form.'.$setting});
                 }
                 # Determine if the array contents are the same.
                 if ($stored_form ne $env{$envname}) {
@@ -5068,7 +5456,7 @@ sub restore_course_settings {
             } elsif ($type eq 'array') {
                 $env{'form.'.$setting} = [ 
                                            map { 
-                                               &Apache::lonnet::unescape($_); 
+                                               &unescape($_); 
                                            } split(',',$env{$envname})
                                            ];
             }
@@ -5079,15 +5467,26 @@ sub restore_course_settings {
 ############################################################
 ############################################################
 
-sub propath {
-    my ($udom,$uname)=@_;
-    $udom=~s/\W//g;
-    $uname=~s/\W//g;
-    my $subdir=$uname.'__';
-    $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/;
-    my $proname="$Apache::lonnet::perlvar{'lonUsersDir'}/$udom/$subdir/$uname";
-    return $proname;
-} 
+sub course_type {
+    my ($cid) = @_;
+    if (!defined($cid)) {
+        $cid = $env{'request.course.id'};
+    }
+    if (defined($env{'course.'.$cid.'.type'})) {
+        return $env{'course.'.$cid.'.type'};
+    } else {
+        return 'Course';
+    }
+}
+
+sub group_term {
+    my $crstype = &course_type();
+    my %names = (
+                  'Course' => 'group',
+                  'Group' => 'team',
+                );
+    return $names{$crstype};
+}
 
 sub icon {
     my ($file)=@_;
@@ -5141,7 +5540,7 @@ sub escape_double {
 sub escape_url {
     my ($url)   = @_;
     my @urlslices = split(/\//, $url,-1);
-    my $lastitem = &Apache::lonnet::escape(pop(@urlslices));
+    my $lastitem = &escape(pop(@urlslices));
     return join('/',@urlslices).'/'.$lastitem;
 }
 =pod