--- loncom/interface/lonmsgdisplay.pm	2006/04/26 14:43:03	1.19
+++ loncom/interface/lonmsgdisplay.pm	2006/05/30 12:46:09	1.29
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines for messaging display
 #
-# $Id: lonmsgdisplay.pm,v 1.19 2006/04/26 14:43:03 albertel Exp $
+# $Id: lonmsgdisplay.pm,v 1.29 2006/05/30 12:46:09 www 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;
@@ -259,89 +262,32 @@ sub movemsg {
 # ======================================================= Display a course list
 
 sub discourse {
-    my $r=shift;
-    my $classlist = &Apache::loncoursedata::get_classlist();
-    my $now=time;
-    my %lt=&Apache::lonlocal::texthash('cfa' => 'Check All',
-            'cfs' => 'Check Section/Group',
-            'cfn' => 'Uncheck All');
-    $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;
-            }
-        }
-    }
-
-    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="5" name="chksec" />&nbsp;
-<input type="button" onClick="uncheckall()" value="$lt{'cfn'}" />
-<p>
-ENDDISHEADER
-    my %coursepersonnel=&Apache::lonnet::get_course_adv_roles();
-    $r->print('<table>');
-    foreach my $role (sort keys %coursepersonnel) {
-        foreach (split(/\,/,$coursepersonnel{$role})) {
-            my ($puname,$pudom)=split(/\:/,$_);
-            $r->print('<tr><td><label>'.
-                      '<input type="checkbox" name="send_to_&&&&&&_'.
-                      $puname.':'.$pudom.'" /> '.
-                      &Apache::loncommon::plainname($puname,$pudom).
-                      '</label></td>'.
-                      '<td>('.$_.'),</td><td><i>'.$role.'</i></td></tr>');
-        }
-    }
-    $r->print('</table><table>');
-    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 $key = 'send_to_&&&'.$section.'&&&_'.$student;
-        if (! defined($fullname) || $fullname eq '') { $fullname = $sname; }
-        $r->print('<tr><td><label>'.
-                  qq{<input type="checkbox" name="$key" />}.('&nbsp;'x2).
-                  $fullname.'</label></td><td>'.$sname.':'.$sdom.'</td><td>'.$section.
-                  '</td></tr>');
-    }
-    $r->print('</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
@@ -400,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);
@@ -526,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/) {
@@ -709,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});
@@ -728,7 +674,7 @@ ENDDISHEADER
 	} elsif ($status eq 'deleted') {
 # purge
 	    my ($result,$msg) = 
-		&movemsg(&Apache::lonnet::unescape($origID),$folder,'trash');
+		&movemsg(&unescape($origID),$folder,'trash');
 	    
 	}
     }   
@@ -772,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>');
@@ -830,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) {
@@ -846,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".
@@ -932,6 +880,8 @@ ENDUPLOAD
     }
     if ($broadcast eq 'group') {
        &discourse($r);
+       my $studentsel = &discourse();
+       $r->print($studentsel);
     }
     $r->print('</form>'.
 	      &Apache::lonfeedback::generate_preview_button('compemail','message').
@@ -992,7 +942,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 {
@@ -1005,7 +955,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 {
@@ -1310,7 +1260,7 @@ END
 	
 	my ($setuname,$setudom,$title) = 
 	    &parse_block_record($$records{$record});
-	$title = &HTML::Entities::encode($title,'"<>');
+	$title = &HTML::Entities::encode($title,'"<>&');
         my $settername = &Apache::loncommon::plainname($setuname,$setudom);
         $r->print(&Apache::loncommon::start_data_table_row());
         $r->print(<<"END");
@@ -1486,7 +1436,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;
@@ -1496,17 +1446,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':'').
@@ -1610,7 +1560,7 @@ sub header {
     $r->print(&Apache::loncommon::start_page('Communication and Messages',
 					     $extra));
     $r->print(&Apache::lonhtmlcommon::breadcrumbs
-	      (undef,($title?$title:'Communication and Messages')));
+	      (($title?$title:'Communication and Messages')));
 
 }
 
@@ -1635,14 +1585,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\:/) {
@@ -1687,13 +1637,26 @@ sub sendoffmail {
 	    &statuschange($msgid,'replied',$folder);
 	}
 
+	my $to = $env{'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);
@@ -1703,12 +1666,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}='';
+		}
 	    }
 	}
 
@@ -1777,20 +1744,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') {
@@ -1837,7 +1804,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>');
     }
 }
 
@@ -1858,7 +1825,7 @@ sub handler {
         ['display','replyto','forward','markread','markdel','markunread',
          'sendreply','compose','sendmail','critical','recname','recdom',
          'recordftf','sortedby','block','folder','startdis','interdis',
-	 'showcommentbaseurl','dismode']);
+	 'showcommentbaseurl','dismode','group','subject','text']);
     $sqs='&sortedby='.$env{'form.sortedby'};
 
 # ------------------------------------------------------ They checked for email
@@ -1880,7 +1847,7 @@ sub handler {
     unless ($folder) { 
 	$folder=''; 
     } else {
-	$sqs.='&folder='.&Apache::lonnet::escape($folder);
+	$sqs.='&folder='.&escape($folder);
     }
 # ------------------------------------------------------------ Get Display Mode
 
@@ -1888,7 +1855,7 @@ sub handler {
     unless ($dismode) { 
 	$dismode=''; 
     } else {
-	$sqs.='&dismode='.&Apache::lonnet::escape($dismode);
+	$sqs.='&dismode='.&escape($dismode);
     }
 
 # --------------------------------------------------------------------- Display
@@ -1958,7 +1925,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++;
@@ -1985,7 +1952,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++;