--- loncom/interface/lonmsg.pm	2005/11/18 13:35:30	1.155
+++ loncom/interface/lonmsg.pm	2005/11/28 18:32:39	1.157
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines for messaging
 #
-# $Id: lonmsg.pm,v 1.155 2005/11/18 13:35:30 www Exp $
+# $Id: lonmsg.pm,v 1.157 2005/11/28 18:32:39 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -126,7 +126,7 @@ my $interdis;
 
 sub packagemsg {
     my ($subject,$message,$citation,$baseurl,$attachmenturl,
-	$recuser,$recdomain)=@_;
+	$recuser,$recdomain,$msgid)=@_;
     $message =&HTML::Entities::encode($message,'<>&"');
     $citation=&HTML::Entities::encode($citation,'<>&"');
     $subject =&HTML::Entities::encode($subject,'<>&"');
@@ -141,10 +141,12 @@ sub packagemsg {
     $msgcount++;
     my $partsubj=$subject;
     $partsubj=&Apache::lonnet::escape($partsubj);
-    my $msgid=&Apache::lonnet::escape(
+    unless(defined($msgid)) {
+        $msgid=&Apache::lonnet::escape(
            $now.':'.$partsubj.':'.$env{'user.name'}.':'.
            $env{'user.domain'}.':'.$msgcount.':'.
            $env{'request.course.id'}.':'.$$);
+    }
     my $result='<sendername>'.$env{'user.name'}.'</sendername>'.
            '<senderdomain>'.$env{'user.domain'}.'</senderdomain>'.
            '<subject>'.$subject.'</subject>'.
@@ -161,10 +163,17 @@ sub packagemsg {
 	   '<coursesec>'.$env{'request.course.sec'}.'</coursesec>'.
 	   '<role>'.$env{'request.role'}.'</role>'.
 	   '<resource>'.$env{'request.filename'}.'</resource>'.
-           '<msgid>'.$msgid.'</msgid>'.
-	   '<recuser>'.$recuser.'</recuser>'.
-	   '<recdomain>'.$recdomain.'</recdomain>'.
-	   '<message>'.$message.'</message>';
+           '<msgid>'.$msgid.'</msgid>';
+    if (ref($recuser) eq 'ARRAY') {
+        for (my $i=0; $i<@{$recuser}; $i++) {
+            $result .= '<recuser>'.$$recuser[$i].'</recuser>'.
+                       '<recdomain>'.$$recdomain[$i].'</recdomain>';
+        }
+    } else {
+        $result .= '<recuser>'.$recuser.'</recuser>'.
+                   '<recdomain>'.$recdomain.'</recdomain>';
+    }
+    $result .= '<message>'.$message.'</message>';
     if (defined($citation)) {
 	$result.='<citation>'.$citation.'</citation>';
     }
@@ -188,7 +197,11 @@ sub unpackagemsg {
        if ($token->[0] eq 'S') {
 	   my $entry=$token->[1];
            my $value=$parser->get_text('/'.$entry);
-           $content{$entry}=$value;
+           if (($entry eq 'recuser') || ($entry eq 'recdomain')) {
+               push(@{$content{$entry}},$value);
+           } else {
+               $content{$entry}=$value;
+           }
        }
     }
     if ($content{'attachmenturl'}) {
@@ -474,7 +487,7 @@ sub user_crit_received {
 
 sub user_normal_msg_raw {
     my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl,
-	$toperm)=@_;
+	$toperm,$newid)=@_;
 # Check if allowed missing
     my $status='';
     my $msgid='undefined';
@@ -492,15 +505,16 @@ sub user_normal_msg_raw {
 # Save new message received time
        &Apache::lonnet::put
                          ('email_status',{'recnewemail'=>time},$domain,$user);
-# Into sent-mail folder
-       $status.=' '.&Apache::lonnet::critical(
-           'put:'.$env{'user.domain'}.':'.$env{'user.name'}.
-					      ':nohist_email_sent:'.
-           &Apache::lonnet::escape($msgid).'='.
-           &Apache::lonnet::escape($message),$env{'user.home'});
+# Into sent-mail folder unless a broadcast message
+       unless (($env{'request.course.id'}) && ($env{'form.sendmode'} eq 'group')) {
+           $status .= &store_sent_mail($msgid,$message);
+       }
     } else {
        $status='no_host';
     }
+    if (defined($newid)) {
+        $$newid = $msgid;
+    }
 # Notifications
     my %userenv = &Apache::lonnet::get('environment',['notification',
                                                       'permanentemail'],
@@ -550,6 +564,15 @@ sub user_normal_msg {
     return $status;
 }
 
+sub store_sent_mail {
+    my ($msgid,$message) = @_;
+        my $status =' '.&Apache::lonnet::critical(
+                   'put:'.$env{'user.domain'}.':'.$env{'user.name'}.
+                                              ':nohist_email_sent:'.
+                   &Apache::lonnet::escape($msgid).'='.
+                   &Apache::lonnet::escape($message),$env{'user.home'});
+    return $status;
+}
 
 # ============================================================ List all folders
 
@@ -787,8 +810,9 @@ sub sortedmessages {
 	my $msgid=&Apache::lonnet::escape($_);
 	my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid)=
 	    &Apache::lonmsg::unpackmsgid($msgid,$folder);
+        my $description = &get_course_desc($fromcid);
 	my @temp1 = ($sendtime,$shortsubj,$fromname,$fromdomain,$status,
-		     $msgid);
+		     $msgid,$description);
         # Check whether message was sent during blocking period.
         if ($sendtime >= $startblock && ($sendtime <= $endblock && $endblock > 0) ) {
             my $escid = &Apache::lonnet::unescape($msgid);
@@ -824,6 +848,12 @@ sub sortedmessages {
     if ($env{'form.sortedby'} eq "revsubject"){
         @temp = sort  {lc($b->[1]) cmp lc($a->[1])} @temp;
     }
+    if ($env{'form.sortedby'} eq "course"){
+        @temp = sort  {lc($a->[6]) cmp lc($b->[6])} @temp;
+    }
+    if ($env{'form.sortedby'} eq "revcourse"){
+        @temp = sort  {lc($b->[6]) cmp lc($a->[6])} @temp;
+    }
     if ($env{'form.sortedby'} eq "status"){
         @temp = sort  {$a->[4] cmp $b->[4]} @temp;
     }
@@ -833,6 +863,18 @@ sub sortedmessages {
     return @temp;
 }
 
+sub get_course_desc {
+    my ($fromcid) = @_;
+    my $description; 
+    if (defined($env{'course.'.$fromcid.'.description'})) {
+       $description = $env{'course.'.$fromcid.'.description'};
+    } else {
+       my %courseinfo=&Apache::lonnet::coursedescription($fromcid);
+        $description = $courseinfo{'description'};
+    }
+    return $description;
+}
+
 # ======================================================== Display new messages
 
 
@@ -841,6 +883,7 @@ sub disnew {
     my %lt=&Apache::lonlocal::texthash(
 				       'nm' => 'New Messages',
 				       'su' => 'Subject',
+                                       'co' => 'Course',
 				       'da' => 'Date',
 				       'us' => 'Username',
 				       'op' => 'Open',
@@ -862,6 +905,7 @@ sub disnew {
         my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=
 	    &Apache::lonmsg::unpackmsgid($_);
         if (defined($sendtime) && $sendtime!~/error/) {
+            my $description = &get_course_desc($fromcid);
             my $numsendtime = $sendtime;
             $sendtime = &Apache::lonlocal::locallocaltime($sendtime);
             if ($status eq 'new') {
@@ -874,7 +918,8 @@ sub disnew {
                         sendtime => $sendtime,
                         shortsub => &Apache::lonnet::unescape($shortsubj),
                         from     => $fromname,
-                        fromdom  => $fromdom 
+                        fromdom  => $fromdom,
+                        course   => $description 
                         }
                 }
             }
@@ -884,7 +929,7 @@ sub disnew {
         $r->print(<<TABLEHEAD);
 <h2>$lt{'nm'}</h2>
 <table border=2><tr><th>&nbsp</th>
-<th>$lt{'da'}</th><th>$lt{'us'}</th><th>$lt{'do'}</th><th>$lt{'su'}</th></tr>
+<th>$lt{'da'}</th><th>$lt{'us'}</th><th>$lt{'do'}</th><th>$lt{'su'}</th><th>$lt{'co'}</th></tr>
 TABLEHEAD
         foreach my $msg (@newmsgs) {
             $r->print(<<"ENDLINK");
@@ -892,7 +937,7 @@ TABLEHEAD
 onMouseOut="javascript:style.backgroundColor='#FFBB77'">
 <td><a href="/adm/email?dismode=new&display=$msg->{'msgid'}">$lt{'op'}</a></td>
 ENDLINK
-            foreach ('sendtime','from','fromdom','shortsub') {
+            foreach ('sendtime','from','fromdom','shortsub','course') {
                 $r->print("<td>$msg->{$_}</td>");
             }
             $r->print("</td></tr>");
@@ -1006,6 +1051,12 @@ ENDDISHEADER
     	$r->print('<a href = "?sortedby=revsubject'.$fsqs.'">'.&mt('Subject').'</a>');
     }
     $r->print('</th><th>');
+    if ($env{'form.sortedby'} eq "revcourse") {
+        $r->print('<a href = "?sortedby=course'.$fsqs.'">'.&mt('Course').'</a>');
+    } else {
+        $r->print('<a href = "?sortedby=revcourse'.$fsqs.'">'.&mt('Course').'</a>');
+    }
+    $r->print('</th><th>');
     if ($env{'form.sortedby'} eq "revstatus") {
 	$r->print('<a href = "?sortedby=status'.$fsqs.'">'.&mt('Status').'</a></th>');
     } else {
@@ -1013,7 +1064,7 @@ ENDDISHEADER
     }
     $r->print("</tr>\n");
     for (my $n=$firstdis;$n<=$lastdis;$n++) {
-	my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$origID)= @{$temp[$n]};
+	my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$origID,$description)= @{$temp[$n]};
 	if (($status ne 'deleted') && defined($sendtime) && $sendtime!~/error/) {
 	    if ($status eq 'new') {
 		$r->print('<tr bgcolor="#FFBB77" onMouseOver="javascript:style.backgroundColor=\'#DD9955\'"  onMouseOut="javascript:style.backgroundColor=\'#FFBB77\'">');
@@ -1031,7 +1082,7 @@ ENDDISHEADER
 		      '<td>'.&Apache::lonlocal::locallocaltime($sendtime).'</td><td>'.
 		      $fromname.'</td><td>'.$fromdomain.'</td><td>'.
 		      &Apache::lonnet::unescape($shortsubj).'</td><td>'.
-                      $status."</td></tr>\n");
+                      $description.'</td><td>'.$status.'</td></tr>'."\n");
 	} elsif ($status eq 'deleted') {
 # purge
 	    &movemsg(&Apache::lonnet::unescape($origID),$folder,'trash');
@@ -1826,6 +1877,16 @@ sub displaymessage {
 	}
 	$r->print('</tr></table>');
     }
+    my $tolist;
+    my @recipients = ();
+    for (my $i=0; $i<@{$content{'recuser'}}; $i++) {
+        $recipients[$i] =  &Apache::loncommon::aboutmewrapper(
+           &Apache::loncommon::plainname($content{'recuser'}[$i],
+                                      $content{'recdomain'}[$i]),
+              $content{'recuser'}[$i],$content{'recdomain'}[$i]).
+       ' ('.$content{'recuser'}[$i].' at '.$content{'recdomain'}[$i].') ';
+    }
+    $tolist = join(', ',@recipients);
     $r->print('<br /><b>'.&mt('Subject').':</b> '.$content{'subject'}.
 	      ($folder ne 'sent'?'<br /><b>'.&mt('From').':</b> '.
 	      &Apache::loncommon::aboutmewrapper(
@@ -1833,11 +1894,7 @@ sub displaymessage {
 						 $content{'sendername'},$content{'senderdomain'}).' ('.
 	      $content{'sendername'}.' at '.
 	      $content{'senderdomain'}.') ':'<br /><b>'.&mt('To').':</b> '.
-	      &Apache::loncommon::aboutmewrapper(
-						 &Apache::loncommon::plainname($content{'recuser'},$content{'recdomain'}),
-						 $content{'recuser'},$content{'recdomain'}).' ('.
-	      $content{'recuser'}.' at '.
-	      $content{'recdomain'}.') ').
+              $tolist).
 	      ($content{'courseid'}?'<br /><b>'.&mt('Course').':</b> '.$courseinfo{'description'}.
 	       ($content{'coursesec'}?' ('.&mt('Group/Section').': '.$content{'coursesec'}.')':''):'').
 	      '<br /><b>'.&mt('Time').':</b> '.$content{'time'}.
@@ -1952,6 +2009,8 @@ sub sendoffmail {
     my ($r,$folder)=@_;
     my $suffix=&foldersuffix($folder);
     my $sendstatus='';
+    my %broadcast_status;
+    my $numbroadcast = 0;
     if ($env{'form.send'}) {
 	&printheader($r,'','Messages being sent.');
 	$r->rflush();
@@ -1996,18 +2055,22 @@ sub sendoffmail {
 		$toaddr{$auname.':'.$audom}='';
 	    }
 	}
+
+        my $basicmsg;
+        my $msgtype;
+        if ((($env{'form.critmsg'}) || ($env{'form.sendbck'})) &&
+            (&Apache::lonnet::allowed('srm',$env{'request.course.id'}))) {
+            $basicmsg=&Apache::lonfeedback::clear_out_html($env{'form.message'},1);
+            $msgtype = '(critical)';
+        } else {
+            $basicmsg=&Apache::lonfeedback::clear_out_html($env{'form.message'});
+        }
 	
 	foreach (keys %toaddr) {
 	    my ($recuname,$recdomain)=split(/\:/,$_);
-            my $msgtxt;
-            if ((($env{'form.critmsg'}) || ($env{'form.sendbck'})) &&
-                (&Apache::lonnet::allowed('srm',$env{'request.course.id'}))) {
-                $msgtxt=&Apache::lonfeedback::clear_out_html($env{'form.message'},1);
-            } else {  
-	        $msgtxt=&Apache::lonfeedback::clear_out_html($env{'form.message'});
-            }
+            my $msgtxt = $basicmsg;
 	    if ($toaddr{$_}) { $msgtxt.='<hr />'.$toaddr{$_}; }
-	    my $thismsg;    
+	    my $thismsg;
 	    if ((($env{'form.critmsg'}) || ($env{'form.sendbck'})) && 
 		(&Apache::lonnet::allowed('srm',$env{'request.course.id'}))) {
 		$r->print(&mt('Sending critical message').' '.$recuname.'@'.$recdomain.': ');
@@ -2021,17 +2084,52 @@ sub sendoffmail {
 					  &Apache::lonfeedback::clear_out_html($env{'form.subject'}),
 					  $msgtxt,
 					  $content{'citation'},undef,undef,$env{'form.permanent'});
-		if (($env{'request.course.id'}) && ($env{'form.sendmode'} eq 'group')) {
-		    &user_normal_msg_raw(
-					 $env{'course.'.$env{'request.course.id'}.'.num'},
-					 $env{'course.'.$env{'request.course.id'}.'.domain'},
-					 'Broadcast ['.$recuname.':'.$recdomain.']',
-					 $msgtxt);
-		}
+            }
+	    if (($env{'request.course.id'}) && 
+                                         ($env{'form.sendmode'} eq 'group')) {
+	        $broadcast_status{$recuname.':'.$recdomain}  = $thismsg;
+                if ($thismsg eq 'ok') {
+                    $numbroadcast ++;
+                }
 	    }
 	    $r->print($thismsg.'<br />');
 	    $sendstatus.=' '.$thismsg;
 	}
+        if (($env{'request.course.id'}) && ($env{'form.sendmode'} eq 'group')) {
+            my $subj_prefix;
+            if ($msgtype eq 'critical') {
+                $subj_prefix = 'Critical broadcast';
+            } else {
+                $subj_prefix = 'Broadcast';
+            }
+            my ($broadmsgid,$broadresult);
+            if ($numbroadcast) {
+                $broadresult = &user_normal_msg_raw(
+                    $env{'course.'.$env{'request.course.id'}.'.num'},
+                    $env{'course.'.$env{'request.course.id'}.'.domain'},                $subj_prefix.' to: '.$env{'course.'.$env{'request.course.id'}.'.description'}.
+                    ' ('.$numbroadcast.' sent)',$basicmsg,undef,undef,undef,
+                    undef,\$broadmsgid);
+            }
+            if ($broadresult eq 'ok') {
+                my $record_sent;
+                my @recusers = ();
+                my @recudoms = ();
+                foreach my $recipient (sort(keys(%toaddr))) {
+                    if ($broadcast_status{$recipient} eq 'ok') {
+                        my ($uname,$udom) = split/:/,$recipient;
+                        push(@recusers,$uname);
+                        push(@recudoms,$udom);
+                    }
+                }
+                if (@recusers) {
+                    my $broadmessage;
+                    ($broadmsgid,$broadmessage)=&packagemsg(&Apache::lonfeedback::clear_out_html($env{'form.subject'}),$basicmsg,undef,undef,undef,\@recusers,\@recudoms,$broadmsgid);
+                    $record_sent = &store_sent_mail($broadmsgid,$broadmessage);
+                }
+            } else {
+                &Apache::lonnet::logthis('Failed to create record of broadcast in '.$env{'course.'.$env{'request.course.id'}.'.num'}.' at '.$env{'course.'.$env{'request.course.id'}.'.domain'}.' - no msgid generated');
+            }
+        }
     } else {
 	&printheader($r,'','No messages sent.'); 
     }