--- loncom/interface/lonmsg.pm 2001/12/19 17:17:46 1.26 +++ loncom/interface/lonmsg.pm 2003/03/17 16:55:06 1.42.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Routines for messaging # -# $Id: lonmsg.pm,v 1.26 2001/12/19 17:17:46 albertel Exp $ +# $Id: lonmsg.pm,v 1.42.2.1 2003/03/17 16:55:06 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -39,30 +39,35 @@ # 07/27 Guy Albertelli # 07/27,07/28,07/30,08/03,08/06,08/08,08/09,08/10,8/13,8/15, # 10/1,11/5 Gerd Kortemeyer - +# YEAR=2002 +# 1/1,3/18 Gerd Kortemeyer +# package Apache::lonmsg; use strict; use Apache::lonnet(); use vars qw($msgcount); -use HTML::TokeParser; +use HTML::TokeParser(); use Apache::Constants qw(:common); +use Apache::loncommon(); +use Apache::lontexconvert(); +use HTML::Entities(); # ===================================================================== Package sub packagemsg { my ($subject,$message,$citation)=@_; - $message=~s/\</\<\;/g; - $message=~s/\>/\>\;/g; - $citation=~s/\</\<\;/g; - $citation=~s/\>/\>\;/g; - $subject=~s/\</\<\;/g; - $subject=~s/\>/\>\;/g; +# $message=~s/\</\<\;/g; +# $message=~s/\>/\>\;/g; + $message =&HTML::Entities::encode($message); + $citation=&HTML::Entities::encode($citation); + $subject =&HTML::Entities::encode($subject); +# $subject=~s/\</\<\;/g; +# $subject=~s/\>/\>\;/g; my $now=time; $msgcount++; my $partsubj=$subject; $partsubj=&Apache::lonnet::escape($partsubj); - $partsubj=substr($partsubj,0,50); my $msgid=&Apache::lonnet::escape( $now.':'.$partsubj.':'.$ENV{'user.name'}.':'. $ENV{'user.domain'}.':'.$msgcount.':'.$$); @@ -116,6 +121,17 @@ sub unpackmsgid { return ($sendtime,$shortsubj,$fromname,$fromdomain,$status{$msgid}); } +# ============================================================= Check for email + +sub newmail { + if ((time-$ENV{'user.mailcheck.time'})>300) { + my %what=&Apache::lonnet::get('email_status',['recnewemail']); + &Apache::lonnet::appenv('user.mailcheck.time'=>time); + if ($what{'recnewemail'}>0) { return 1; } + } + return 0; +} + # =============================== Automated message to the author of a resource sub author_res_msg { @@ -138,7 +154,7 @@ sub author_res_msg { # ================================================== Critical message to a user -sub user_crit_msg { +sub user_crit_msg_raw { my ($user,$domain,$subject,$message,$sendback)=@_; # Check if allowed missing my $status=''; @@ -165,6 +181,27 @@ sub user_crit_msg { return $status; } +# New routine that respects "forward" and calls old routine + +sub user_crit_msg { + my ($user,$domain,$subject,$message,$sendback)=@_; + my $status=''; + my %userenv = &Apache::lonnet::get('environment',['msgforward'], + $domain,$user); + my $msgforward=$userenv{'msgforward'}; + if ($msgforward) { + foreach (split(/\,/,$msgforward)) { + my ($forwuser,$forwdomain)=split(/\:/,$_); + $status.= + &user_crit_msg_raw($forwuser,$forwdomain,$subject,$message, + $sendback).' '; + } + } else { + $status=&user_crit_msg_raw($user,$domain,$subject,$message,$sendback); + } + return $status; +} + # =================================================== Critical message received sub user_crit_received { @@ -175,9 +212,10 @@ sub user_crit_received { &user_normal_msg($contents{'sendername'},$contents{'senderdomain'}, 'Receipt: '.$ENV{'user.name'}.' at '.$ENV{'user.domain'}, 'User '.$ENV{'user.name'}.' at '.$ENV{'user.domain'}. - ' acknowledged receipt of message "'. - $contents{'subject'}.'" dated '.$contents{'time'}.".\n\n" - .'Message ID: '.$contents{'msgid'}):'no msg req'); + ' acknowledged receipt of message'."\n".' "'. + $contents{'subject'}.'"'."\n".'dated '. + $contents{'time'}.".\n" + ):'no msg req'); $status.=' trans: '. &Apache::lonnet::put( 'nohist_email',{$contents{'msgid'} => $message{$msgid}}); @@ -192,7 +230,7 @@ sub user_crit_received { # ======================================================== Normal communication -sub user_normal_msg { +sub user_normal_msg_raw { my ($user,$domain,$subject,$message,$citation)=@_; # Check if allowed missing my $status=''; @@ -205,6 +243,8 @@ sub user_normal_msg { 'put:'.$domain.':'.$user.':nohist_email:'. &Apache::lonnet::escape($msgid).'='. &Apache::lonnet::escape($message),$homeserver); + &Apache::lonnet::put + ('email_status',{'recnewemail'=>time},$domain,$user); } else { $status='no_host'; } @@ -214,6 +254,29 @@ sub user_normal_msg { return $status; } +# New routine that respects "forward" and calls old routine + +sub user_normal_msg { + my ($user,$domain,$subject,$message,$citation)=@_; + my $status=''; + my %userenv = &Apache::lonnet::get('environment',['msgforward'], + $domain,$user); + my $msgforward=$userenv{'msgforward'}; + if ($msgforward) { + foreach (split(/\,/,$msgforward)) { + my ($forwuser,$forwdomain)=split(/\:/,$_); + $status.= + &user_normal_msg_raw($forwuser,$forwdomain,$subject,$message, + $citation).' '; + } + } else { + $status= + &user_normal_msg_raw($user,$domain,$subject,$message,$citation); + } + return $status; +} + + # =============================================================== Status Change sub statuschange { @@ -276,7 +339,7 @@ sub discourse { <input type=button onClick="uncheckall()" value="Check for None"> <p> ENDDISHEADER - map { + foreach (sort keys %courselist) { my ($end,$start)=split(/\:/,$courselist{$_}); my $active=1; if (($end) && ($now>$end)) { $active=0; } @@ -295,28 +358,43 @@ ENDDISHEADER $reply{'generation'}. ' ('.$_.') '.$section); } - } sort keys %courselist; + } } # ==================================================== Display Critical Message sub discrit { my $r=shift; - $r->print('<h1><font color=red>Critical Messages</font></h1>'. - '<form action=/adm/email method=post>'. - '<input type=hidden name=confirm value=true>'); - my %what=&Apache::lonnet::dump('critical'); - map { - my %content=&unpackagemsg($what{$_}); - $content{'message'}=~s/\n/\<br\>/g; - $r->print('<hr>From: <b>'.$content{'sendername'}.'@'. - $content{'senderdomain'}.'</b> ('.$content{'time'}. - ')<br><blockquote>'.$content{'message'}.'</blockquote>'. - '<input type=submit name="rec_'.$_.'" value="Confirm Receipt">'. - '<input type=submit name="reprec_'.$_.'" value="Confirm Receipt and Reply">'); - } sort keys %what; - $r->print( - '<input type=hidden name="displayedcrit" value="true"></form>'); + my $header = '<h1><font color=red>Critical Messages</font></h1>'. + '<form action=/adm/email method=post>'. + '<input type=hidden name=confirm value=true>'; + my %what=&Apache::lonnet::dump('critical'); + my $result = ''; + foreach (sort keys %what) { + my %content=&unpackagemsg($what{$_}); + next if ($content{'senderdomain'} eq ''); + $content{'message'}=~s/\n/\<br\>/g; + $result.='<hr>From: <b>'. +&Apache::loncommon::aboutmewrapper( + &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}),$content{'sendername'},$content{'senderdomain'}).'</b> ('. +$content{'sendername'}.'@'. + $content{'senderdomain'}.') '.$content{'time'}. + '<br>Subject: '.$content{'subject'}. + '<br><blockquote>'. + &Apache::lontexconvert::msgtexconverted($content{'message'}). + '</blockquote>'. + '<input type=submit name="rec_'.$_.'" value="Confirm Receipt">'. + '<input type=submit name="reprec_'.$_.'" '. + 'value="Confirm Receipt and Reply">'; + } + # Check to see if there were any messages. + if ($result eq '') { + $result = "<h2>You have no critical messages.</h2>"; + } else { + $r->print($header); + } + $r->print($result); + $r->print('<input type=hidden name="displayedcrit" value="true"></form>'); } # =============================================================== Compose reply @@ -332,16 +410,18 @@ sub comprep { my $subject='Re: '.$content{'subject'}; my $dispcrit=''; if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { + my $crithelp = Apache::loncommon::help_open_topic("Course_Critical_Message"); $dispcrit= - '<input type=checkbox name=critmsg> Send as critical message<br>'. - '<input type=checkbox name=sendbck> Send as critical message'. - ' and return receipt<p>'; + '<input type=checkbox name=critmsg> Send as critical message ' . $crithelp . + '<br>'. + '<input type=checkbox name=sendbck> Send as critical message ' . + ' and return receipt' . $crithelp . '<p>'; } $r->print(<<"ENDREPLY"); <form action="/adm/email" method=post> <input type=hidden name=sendreply value="$msgid"> Subject: <input type=text size=50 name=subject value="$subject"><p> -<textarea name=message cols=64 rows=10 wrap=hard> +<textarea name=message cols=84 rows=10 wrap=hard> $quotemsg </textarea><p> $dispcrit @@ -354,36 +434,60 @@ ENDREPLY sub disall { my $r=shift; - $r->print( - '<h1>Display All Messages</h1><form method=post action="/adm/email">'. + $r->print(<<ENDDISHEADER); +<script> + function checkall() { + 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].checked=true; + } + } + } + + 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].checked=false; + } + } + } +</script> +ENDDISHEADER + $r->print( + '<h1>Display All Messages</h1><form method=post name=disall '. + 'action="/adm/email">'. '<table border=2><tr><th colspan=2> </th><th>Date</th>'. '<th>Username</th><th>Domain</th><th>Subject</th><th>Status</th></tr>'); - map { + foreach (sort split(/\&/,&Apache::lonnet::reply('keys:'. + $ENV{'user.domain'}.':'. + $ENV{'user.name'}.':nohist_email', + $ENV{'user.home'}))) { my ($sendtime,$shortsubj,$fromname,$fromdomain,$status)= &Apache::lonmsg::unpackmsgid($_); - unless ($status eq 'deleted') { - if ($status eq 'new') { - $r->print('<tr bgcolor="#FFBB77">'); - } elsif ($status eq 'read') { - $r->print('<tr bgcolor="#BBBB77">'); - } elsif ($status eq 'replied') { - $r->print('<tr bgcolor="#AAAA88">'); - } else { - $r->print('<tr bgcolor="#99BBBB">'); - } - $r->print('<td><a href="/adm/email?display='.$_. - '">Open</a></td><td><a href="/adm/email?markdel='.$_. - '">Delete</a><input type=checkbox name="delmark_'.$_.'"></td>'. - '<td>'.localtime($sendtime).'</td><td>'. - $fromname.'</td><td>'.$fromdomain.'</td><td>'. + if (($status ne 'deleted') && defined($sendtime) && $sendtime!~/error/) { + if ($status eq 'new') { + $r->print('<tr bgcolor="#FFBB77">'); + } elsif ($status eq 'read') { + $r->print('<tr bgcolor="#BBBB77">'); + } elsif ($status eq 'replied') { + $r->print('<tr bgcolor="#AAAA88">'); + } else { + $r->print('<tr bgcolor="#99BBBB">'); + } + $r->print('<td><a href="/adm/email?display='.$_. + '">Open</a></td><td><a href="/adm/email?markdel='.$_. + '">Delete</a><input type=checkbox name="delmark_'.$_.'"></td>'. + '<td>'.localtime($sendtime).'</td><td>'. + $fromname.'</td><td>'.$fromdomain.'</td><td>'. &Apache::lonnet::unescape($shortsubj).'</td><td>'. $status.'</td></tr>'); - } - } sort split(/\&/,&Apache::lonnet::reply('keys:'. - $ENV{'user.domain'}.':'. - $ENV{'user.name'}.':nohist_email', - $ENV{'user.home'})); + } + } $r->print('</table><p>'. + '<a href="javascript:checkall()">Check All</a> '. + '<a href="javascript:uncheckall()">Uncheck All</a><p>'. '<input type=submit name="markeddel" value="Delete Checked">'. '</form></body></html>'); } @@ -397,10 +501,12 @@ sub compout { my $dismsg=''; my $func='Send New'; if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { + my $crithelp = Apache::loncommon::help_open_topic("Course_Critical_Message"); $dispcrit= - '<input type=checkbox name=critmsg> Send as critical message<br>'. - '<input type=checkbox name=sendbck> Send as critical message'. - ' and return receipt<p>'; + '<input type=checkbox name=critmsg> Send as critical message ' . $crithelp . + '<br>'. + '<input type=checkbox name=sendbck> Send as critical message ' . + ' and return receipt' . $crithelp . '<p>'; } if ($forwarding) { $dispcrit.='<input type=hidden name=forwid value="'. @@ -414,47 +520,57 @@ sub compout { $content{'sendername'}.' at '.$content{'senderdomain'}; } my $defdom=$ENV{'user.domain'}; + if ($ENV{'form.recdom'}) { $defdom=$ENV{'form.recdom'}; } $r->print( - '<form action="/adm/email" name="compemail" method=post'. - ' enctype="multipart/form-data">'. - '<input type=hidden name=sendmail value=on><table>'); + '<form action="/adm/email" name="compemail" method="post"'. + ' enctype="multipart/form-data">'."\n". + '<input type="hidden" name="sendmail" value="on">'."\n". + '<table>'); unless (($broadcast eq 'group') || ($broadcast eq 'upload')) { + my $domform = &Apache::loncommon::select_dom_form($defdom,'recdomain'); + $r->print(<<"ENDREC"); <table> -<tr><td>Username:</td><td><input type=text size=12 name=recuname></td></tr> +<tr><td>Username:</td><td><input type=text size=12 name=recuname value="$ENV{'form.recname'}"></td></tr> <tr><td>Domain:</td> -<td><input type=text size=12 name=recdomain value="$defdom"></td></tr> +<td>$domform</td></tr> ENDREC } - unless ($broadcast eq 'upload') { + if ($broadcast ne 'upload') { $r->print(<<"ENDCOMP"); <tr><td>Additional Recipients<br><tt>username\@domain,username\@domain, ... </tt></td><td> <input type=text size=50 name=additionalrec></td></tr> <tr><td>Subject:</td><td><input type=text size=50 name=subject value="$dissub"> </td></tr></table> -<textarea name=message cols=60 rows=10 wrap=hard>$dismsg +<textarea name=message cols=80 rows=10 wrap=hard>$dismsg </textarea><p> $dispcrit <input type=submit value="$func Mail"> ENDCOMP - } - if ($broadcast eq 'upload') { + } else { # $broadcast is 'upload' $r->print(<<ENDUPLOAD); <input type=hidden name=sendmode value=upload> <h3>Generate messages from a file</h3> +<p> Subject: <input type=text size=50 name=subject> +</p> +<p>General message text<br /> +<textarea name=message cols=60 rows=10 wrap=hard>$dismsg +</textarea></p> +<p> +The file format for the uploaded portion of the message is: <pre> username1\@domain1: text username2\@domain2: text -username1\@domain1: text +username3\@domain1: text </pre> +</p> +<p> The messages will be assembled from all lines with the respective -<tt>username\@domain</tt>, and appended to the general message text.<p> +<tt>username\@domain</tt>, and appended to the general message text.</p> +<p> <input type=file name=upfile size=20><p> -General message text:<p> -<textarea name=message cols=60 rows=10 wrap=hard>$dismsg -</textarea><p> $dispcrit <input type=submit value="Upload and send"> ENDUPLOAD @@ -478,36 +594,28 @@ sub handler { return OK if $r->header_only; # --------------------------- Get query string for limited number of parameters + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['display','replyto','forward','markread','markdel','markunread', + 'sendreply','compose','sendmail','critical','recname','recdom']); - map { - my ($name, $value) = split(/=/,$_); - $value =~ tr/+/ /; - $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; - if (($name eq 'display') || ($name eq 'replyto') || - ($name eq 'forward') || ($name eq 'markread') || - ($name eq 'markdel') || ($name eq 'markunread') || - ($name eq 'sendreply') || ($name eq 'compose') || - ($name eq 'sendmail') || ($name eq 'critical')) { - unless ($ENV{'form.'.$name}) { - $ENV{'form.'.$name}=$value; - } - } - } (split(/&/,$ENV{'QUERY_STRING'})); - +# ------------------------------------------------------ They checked for email + &Apache::lonnet::put('email_status',{'recnewemail'=>0}); # --------------------------------------------------------------- Render Output - $r->print('<html><head><title>EMail and Messaging</title></head>'); - $r->print( - '<body bgcolor="#FFFFFF"><img align=right src=/adm/lonIcons/lonlogos.gif>'); - $r->print('<h1>EMail</h1>'); + $r->print('<html><head><title>EMail and Messaging</title></head>'. + &Apache::loncommon::bodytag('EMail and Messages')); if ($ENV{'form.display'}) { my $msgid=$ENV{'form.display'}; &statuschange($msgid,'read'); my %message=&Apache::lonnet::get('nohist_email',[$msgid]); my %content=&unpackagemsg($message{$msgid}); $r->print('<b>Subject:</b> '.$content{'subject'}. - '<br><b>From:</b> '.$content{'sendername'}.' at '. - $content{'senderdomain'}. + '<br><b>From:</b> '. +&Apache::loncommon::aboutmewrapper( +&Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}), +$content{'sendername'},$content{'senderdomain'}).' ('. + $content{'sendername'}.' at '. + $content{'senderdomain'}.') '. '<br><b>Time:</b> '.$content{'time'}.'<p>'. '<table border=2><tr bgcolor="#FFFFAA"><td>Functions:</td>'. '<td><a href="/adm/email?replyto='.&Apache::lonnet::escape($msgid). @@ -518,7 +626,8 @@ sub handler { '"><b>Mark Unread</b></a></td>'. '<td><a href="/adm/email"><b>Display all Messages</b></a></td>'. '</tr></table><p><pre>'. - $content{'message'}.'</pre><hr>'.$content{'citation'}); + &Apache::lontexconvert::msgtexconverted($content{'message'}). + '</pre><hr>'.$content{'citation'}); } elsif ($ENV{'form.replyto'}) { &comprep($r,$ENV{'form.replyto'}); } elsif ($ENV{'form.sendreply'}) { @@ -546,7 +655,7 @@ sub handler { &disall($r); } } elsif ($ENV{'form.confirm'}) { - map { + foreach (keys %ENV) { if ($_=~/^form\.rec\_(.*)$/) { $r->print('<b>Confirming Receipt:</b> '. &user_crit_received($1).'<br>'); @@ -557,7 +666,7 @@ sub handler { &user_crit_received($msgid).'<br>'); &comprep($r,$msgid); } - } keys %ENV; + } &discrit($r); } elsif ($ENV{'form.critical'}) { &discrit($r); @@ -569,12 +678,12 @@ sub handler { &disall($r); } elsif ($ENV{'form.markeddel'}) { my $total=0; - map { + foreach (keys %ENV) { if ($_=~/^form\.delmark_(.*)$/) { &statuschange(&Apache::lonnet::unescape($1),'deleted'); $total++; } - } keys %ENV; + } $r->print('Deleted '.$total.' message(s)<p>'); &disall($r); } elsif ($ENV{'form.markunread'}) { @@ -596,29 +705,29 @@ sub handler { my %toaddr=(); undef %toaddr; if ($ENV{'form.sendmode'} eq 'group') { - map { + foreach (keys %ENV) { if ($_=~/^form\.send\_to\_\&\&\&[^\&]*\&\&\&\_(.+)$/) { $toaddr{$1}=''; } - } keys %ENV; + } } elsif ($ENV{'form.sendmode'} eq 'upload') { - map { + foreach (split(/[\n\r\f]+/,$ENV{'form.upfile'})) { my ($rec,$txt)=split(/\s*\:\s*/,$_); if ($txt) { $rec=~s/\@/\:/; $toaddr{$rec}.=$txt."\n"; } - } split(/[\n\r\f]+/,$ENV{'form.upfile'}); + } } else { $toaddr{$ENV{'form.recuname'}.':'.$ENV{'form.recdomain'}}=''; } if ($ENV{'form.additionalrec'}) { - map { + foreach (split(/\,/,$ENV{'form.additionalrec'})) { my ($auname,$audom)=split(/\@/,$_); $toaddr{$auname.':'.$audom}=''; - } split(/\,/,$ENV{'form.additionalrec'}); + } } - map { + foreach (keys %toaddr) { my ($recuname,$recdomain)=split(/\:/,$_); my $msgtxt=$ENV{'form.message'}; if ($toaddr{$_}) { $msgtxt.='<hr>'.$toaddr{$_}; } @@ -636,7 +745,7 @@ sub handler { $content{'citation'})); } $r->print('<br>'); - } keys %toaddr; + } if ($ENV{'form.displayedcrit'}) { &discrit($r); } else { @@ -651,7 +760,7 @@ sub handler { } # ================================================= Main program, reset counter -sub BEGIN { +BEGIN { $msgcount=0; }