--- loncom/interface/loncommon.pm	2007/12/21 05:19:04	1.627
+++ loncom/interface/loncommon.pm	2008/02/01 23:03:13	1.639
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.627 2007/12/21 05:19:04 raeburn Exp $
+# $Id: loncommon.pm,v 1.639 2008/02/01 23:03:13 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -472,7 +472,10 @@ sub setsec_javascript {
     my ($sec_element,$formname) = @_;
     my $setsections = qq|
 function setSect(sectionlist) {
-    var sectionsArray = sectionlist.split(",");
+    var sectionsArray = new Array();
+    if ((sectionlist != '') && (typeof sectionlist != "undefined")) {
+        sectionsArray = sectionlist.split(",");
+    }
     var numSections = sectionsArray.length;
     document.$formname.$sec_element.length = 0;
     if (numSections == 0) {
@@ -779,10 +782,10 @@ sub helpLatexCheatsheet {
     }
     return '<table><tr><td>'.
 	$addOther .
-	&Apache::loncommon::help_open_topic("Greek_Symbols",'Greek Symbols',
+	&Apache::loncommon::help_open_topic("Greek_Symbols",&mt('Greek Symbols'),
 					    undef,undef,600)
 	.'</td><td>'.
-	&Apache::loncommon::help_open_topic("Other_Symbols",'Other Symbols',
+	&Apache::loncommon::help_open_topic("Other_Symbols",&mt('Other Symbols'),
 					    undef,undef,600)
 	.'</td></tr></table>';
 }
@@ -3667,45 +3670,78 @@ sub get_domainconf {
 
     my %domconfig = &Apache::lonnet::get_dom('configuration',
 					     ['login','rolecolors'],$udom);
-    my %designhash;
+    my (%designhash,%legacy);
     if (keys(%domconfig) > 0) {
         if (ref($domconfig{'login'}) eq 'HASH') {
-            foreach my $key (keys(%{$domconfig{'login'}})) {
-                $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};
+            if (keys(%{$domconfig{'login'}})) {
+                foreach my $key (keys(%{$domconfig{'login'}})) {
+                    $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};
+                }
+            } else {
+                $legacy{'login'} = 1;
             }
+        } else {
+            $legacy{'login'} = 1;
         }
         if (ref($domconfig{'rolecolors'}) eq 'HASH') {
-            foreach my $role (keys(%{$domconfig{'rolecolors'}})) {
-                if (ref($domconfig{'rolecolors'}{$role}) eq 'HASH') {
-                    foreach my $item (keys(%{$domconfig{'rolecolors'}{$role}})) {
-                        $designhash{$udom.'.'.$role.'.'.$item}=$domconfig{'rolecolors'}{$role}{$item};
+            if (keys(%{$domconfig{'rolecolors'}})) {
+                foreach my $role (keys(%{$domconfig{'rolecolors'}})) {
+                    if (ref($domconfig{'rolecolors'}{$role}) eq 'HASH') {
+                        foreach my $item (keys(%{$domconfig{'rolecolors'}{$role}})) {
+                            $designhash{$udom.'.'.$role.'.'.$item}=$domconfig{'rolecolors'}{$role}{$item};
+                        }
                     }
                 }
+            } else {
+                $legacy{'rolecolors'} = 1;
             }
+        } else {
+            $legacy{'rolecolors'} = 1;
         }
-    } else {
-        my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
-        my $designfile =  $designdir.'/'.$udom.'.tab';
-        if (-e $designfile) {
-            if ( open (my $fh,"<$designfile") ) {
-                while (my $line = <$fh>) {
-                    next if ($line =~ /^\#/);
-                    chomp($line);
-                    my ($key,$val)=(split(/\=/,$line));
-                    if ($val) { $designhash{$udom.'.'.$key}=$val; }
+        if (keys(%legacy) > 0) {
+            my %legacyhash = &get_legacy_domconf($udom);
+            foreach my $item (keys(%legacyhash)) {
+                if ($item =~ /^\Q$udom\E\.login/) {
+                    if ($legacy{'login'}) { 
+                        $designhash{$item} = $legacyhash{$item};
+                    }
+                } else {
+                    if ($legacy{'rolecolors'}) {
+                        $designhash{$item} = $legacyhash{$item};
+                    }
                 }
-                close($fh);
             }
         }
-        if (-e '/home/httpd/html/adm/lonDomLogos/'.$udom.'.gif') {
-            $designhash{$udom.'.login.domlogo'} = "/adm/lonDomLogos/$udom.gif";
-        }
+    } else {
+        %designhash = &get_legacy_domconf($udom); 
     }
     &Apache::lonnet::do_cache_new('domainconfig',$udom,\%designhash,
 				  $cachetime);
     return %designhash;
 }
 
+sub get_legacy_domconf {
+    my ($udom) = @_;
+    my %legacyhash;
+    my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
+    my $designfile =  $designdir.'/'.$udom.'.tab';
+    if (-e $designfile) {
+        if ( open (my $fh,"<$designfile") ) {
+            while (my $line = <$fh>) {
+                next if ($line =~ /^\#/);
+                chomp($line);
+                my ($key,$val)=(split(/\=/,$line));
+                if ($val) { $legacyhash{$udom.'.'.$key}=$val; }
+            }
+            close($fh);
+        }
+    }
+    if (-e '/home/httpd/html/adm/lonDomLogos/'.$udom.'.gif') {
+        $legacyhash{$udom.'.login.domlogo'} = "/adm/lonDomLogos/$udom.gif";
+    }
+    return %legacyhash;
+}
+
 =pod
 
 =item * &domainlogo()
@@ -3755,10 +3791,10 @@ Returns: value of designparamter $which
 sub designparm {
     my ($which,$domain)=@_;
     if ($env{'browser.blackwhite'} eq 'on') {
-	if ($which=~/\.(font|alink|vlink|link)$/) {
+	if ($which=~/\.(font|alink|vlink|link|textcol)$/) {
 	    return '#000000';
 	}
-	if ($which=~/\.(pgbg|sidebg)$/) {
+	if ($which=~/\.(pgbg|sidebg|bgcol)$/) {
 	    return '#FFFFFF';
 	}
 	if ($which=~/\.tabbg$/) {
@@ -3777,7 +3813,7 @@ sub designparm {
         $output = $defaultdesign{$which};
     }
     if (($which =~ /^(student|coordinator|author|admin)\.img$/) ||
-        ($which =~ /login\.(img|logo|domlogo)/)) {
+        ($which =~ /login\.(img|logo|domlogo|login)/)) {
         if ($output =~ m{^/(adm|res)/}) {
 	    if ($output =~ m{^/res/}) {
 		my $local_name = &Apache::lonnet::filelocation('',$output);
@@ -4094,18 +4130,25 @@ sub make_attr_string {
 
 Returns a uniform footer for LON-CAPA web pages.
 
-Inputs: none
+Inputs: 1 - optional reference to an args hash
+If in the hash, key for noredirectlink has a value which evaluates to true,
+a 'Continue' link is not displayed if the page contains an
+internal redirect in the <head></head> section,
+i.e., $env{'internal.head.redirect'} exists   
 
 =cut
 
 sub endbodytag {
+    my ($args) = @_;
     my $endbodytag='</body>';
     $endbodytag=&Apache::lontexconvert::jsMath_process()."\n".$endbodytag;
     if ( exists( $env{'internal.head.redirect'} ) ) {
-	$endbodytag=
-	    "<br /><a href=\"$env{'internal.head.redirect'}\">".
-	    &mt('Continue').'</a>'.
-	    $endbodytag;
+        if (!(ref($args) eq 'HASH' && $args->{'noredirectlink'})) {
+	    $endbodytag=
+	        "<br /><a href=\"$env{'internal.head.redirect'}\">".
+	        &mt('Continue').'</a>'.
+	        $endbodytag;
+        }
     }
     return $endbodytag;
 }
@@ -4368,6 +4411,7 @@ td.LC_menubuttons_img {
 }
 .LC_new_mail {
   font-family: $sans;
+  background: $tabbg;
   font-weight: bold;
 }
 
@@ -4454,6 +4498,10 @@ table.LC_aboutme_port tr.LC_even_row td
 table.LC_data_table tr.LC_data_table_highlight td {
   background-color: $data_table_darker;
 }
+table.LC_data_table tr td.LC_leftcol_header {
+  background-color: $data_table_head;
+  font-weight: bold;
+}
 table.LC_data_table tr.LC_empty_row td,
 table.LC_nested tr.LC_empty_row td {
   background-color: #FFFFFF;
@@ -4943,6 +4991,11 @@ span.LC_cusr_emph {
   font-style: italic;
 }
 
+span.LC_cusr_subheading {
+  font-weight: normal;
+  font-size: 85%;
+}
+
 table.LC_docs_documents {
   background: #BBBBBB;
   border-width: 0px;
@@ -5470,7 +5523,7 @@ sub end_page {
     if ($args->{'frameset'}) {
 	$result .= '</frameset>';
     } else {
-	$result .= &endbodytag();
+	$result .= &endbodytag($args);
     }
     $result .= "\n</html>";
 
@@ -5848,6 +5901,8 @@ previous, future, or all.
 6. reference to results object (hash of hashes).
 7. reference to optional userdata hash
 8. reference to optional statushash
+9. flag if privileged users (except those set to unhide in
+   course settings) should be excluded    
 Keys of top level results hash are roles.
 Keys of inner hashes are username:domain, with 
 values set to access type.
@@ -5864,7 +5919,7 @@ of the possibility of multiple values fo
 ###############################################
 
 sub get_course_users {
-    my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata,$statushash) = @_;
+    my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata,$statushash,$hidepriv) = @_;
     my %idx = ();
     my %seclists;
 
@@ -5940,6 +5995,17 @@ sub get_course_users {
                               active   => 'Active',
                               future   => 'Future',
                             );
+        my %nothide;
+        if ($hidepriv) {
+            my %coursehash=&Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+            foreach my $user (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
+                if ($user !~ /:/) {
+                    $nothide{join(':',split(/[\@]/,$user))}=1;
+                } else {
+                    $nothide{$user} = 1;
+                }
+            }
+        }
         foreach my $person (sort(keys(%coursepersonnel))) {
             my $match = 0;
             my $secmatch = 0;
@@ -5973,6 +6039,12 @@ sub get_course_users {
                     $usec = 'none';
                 }
                 if ($uname ne '' && $udom ne '') {
+                    if ($hidepriv) {
+                        if ((&Apache::lonnet::privileged($uname,$udom)) &&
+                            (!$nothide{$uname.':'.$udom})) {
+                            next;
+                        }
+                    }
                     if ($end > 0 && $end < $now) {
                         $status = 'previous';
                     } elsif ($start > $now) {
@@ -7598,6 +7670,8 @@ a hash ref describing the data to be sto
 
 Returns: both routines return nothing
 
+=back
+
 =cut
 
 #######################################################
@@ -7753,7 +7827,7 @@ sub build_recipient_list {
 
 sub commit_customrole {
     my ($udom,$uname,$url,$three,$four,$five,$start,$end) = @_;
-    my $output = &mt('Assigning custom role').' "'.$five.'" by '.$four.'@'.$three.' in '.$url.
+    my $output = &mt('Assigning custom role').' "'.$five.'" by '.$four.':'.$three.' in '.$url.
                          ($start?', '.&mt('starting').' '.localtime($start):'').
                          ($end?', ending '.localtime($end):'').': <b>'.
               &Apache::lonnet::assigncustomrole(
@@ -7816,16 +7890,36 @@ sub commit_studentrole {
         my $secchange = 0;
         my $expire_role_result;
         my $modify_section_result;
-        unless ($oldsec eq '-1') {
-            unless ($sec eq $oldsec) {
+        if ($oldsec ne '-1') { 
+            if ($oldsec ne $sec) {
                 $secchange = 1;
+                my $now = time;
                 my $uurl='/'.$cid;
                 $uurl=~s/\_/\//g;
                 if ($oldsec) {
                     $uurl.='/'.$oldsec;
                 }
                 $oldsecurl = $uurl;
-                $expire_role_result = &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',time);
+                $expire_role_result = 
+                    &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',$now);
+                if ($env{'request.course.sec'} ne '') { 
+                    if ($expire_role_result eq 'refused') {
+                        my @roles = ('st');
+                        my @statuses = ('previous');
+                        my @roledoms = ($one);
+                        my $withsec = 1;
+                        my %roleshash = 
+                            &Apache::lonnet::get_my_roles($uname,$udom,'userroles',
+                                              \@statuses,\@roles,\@roledoms,$withsec);
+                        if (defined ($roleshash{$two.':'.$one.':st:'.$oldsec})) {
+                            my ($oldstart,$oldend) = 
+                                split(':',$roleshash{$two.':'.$one.':st:'.$oldsec});
+                            if ($oldend > 0 && $oldend <= $now) {
+                                $expire_role_result = 'ok';
+                            }
+                        }
+                    }
+                }
                 $result = $expire_role_result;
             }
         }
@@ -7833,18 +7927,38 @@ sub commit_studentrole {
             $modify_section_result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,'','',$cid);
             if ($modify_section_result =~ /^ok/) {
                 if ($secchange == 1) {
-                    $$logmsg .= &mt('Section for [_1] switched from old section: [_2] to new section: [_3].',$uname,$oldsec,$sec).$linefeed;
+                    if ($sec eq '') {
+                        $$logmsg .= &mt('Section for [_1] switched from (possibly expired) old section: [_2] to student role without a section.',$uname,$oldsec).$linefeed;
+                    } else {
+                        $$logmsg .= &mt('Section for [_1] switched from (possibly expired) old section: [_2] to new section: [_3].',$uname,$oldsec,$sec).$linefeed;
+                    }
                 } elsif ($oldsec eq '-1') {
-                    $$logmsg .= &mt('New student role for [_1] in section [_2] in course [_3].',$uname,$sec,$cid).$linefeed;
+                    if ($sec eq '') {
+                        $$logmsg .= &mt('New student role without a section for [_1] in course [_2].',$uname,$cid).$linefeed;
+                    } else {
+                        $$logmsg .= &mt('New student role for [_1] in section [_2] in course [_3].',$uname,$sec,$cid).$linefeed;
+                    }
                 } else {
-                    $$logmsg .= &mt('Student [_1] assigned to unchanged section [_2] in course [_3].',$uname,$sec,$cid).$linefeed;
+                    if ($sec eq '') {
+                        $$logmsg .= &mt('Student [_1] assigned to course [_2] without a section.',$uname,$cid).$linefeed;
+                    } else {
+                        $$logmsg .= &mt('Student [_1] assigned to section [_2] in course [_3].',$uname,$sec,$cid).$linefeed;
+                    }
                 }
             } else {
-                $$logmsg .= &mt('Error when attempting section change for [_1] from old section [_2] to new section: [_3] in course [_4] -error:',$uname,$oldsec,$sec,$cid).' '.$modify_section_result.$linefeed;
+                if ($secchange) {       
+                    $$logmsg .= &mt('Error when attempting section change for [_1] from old section "[_2]" to new section: "[_3]" in course [_4] -error:',$uname,$oldsec,$sec,$cid).' '.$modify_section_result.$linefeed;
+                } else {
+                    $$logmsg .= &mt('Error when attempting to modify role for [_1] for section: "[_2]" in course [_3] -error:',$uname,$sec,$cid).' '.$modify_section_result.$linefeed;
+                }
             }
             $result = $modify_section_result;
         } elsif ($secchange == 1) {
-            $$logmsg .= &mt('Error when attempting to expire role for [_1] in old section [_2] in course [_3] -error: ',$uname,$oldsec,$cid).' '.$expire_role_result.$linefeed;
+            if ($oldsec eq '') {
+                $$logmsg .= &mt('Error when attempting to expire existing role without a section for [_1] in course [_3] -error: ',$uname,$cid).' '.$expire_role_result.$linefeed;
+            } else {
+                $$logmsg .= &mt('Error when attempting to expire existing role for [_1] in section [_2] in course [_3] -error: ',$uname,$oldsec,$cid).' '.$expire_role_result.$linefeed;
+            }
             if ($expire_role_result eq 'refused') {
                 my $newsecurl = '/'.$cid;
                 $newsecurl =~ s/\_/\//g;
@@ -7973,19 +8087,26 @@ sub construct_course {
 	$outcome .= $clonemsg.$linefeed;
 	my %oldcenv=&Apache::lonnet::dump('environment',$$crsudom,$$crsunum);
 # Copy all files
-	&Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid);
+	&Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid,$args->{'datemode'},$args->{'dateshift'});
 # Restore URL
 	$cenv{'url'}=$oldcenv{'url'};
 # Restore title
 	$cenv{'description'}=$oldcenv{'description'};
-# restore grading mode
-	if (defined($oldcenv{'grading'})) {
-	    $cenv{'grading'}=$oldcenv{'grading'};
-	}
 # Mark as cloned
 	$cenv{'clonedfrom'}=$cloneid;
-	delete($cenv{'default_enrollment_start_date'});
-	delete($cenv{'default_enrollment_end_date'});
+# Need to clone grading mode
+        my %newenv=&Apache::lonnet::get('environment',['grading'],$$crsudom,$$crsunum);
+        $cenv{'grading'}=$newenv{'grading'};
+# Do not clone these environment entries
+        &Apache::lonnet::del('environment',
+                  ['default_enrollment_start_date',
+                   'default_enrollment_end_date',
+                   'question.email',
+                   'policy.email',
+                   'comment.email',
+                   'pch.users.denied',
+                   'plc.users.denied'],
+                   $$crsudom,$$crsunum);
     }
 
 #
@@ -8013,7 +8134,6 @@ sub construct_course {
     } else {
         $cenv{'internal.courseowner'} = $args->{'curruser'};
     }
-
     my @badclasses = (); # Used to accumulate sections/crosslistings that did not pass classlist access check for course owner.
     if ($args->{'crssections'}) {
         $cenv{'internal.sectionnums'} = '';
@@ -8073,7 +8193,7 @@ sub construct_course {
     }
     if ($args->{'notify_dc'}) {
         if ($uname ne '') { 
-            push(@notified,$uname.'@'.$udom);
+            push(@notified,$uname.':'.$udom);
         }
     }
     if (@notified > 0) {