--- loncom/interface/lonmsgdisplay.pm	2006/05/01 19:37:33	1.22
+++ loncom/interface/lonmsgdisplay.pm	2006/07/17 16:26:09	1.37
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines for messaging display
 #
-# $Id: lonmsgdisplay.pm,v 1.22 2006/05/01 19:37:33 albertel Exp $
+# $Id: lonmsgdisplay.pm,v 1.37 2006/07/17 16:26:09 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -125,6 +125,9 @@ use Apache::lonlocal;
 use Apache::loncommunicate;
 use Apache::lonfeedback;
 use Apache::lonrss();
+use Apache::lonselstudent();
+use lib '/home/httpd/lib/perl/';
+use LONCAPA;
 
 # Querystring component with sorting type
 my $sqs;
@@ -214,7 +217,7 @@ sub movemsg {
 # Copy message
     my %message=&Apache::lonnet::get('nohist_email'.$srcsuffix,[$msgid]);
     if (!exists($message{$msgid}) || $message{$msgid} eq '') {
-	if (&Apache::slotrequest::network_error(%message)) {
+	if (&Apache::lonnet::error(%message)) {
 	    return (0,&mt('Message not moved, A network error occurred.'));
 	} else {
 	    return (0,&mt('Message not moved as the message is no longer in the source folder.'));
@@ -223,7 +226,7 @@ sub movemsg {
 
     my $result =&Apache::lonnet::put('nohist_email'.$trgsuffix,
 				     {$msgid => $message{$msgid}});
-    if (&Apache::slotrequest::network_error($result)) {
+    if (&Apache::lonnet::error($result)) {
 	return (0,&mt('Message not moved, A network error occurred.'));
     }
 
@@ -231,12 +234,12 @@ sub movemsg {
     unless ($trgfolder eq 'trash') {
        	my %status=&Apache::lonnet::get('email_status'.$srcsuffix,[$msgid]);
 	# a non-existant status is the mark of an unread msg
-	if (&Apache::slotrequest::network_error(%status)) {
+	if (&Apache::lonnet::error(%status)) {
 	    return (0,&mt('Message copied to new folder but status was not, A network error occurred.'));
 	}
 	my $result=&Apache::lonnet::put('email_status'.$trgsuffix,
 					{$msgid => $status{$msgid}});
-	if (&Apache::slotrequest::network_error($result)) {
+	if (&Apache::lonnet::error($result)) {
 	    return (0,&mt('Message copied to new folder but status was not, A network error occurred.'));
 	}
     }
@@ -246,10 +249,10 @@ sub movemsg {
 	&Apache::lonnet::del('nohist_email'.$srcsuffix,[$msgid]);
     my $result_del_stat =
 	&Apache::lonnet::del('email_status'.$srcsuffix,[$msgid]);
-    if (&Apache::slotrequest::network_error($result_del_msg)) {
+    if (&Apache::lonnet::error($result_del_msg)) {
 	return (0,&mt('Message copied, but unable to delete the original from the source folder.'));
     }
-    if (&Apache::slotrequest::network_error($result_del_stat)) {
+    if (&Apache::lonnet::error($result_del_stat)) {
 	return (0,&mt('Message copied, but unable to delete the original status from the source folder.'));
     }
 
@@ -259,133 +262,32 @@ sub movemsg {
 # ======================================================= Display a course list
 
 sub discourse {
-    my $r=shift;
-    my $classlist = &Apache::loncoursedata::get_classlist();
-    my ($classgroups,$studentgroups) = 
-	&Apache::loncoursedata::get_group_memberships($classlist);
-    my %lt=&Apache::lonlocal::texthash('cfa' => 'Check All',
-            'cfs' => 'Check Section/Group',
-            'cfn' => 'Uncheck All');
-    if (defined($env{'form.group'})) {
-        $r->print('<input type="hidden" name="group" value="'.
-                  $env{'form.group'}.'" />'."\n");
-    }
-    $r->print(<<ENDDISHEADER);
-<input type="hidden" name="sendmode" value="group" />
-<script pe="text/javascript">
-    function checkall() {
-	for (i=0; i<document.forms.compemail.elements.length; i++) {
-            if 
-          (document.forms.compemail.elements[i].name.indexOf('send_to_')==0) {
-	      document.forms.compemail.elements[i].checked=true;
-            }
-        }
-    }
-
-    function checksec() {
-	for (i=0; i<document.forms.compemail.elements.length; i++) {
-            if 
-          (document.forms.compemail.elements[i].name.indexOf
-           ('send_to_&&&'+document.forms.compemail.chksec.value+'&&&')==0) {
-	      document.forms.compemail.elements[i].checked=true;
-            }
-            if
-          (document.forms.compemail.elements[i].name.indexOf
-           ('group_&&&'+document.forms.compemail.chksec.value+'&&&_')==0) {
-              var count = i - document.forms.compemail.elements[i].value;
-              document.forms.compemail.elements[count].checked=true;
-            }
-        }
-    }
-
-    function uncheckall() {
-	for (i=0; i<document.forms.compemail.elements.length; i++) {
-            if 
-          (document.forms.compemail.elements[i].name.indexOf('send_to_')==0) {
-	      document.forms.compemail.elements[i].checked=false;
-            }
-        }
-    }
-</script>
-<input type="button" onClick="checkall()" value="$lt{'cfa'}" />&nbsp;
-<input type="button" onClick="checksec()" value="$lt{'cfs'}" />
-<input type="text" size="15" name="chksec" value="$env{'form.group'}" />&nbsp;
-<input type="button" onClick="uncheckall()" value="$lt{'cfn'}" />
-<p>
-ENDDISHEADER
-    my %coursepersonnel=&Apache::lonnet::get_course_adv_roles();
-    $r->print(&Apache::loncommon::start_data_table());
-    if (keys(%coursepersonnel) > 0) {
-        $r->print('<h3>Non-students</h3>');
-        $r->print(&Apache::loncommon::start_data_table());
-        $r->print('<tr><th>Name</th><th>Username:Domain</th><th>Role</th></tr>');
-        foreach my $role (sort(keys(%coursepersonnel))) {
-            foreach my $user (split(/\,/,$coursepersonnel{$role})) {
-                my ($puname,$pudom)=split(/\:/,$user);
-                $r->print(&Apache::loncommon::start_data_table_row());
-                $r->print('<td><label>'.
-                          '<input type="checkbox" name="send_to_&&&&&&_'.
-                          $puname.':'.$pudom.'" /> '.
-                          &Apache::loncommon::plainname($puname,$pudom).
-                          '</label></td>'.
-                          '<td>('.$user.'),</td><td><i>'.$role.'</i></td>');
-                $r->print(&Apache::loncommon::end_data_table_row());
-            }
-        }
-        $r->print(&Apache::loncommon::end_data_table());
-    }
-    if (keys(%{$classlist}) > 0) {
-        $r->print('<h3>Students</h3>');
-        $r->print(&Apache::loncommon::start_data_table());
-        $r->print('<tr><th>Name</th><th>Username:Domain</th><th>Section</th><th>Groups</th></tr>');
-        my $sort = sub {
-	    my $aname=lc($classlist->{$a}[&Apache::loncoursedata::CL_FULLNAME()]);
-	    if (!$aname) { $aname=$a; }
-	    my $bname=lc($classlist->{$b}[&Apache::loncoursedata::CL_FULLNAME()]);
-	    if (!$bname) { $bname=$b; }
-	    return $aname cmp $bname;
-        };
-        foreach my $student (sort $sort (keys(%{$classlist}))) {
-	    my $info=$classlist->{$student};
-            my ($sname,$sdom,$status,$fullname,$section) =
-                (@{$info}[&Apache::loncoursedata::CL_SNAME(),
-                          &Apache::loncoursedata::CL_SDOM(),
-                          &Apache::loncoursedata::CL_STATUS(),
-                          &Apache::loncoursedata::CL_FULLNAME(),
-                          &Apache::loncoursedata::CL_SECTION()]);
-            next if ($status ne 'Active');
-	    next if ($env{'request.course.sec'} &&
-		     $section ne $env{'request.course.sec'});
-            my @studentsgroups = 
-		&Apache::loncoursedata::get_students_groups($student,$status,
-							    $classgroups);
-            my $grouplist = join(', ',@studentsgroups);
-            my $key = 'send_to_&&&'.$section.'&&&_'.$student;
-            if (! defined($fullname) || $fullname eq '') {$fullname = $sname;}
-            my $checked = '';
-            my $groupcount = 0;
-            my $groupitems;
-            $r->print(&Apache::loncommon::start_data_table_row());
-            $r->print('<td><label>');
-            foreach my $group (@studentsgroups) {
-                $groupcount ++;
-                $groupitems .= ('<input type="hidden" name="group_&&&'.
-                                $group.'&&&_'.$student.'" value="'.
-                                $groupcount.'" />');
-                if (defined($env{'form.group'})) {
-                    if ($env{'form.group'} eq $group) {
-                        $checked = 'checked="checked"';
-                    }
-                }
-            }
-            $r->print(qq{<input type="checkbox" name="$key" $checked />}.
-                      ('&nbsp;'x2).$fullname.'</label>'.$groupitems.
-                      '</td><td>'.$sname.':'.$sdom.'</td><td>'.$section.
-                      '</td><td>'.$grouplist.'</td>');
-            $r->print(&Apache::loncommon::end_data_table_row());
-        }
-        $r->print(&Apache::loncommon::end_data_table());
-    }
+    my $result;
+    my ($course_personnel,
+	$current_members,
+	$expired_members,
+	$future_members) = 
+	    &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'});
+    unshift @$current_members, (@$course_personnel);
+    my %defaultUsers;
+
+    $result = &Apache::lonselstudent::render_student_list($current_members,
+							  "compemail",
+							  "current",
+							  \%defaultUsers,
+							  1,"selectedusers",1);
+
+    $result .= &Apache::lonselstudent::render_student_list($expired_members,
+							   "compemail",
+							   "expired",
+							   \%defaultUsers,
+							   1, "selectedusers",0);
+    $result .= &Apache::lonselstudent::render_student_list($future_members,
+							   "compemail",
+							   "future",
+							   \%defaultUsers,
+							   1, "selectedusers", 0);
+    return $result;
 }
 
 # ==================================================== Display Critical Message
@@ -418,7 +320,7 @@ $content{'sendername'}.':'.
     # Check to see if there were any messages.
     if ($result eq '') {
         $result = "<h2>".&mt('You have no critical messages.')."</h2>".
-	    '<a href="/adm/roles">'.&mt('Select a course').'</a><br />'.
+	    '<a href="/adm/roles">'.&mt('Select a course or group').'</a><br />'.
             '<a href="/adm/email">'.&mt('Communicate').'</a>';
     } else {
         $r->print($header);
@@ -444,7 +346,7 @@ sub sortedmessages {
     }
 
     foreach my $msgid (@messages) {
-	my $esc_msgid=&Apache::lonnet::escape($msgid);
+	my $esc_msgid=&escape($msgid);
 	my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid)=
 	    &Apache::lonmsg::unpackmsgid($esc_msgid,$folder,undef,
 					 \%status_cache);
@@ -551,7 +453,7 @@ sub disnew {
     my %lt=&Apache::lonlocal::texthash(
 				       'nm' => 'New Messages',
 				       'su' => 'Subject',
-                                       'co' => 'Course',
+                                       'co' => 'Course/Group',
 				       'da' => 'Date',
 				       'us' => 'Username',
 				       'op' => 'Open',
@@ -570,7 +472,7 @@ sub disnew {
 	&Apache::lonnet::get('email_status',\@msgids);
     my %descriptions;
     foreach (@msgids) {
-	my $msgid=&Apache::lonnet::escape($_);
+	my $msgid=&escape($_);
         my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=
 	    &Apache::lonmsg::unpackmsgid($msgid,undef,undef,\%status_cache);
         if (defined($sendtime) && $sendtime!~/error/) {
@@ -669,7 +571,7 @@ sub disfolder {
     function uncheckall() {
 	for (i=0; i<document.forms.disall.elements.length; i++) {
             if 
-          (document.forms.disall.elements[i].name.indexOf('delmark_')==0) {
+          (document.forms.disall.elements[i].name.indexof('delmark_')==0) {
 	      document.forms.disall.elements[i].checked=false;
             }
         }
@@ -720,9 +622,9 @@ ENDDISHEADER
     }
     $r->print('</th><th>');
     if ($env{'form.sortedby'} eq "revcourse") {
-        $r->print('<a href = "?sortedby=course'.$fsqs.'">'.&mt('Course').'</a>');
+        $r->print('<a href = "?sortedby=course'.$fsqs.'">'.&mt('Course/Group').'</a>');
     } else {
-        $r->print('<a href = "?sortedby=revcourse'.$fsqs.'">'.&mt('Course').'</a>');
+        $r->print('<a href = "?sortedby=revcourse'.$fsqs.'">'.&mt('Course/Group').'</a>');
     }
     $r->print('</th><th>');
     if ($env{'form.sortedby'} eq "revstatus") {
@@ -753,7 +655,7 @@ ENDDISHEADER
 		    $dis_name   = join('<br />',@{$recv_name});
 		    $dis_domain = join('<br />',@{$recv_domain});
 		} else {
-		    my $msg_id  = &Apache::lonnet::unescape($origID);
+		    my $msg_id  = &unescape($origID);
 		    my %message = &Apache::lonnet::get('nohist_email'.$suffix,
 						       [$msg_id]);
 		    my %content = &Apache::lonmsg::unpackagemsg($message{$msg_id});
@@ -772,7 +674,7 @@ ENDDISHEADER
 	} elsif ($status eq 'deleted') {
 # purge
 	    my ($result,$msg) = 
-		&movemsg(&Apache::lonnet::unescape($origID),$folder,'trash');
+		&movemsg(&unescape($origID),$folder,'trash');
 	    
 	}
     }   
@@ -816,15 +718,15 @@ sub compout {
 	     'Broadcast Message');
     } elsif ($forwarding) {
 	&Apache::lonhtmlcommon::add_breadcrumb
-        ({href=>"/adm/email?display=".&Apache::lonnet::escape($forwarding),
+        ({href=>"/adm/email?display=".&escape($forwarding),
           text=>"Display Message"});
-	&printheader($r,'/adm/email?forward='.&Apache::lonnet::escape($forwarding),
+	&printheader($r,'/adm/email?forward='.&escape($forwarding),
 	     'Forwarding a Message');
     } elsif ($replying) {
 	&Apache::lonhtmlcommon::add_breadcrumb
-        ({href=>"/adm/email?display=".&Apache::lonnet::escape($replying),
+        ({href=>"/adm/email?display=".&escape($replying),
           text=>"Display Message"});
-	&printheader($r,'/adm/email?replyto='.&Apache::lonnet::escape($replying),
+	&printheader($r,'/adm/email?replyto='.&escape($replying),
 	     'Replying to a Message');
     } elsif ($replycrit) {
 	$r->print('<h3>'.&mt('Replying to a Critical Message').'</h3>');
@@ -874,7 +776,7 @@ sub compout {
 	$dismsg=&mt('Forwarded message from').' '.
 	    $content{'sendername'}.' '.&mt('at').' '.$content{'senderdomain'};
 	if ($content{'baseurl'}) {
-	    $disbase='<input type="hidden" name="baseurl" value="'.&Apache::lonnet::escape($content{'baseurl'}).'" />';
+	    $disbase='<input type="hidden" name="baseurl" value="'.&escape($content{'baseurl'}).'" />';
 	}
     }
     if ($replying) {
@@ -890,18 +792,20 @@ sub compout {
 	$dismsg=~s/\f/\n/g;
 	$dismsg=~s/\n+/\n\> /g;
 	if ($content{'baseurl'}) {
-	    $disbase='<input type="hidden" name="baseurl" value="'.&Apache::lonnet::escape($content{'baseurl'}).'" />';
+	    $disbase='<input type="hidden" name="baseurl" value="'.&escape($content{'baseurl'}).'" />';
 	    if ($env{'user.adv'}) {
 		$disbase.='<label><input type="checkbox" name="storebasecomment" />'.&mt('Store message for re-use').
 		    '</label> <a href="/adm/email?showcommentbaseurl='.
-		    &Apache::lonnet::escape($content{'baseurl'}).'" target="comments">'.
+		    &escape($content{'baseurl'}).'" target="comments">'.
 		    &mt('Show re-usable messages').'</a><br />';
 	    }
 	}
     }
     my $citation=&displayresource(%content);
     if ($env{'form.recdom'}) { $defdom=$env{'form.recdom'}; }
-      $r->print(
+    if ($env{'form.text'}) { $dismsg=$env{'form.text'}; }
+    if ($env{'form.subject'}) { $dissub=$env{'form.subject'}; }
+    $r->print(
                 '<form action="/adm/email"  name="compemail" method="post"'.
                 ' enctype="multipart/form-data">'."\n".
                 '<input type="hidden" name="sendmail" value="on" />'."\n".
@@ -976,6 +880,11 @@ ENDUPLOAD
     }
     if ($broadcast eq 'group') {
        &discourse($r);
+       my $studentsel = &discourse();
+       $r->print($studentsel);
+    }
+    if ($env{'form.displayedcrit'}) {
+	$r->print('<input type="hidden" name="displayedcrit" value="true" />');
     }
     $r->print('</form>'.
 	      &Apache::lonfeedback::generate_preview_button('compemail','message').
@@ -1036,7 +945,7 @@ sub disfacetoface {
             $result .='<h3>'.&mt('Broadcast Message').'</h3>';
             if ($content{'subject'}=~/^Broadcast\./) {
                 if (defined($content{'coursemsgid'})) {
-                    my $crsmsgid = &Apache::lonnet::escape($content{'coursemsgid'});
+                    my $crsmsgid = &escape($content{'coursemsgid'});
                     my $broadcast_message = &general_message($crsmsgid);
                     $content{'message'} = '<b>'.&mt('Subject').': '.$content{'message'}.'</b><br />'.$broadcast_message;
                 } else {
@@ -1049,7 +958,7 @@ sub disfacetoface {
         } else {
             $result.='<h3>'.&mt('Critical Message').'</h3>';
             if (defined($content{'coursemsgid'})) {
-                my $crsmsgid=&Apache::lonnet::escape($content{'coursemsgid'});
+                my $crsmsgid=&escape($content{'coursemsgid'});
                 my $critical_message = &general_message($crsmsgid);
                 $content{'message'} = '<b>'.&mt('Subject').': '.$content{'message'}.'</b><br />'.$critical_message;
             } else {
@@ -1070,10 +979,11 @@ $content{'sendername'}.':'.
      }
     # Check to see if there were any messages.
     if ($result eq '') {
+        my $lctype = lc(&Apache::loncommon::course_type());
 	if ($target ne 'tex') { 
-	    $r->print("<p><b>".&mt("No notes, face-to-face discussion records, critical messages, or broadcast messages in this course.")."</b></p>");
+	    $r->print("<p><b>".&mt('No notes, face-to-face discussion records, critical messages, or broadcast messages in this [_1].',$lctype)."</b></p>");
 	} else {
-	    $r->print('\textbf{'.&mt("No notes, face-to-face discussion records, critical messages or broadcast messages in this course.").'}\\\\');
+	    $r->print('\textbf{'.&mt('No notes, face-to-face discussion records, critical messages or broadcast messages in this [_1].',$lctype).'}\\\\');
 	}
     } else {
        $r->print($result);
@@ -1102,6 +1012,9 @@ sub facetoface {
 	$r->print('Not allowed');
 	return;
     }
+    my $crstype = &Apache::loncommon::course_type();
+    my $leaders = ($crstype eq 'Group') ? 'coordinators and leaders'
+                                        : 'faculty and staff';
     &printheader($r,
 		 '/adm/email?recordftf=query',
 		 "User Notes, Face-to-Face, Critical Messages, Broadcast Messages");
@@ -1119,9 +1032,9 @@ sub facetoface {
 	('stdselect','recuname','recdomain');
     my %lt=&Apache::lonlocal::texthash('user' => 'Username',
 				       'dom' => 'Domain',
-				       'head' => 'User Notes, Records of Face-To-Face Discussions, Critical Messages, and Broadcast Messages in Course',
+				       'head' => "User Notes, Records of Face-To-Face Discussions, Critical Messages, and Broadcast Messages in $crstype",
 				       'subm' => 'Retrieve discussion and message records',
-				       'newr' => 'New Record (record is visible to course faculty and staff)',
+				       'newr' => 'New Record (record is visible to '.lc($crstype).' '.$leaders.')',
 				       'post' => 'Post this Record');
     $r->print(<<"ENDTREC");
 <h3>$lt{'head'}</h3>
@@ -1142,13 +1055,9 @@ ENDTREC
         ($env{'form.recdomain'}) && ($env{'form.recuname'})) {
         chomp($env{'form.newrecord'});
         if ($env{'form.newrecord'}) {
-           my $recordtxt = $env{'form.newrecord'};
-           &Apache::lonmsg::user_normal_msg_raw(
-            $env{'course.'.$env{'request.course.id'}.'.num'},
-            $env{'course.'.$env{'request.course.id'}.'.domain'},
-            &mt('Record').
-	     ' ['.$env{'form.recuname'}.':'.$env{'form.recdomain'}.']',
-	    $recordtxt);
+	    &Apache::lonmsg::store_instructor_comment($env{'form.newrecord'},
+						      $env{'form.recuname'},
+						      $env{'form.recdomain'});
         }
         $r->print('<h3>'.&Apache::loncommon::plainname($env{'form.recuname'},
 				     $env{'form.recdomain'}).'</h3>');
@@ -1180,10 +1089,12 @@ sub examblock {
 	$r->print('Not allowed');
 	return;
     }
+    my $usertype = (&Apache::loncommon::course_type() eq 'Group') ? 'members'
+	                                                          : 'students';
     my %lt=&Apache::lonlocal::texthash(
             'comb' => 'Communication Blocking',
             'cbds' => 'Communication blocking during scheduled exams',
-            'desc' => 'You can use communication blocking to prevent students enrolled in this course from displaying LON-CAPA messages sent by other students during an online exam. As blocking of communication could potentially interrupt legitimate communication between students who are also both enrolled in a different LON-CAPA course, please be careful that you select the correct start and end times for your scheduled exam when setting or modifying these parameters.',
+            'desc' => "You can use communication blocking to prevent $usertype enrolled in this course from displaying LON-CAPA messages sent by other $usertype during an online exam. As blocking of communication could potentially interrupt legitimate communication between $usertype who are also both enrolled in a different LON-CAPA course, please be careful that you select the correct start and end times for your scheduled exam when setting or modifying these parameters.",
              'mecb' => 'Modify existing communication blocking periods',
              'ncbc' => 'No communication blocks currently stored'
     );
@@ -1471,7 +1382,7 @@ sub build_block_table {
     my ($r,$startblock,$endblock,$setters) = @_;
     my %lt = &Apache::lonlocal::texthash(
         'cacb' => 'Currently active communication blocks',
-        'cour' => 'Course',
+        'cour' => 'Course/Group',
         'dura' => 'Duration',
         'blse' => 'Block set by'
     );
@@ -1515,6 +1426,8 @@ sub displaymessage {
     my $startblock = 0;
     my $endblock = 0;
     my $numblocked = 0;
+    my $crstype = &Apache::loncommon::course_type();
+
 # info to generate "next" and "previous" buttons and check if message is blocked
     &blockcheck(\%setters,\$startblock,\$endblock);
     my @messages=&sortedmessages(\%blocked,$startblock,$endblock,\$numblocked,$folder);
@@ -1530,7 +1443,7 @@ sub displaymessage {
 
     my $counter=0;
     $r->print('<pre>');
-    my $escmsgid=&Apache::lonnet::escape($msgid);
+    my $escmsgid=&escape($msgid);
     foreach (@messages) {
 	if ($_->[5] eq $escmsgid){
 	    last;
@@ -1540,17 +1453,17 @@ sub displaymessage {
     $r->print('</pre>');
     my $number_of_messages = scalar(@messages); #subtract 1 for last index
 # start output
-    &printheader($r,'/adm/email?display='.&Apache::lonnet::escape($msgid),'Display a Message','',$content{'baseurl'});
+    &printheader($r,'/adm/email?display='.&escape($msgid),'Display a Message','',$content{'baseurl'});
     my %courseinfo=&Apache::lonnet::coursedescription($content{'courseid'});
 # Functions
     $r->print('<table border="2" width="100%"><tr bgcolor="#FFFFAA"><td>'.&mt('Functions').':</td>'.
-	      '<td><a href="/adm/email?replyto='.&Apache::lonnet::escape($msgid).$sqs.
+	      '<td><a href="/adm/email?replyto='.&escape($msgid).$sqs.
 	      '"><b>'.&mt('Reply').'</b></a></td>'.
-	      '<td><a href="/adm/email?forward='.&Apache::lonnet::escape($msgid).$sqs.
+	      '<td><a href="/adm/email?forward='.&escape($msgid).$sqs.
 	      '"><b>'.&mt('Forward').'</b></a></td>'.
-	      '<td><a href="/adm/email?markunread='.&Apache::lonnet::escape($msgid).$sqs.
+	      '<td><a href="/adm/email?markunread='.&escape($msgid).$sqs.
 	      '"><b>'.&mt('Mark Unread').'</b></a></td>'.
-	      '<td><a href="/adm/email?markdel='.&Apache::lonnet::escape($msgid).$sqs.
+	      '<td><a href="/adm/email?markdel='.&escape($msgid).$sqs.
 	      '"><b>'.&mt('Delete').'</b></a></td>'.
 	      '<td><a href="/adm/email?'.$sqs.
 	      ($env{'form.dismode'} eq 'new'?'&folder=new':'').
@@ -1596,8 +1509,8 @@ sub displaymessage {
 	      $content{'sendername'}.' at '.
 	      $content{'senderdomain'}.') ':'<br /><b>'.&mt('To').':</b> '.
               $tolist).
-	      ($content{'courseid'}?'<br /><b>'.&mt('Course').':</b> '.$courseinfo{'description'}.
-	       ($content{'coursesec'}?' ('.&mt('Group/Section').': '.$content{'coursesec'}.')':''):'').
+	      ($content{'courseid'}?'<br /><b>'.&mt($crstype).':</b> '.$courseinfo{'description'}.
+	       ($content{'coursesec'}?' ('.&mt('Section').': '.$content{'coursesec'}.')':''):'').
 	      '<br /><b>'.&mt('Time').':</b> '.$content{'time'}.
 	      ($content{'baseurl'}?'<br /><b>'.&mt('Refers to').':</b> <a href="'.$content{'baseurl'}.'">'.
 	       $content{'baseurl'}.' ('.&Apache::lonnet::gettitle($content{'baseurl'}).')</a>':'').
@@ -1679,14 +1592,14 @@ sub storecomment {
 	    $cleanmsgtxt.=$_."\n";
 	}
     }
-    my $key=&Apache::lonnet::escape($env{'form.baseurl'}).'___'.time;
+    my $key=&escape($env{'form.baseurl'}).'___'.time;
     &Apache::lonnet::put('nohist_stored_comments',{ $key => $cleanmsgtxt });
 }
 
 sub storedcommentlisting {
     my ($r)=@_;
     my %msgs=&Apache::lonnet::dump('nohist_stored_comments',undef,undef,
-       '^'.&Apache::lonnet::escape(&Apache::lonnet::escape($env{'form.showcommentbaseurl'})));
+       '^'.&escape(&escape($env{'form.showcommentbaseurl'})));
     $r->print(&Apache::loncommon::start_page('Stored Comment Listing',undef,
 					     {'onlybody' => 1}));
     if ((keys %msgs)[0]=~/^error\:/) {
@@ -1731,13 +1644,27 @@ sub sendoffmail {
 	    &statuschange($msgid,'replied',$folder);
 	}
 
+	my @to =
+	    &Apache::loncommon::get_env_multiple('form.selectedusers_forminput');
+	my $mode = $env{'form.sendmode'};
+
 	my %toaddr;
-	if ($env{'form.sendmode'} eq 'group') {
-	    foreach my $address (keys(%env)) {
-		if ($address=~/^form\.send\_to\_\&\&\&[^\&]*\&\&\&\_(.+)$/) {
-		    $toaddr{$1}='';
+	if (@to) {
+	    foreach my $dest (@to) {
+		my ($user,$domain) = split(/:/, $dest);
+		if (($user ne '') && ($domain ne '')) {
+		    my $address = $user.":".$domain; # How the code below expects it.
+		    $toaddr{$address} = '';
 		}
 	    }
+	}
+
+	if ($env{'form.sendmode'} eq 'group') {
+	     foreach my $address (keys(%env)) {
+	 	if ($address=~/^form\.send\_to\_\&\&\&[^\&]*\&\&\&\_(.+)$/) {
+	 	    $toaddr{$1}='';
+	 	}
+	    }
 	} elsif ($env{'form.sendmode'} eq 'upload') {
 	    foreach my $line (split(/[\n\r\f]+/,$env{'form.upfile'})) {
 		my ($rec,$txt)=split(/\s*\:\s*/,$line);
@@ -1747,12 +1674,16 @@ sub sendoffmail {
 		}
 	    }
 	} else {
-	    $toaddr{$env{'form.recuname'}.':'.$env{'form.recdomain'}}='';
+	    if (($env{'form.recuname'} ne '') && ($env{'form.recdomain'} ne '')) {
+		$toaddr{$env{'form.recuname'}.':'.$env{'form.recdomain'}}='';
+	    }
 	}
 	if ($env{'form.additionalrec'}) {
 	    foreach (split(/\,/,$env{'form.additionalrec'})) {
 		my ($auname,$audom)=split(/\@/,$_);
-		$toaddr{$auname.':'.$audom}='';
+		if (($auname ne "") && ($audom ne "")) {
+		    $toaddr{$auname.':'.$audom}='';
+		}
 	    }
 	}
 
@@ -1821,20 +1752,20 @@ sub sendoffmail {
             my ($specialmsgid,$specialresult);
             my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
             my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
-            my $course_str = &Apache::lonnet::escape('['.$cnum.':'.$cdom.']');
+            my $course_str = &escape('['.$cnum.':'.$cdom.']');
 
             if ($numspecial) {
                 $specialresult = &Apache::lonmsg::user_normal_msg_raw($cnum,$cdom,$subj_prefix.
                     ' '.$course_str,$savemsg,undef,undef,undef,
                     undef,undef,\$specialmsgid);
-                $specialmsgid = &Apache::lonnet::unescape($specialmsgid);
+                $specialmsgid = &unescape($specialmsgid);
             }
             if ($specialresult eq 'ok') {
                 my $record_sent;
                 my @recusers;
                 my @recudoms;
                 my ($stamp,$crssubj,$msgname,$msgdom,$msgcount,$context,$pid) =
-		    split(/\:/,&Apache::lonnet::unescape($specialmsgid));
+		    split(/\:/,&unescape($specialmsgid));
 
                 foreach my $recipient (sort(keys(%toaddr))) {
                     if ($specialmsg_status{$recipient} eq 'ok') {
@@ -1881,7 +1812,7 @@ sub sendoffmail {
 	}
     } else {
 	$r->print('<p><span class="LC_error">'.&mt('Could not deliver message').'</span> '.
-		  &mt('Please use the browser "Back" button and correct the recipient addresses').'</p>');
+		  &mt('Please use the browser "Back" button and correct the recipient addresses '."($sendstatus)").'</p>');
     }
 }
 
@@ -1902,7 +1833,7 @@ sub handler {
         ['display','replyto','forward','markread','markdel','markunread',
          'sendreply','compose','sendmail','critical','recname','recdom',
          'recordftf','sortedby','block','folder','startdis','interdis',
-	 'showcommentbaseurl','dismode','group']);
+	 'showcommentbaseurl','dismode','group','subject','text']);
     $sqs='&sortedby='.$env{'form.sortedby'};
 
 # ------------------------------------------------------ They checked for email
@@ -1924,7 +1855,7 @@ sub handler {
     unless ($folder) { 
 	$folder=''; 
     } else {
-	$sqs.='&folder='.&Apache::lonnet::escape($folder);
+	$sqs.='&folder='.&escape($folder);
     }
 # ------------------------------------------------------------ Get Display Mode
 
@@ -1932,7 +1863,7 @@ sub handler {
     unless ($dismode) { 
 	$dismode=''; 
     } else {
-	$sqs.='&dismode='.&Apache::lonnet::escape($dismode);
+	$sqs.='&dismode='.&escape($dismode);
     }
 
 # --------------------------------------------------------------------- Display
@@ -1968,6 +1899,7 @@ sub handler {
 	&compout($r,'',$env{'form.replyto'},undef,undef,$folder,$dismode);
     } elsif ($env{'form.confirm'}) {
 	&printheader($r,'','Confirmed Receipt');
+	my $replying = 0;
 	foreach (keys %env) {
 	    if ($_=~/^form\.rec\_(.*)$/) {
 		$r->print('<b>'.&mt('Confirming Receipt').':</b> '.
@@ -1978,9 +1910,12 @@ sub handler {
 		$r->print('<b>'.&mt('Confirming Receipt').':</b> '.
 			  &Apache::lonmsg::user_crit_received($msgid).'<br>');
 		&compout($r,'','','',$msgid);
+		$replying = 1;
 	    }
 	}
-	&discrit($r);
+	if (!$replying) {
+	    &discrit($r);
+	}
     } elsif ($env{'form.critical'}) {
 	&printheader($r,'','Displaying Critical Messages');
 	&discrit($r);
@@ -2002,7 +1937,7 @@ sub handler {
 	foreach my $key (keys(%env)) {
 	    if ($key=~/^form\.delmark_(.*)$/) {
 		my ($result,$msg) =
-		    &movemsg(&Apache::lonnet::unescape($1),$folder,
+		    &movemsg(&unescape($1),$folder,
 			     $env{'form.movetofolder'});
 		if ($result) {
 		    $total++;
@@ -2029,7 +1964,7 @@ sub handler {
 	foreach my $key (keys(%env)) {
 	    if ($key=~/^form\.delmark_(.*)$/) {
 		my ($result,$msg) = 
-		    &statuschange(&Apache::lonnet::unescape($1),'deleted',
+		    &statuschange(&unescape($1),'deleted',
 				  $folder);
 		if ($result) {
 		    $total++;
@@ -2074,7 +2009,9 @@ sub handler {
 				      $env{'form.subject'},
 				      $env{'form.message'},'/adm/communicate','public');
 	}
-	&disall($r,($folder?$folder:$dismode));
+	if (!$env{'form.displayedcrit'}) {
+	    &disall($r,($folder?$folder:$dismode));
+	}
     } elsif ($env{'form.newfolder'}) {
 	&printheader($r,'','New Folder');
 	&makefolder($env{'form.newfolder'});