# The LearningOnline Network with CAPA # # Routines for messaging # # (Routines to control the menu # # (TeX Conversion Module # # 05/29/00,05/30 Gerd Kortemeyer) # # 10/05 Gerd Kortemeyer) # # 10/19,10/20,10/30, # 02/06/01 Gerd Kortemeyer # 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 package Apache::lonmsg; use strict; use Apache::lonnet(); use vars qw($msgcount); use HTML::TokeParser; use Apache::Constants qw(:common); # ===================================================================== Package sub packagemsg { my ($subject,$message,$citation)=@_; $message=~s/\/\>\;/g; $citation=~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.':'.$$); return $msgid, ''.$ENV{'user.name'}.''. ''.$ENV{'user.domain'}.''. ''.$subject.''. ''. ''.$ENV{'SERVER_NAME'}.''. ''.$ENV{'HTTP_HOST'}.''. ''.$ENV{'REMOTE_ADDR'}.''. ''.$ENV{'browser.type'}.''. ''.$ENV{'browser.os'}.''. ''.$ENV{'browser.version'}.''. ''.$ENV{'browser.mathml'}.''. ''.$ENV{'HTTP_USER_AGENT'}.''. ''.$ENV{'request.course.id'}.''. ''.$ENV{'request.role'}.''. ''.$ENV{'request.filename'}.''. ''.$msgid.''. ''.$message.''. ''.$citation.''; } # ================================================== Unpack message into a hash sub unpackagemsg { my $message=shift; my %content=(); my $parser=HTML::TokeParser->new(\$message); my $token; while ($token=$parser->get_token) { if ($token->[0] eq 'S') { my $entry=$token->[1]; my $value=$parser->get_text('/'.$entry); $content{$entry}=$value; } } return %content; } # ======================================================= Get info out of msgid sub unpackmsgid { my $msgid=&Apache::lonnet::unescape(shift); my ($sendtime,$shortsubj,$fromname,$fromdomain)=split(/\:/, &Apache::lonnet::unescape($msgid)); my %status=&Apache::lonnet::get('email_status',[$msgid]); if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; } unless ($status{$msgid}) { $status{$msgid}='new'; } return ($sendtime,$shortsubj,$fromname,$fromdomain,$status{$msgid}); } # =============================== Automated message to the author of a resource sub author_res_msg { my ($filename,$message)=@_; unless ($message) { return 'empty'; } $filename=&Apache::lonnet::declutter($filename); my ($domain,$author,@dummy)=split(/\//,$filename); my $homeserver=&Apache::lonnet::homeserver($author,$domain); if ($homeserver ne 'no_host') { my $id=unpack("%32C*",$message); my $msgid; ($msgid,$message)=&packagemsg($filename,$message); return &Apache::lonnet::reply('put:'.$domain.':'.$author. ':nohist_res_msgs:'. &Apache::lonnet::escape($filename.'_'.$id).'='. &Apache::lonnet::escape($message),$homeserver); } return 'no_host'; } # ================================================== Critical message to a user sub user_crit_msg { my ($user,$domain,$subject,$message,$sendback)=@_; # Check if allowed missing my $status=''; my $msgid='undefined'; unless (($message)&&($user)&&($domain)) { $status='empty'; }; my $homeserver=&Apache::lonnet::homeserver($user,$domain); if ($homeserver ne 'no_host') { ($msgid,$message)=&packagemsg($subject,$message); if ($sendback) { $message.='true'; } $status=&Apache::lonnet::critical( 'put:'.$domain.':'.$user.':critical:'. &Apache::lonnet::escape($msgid).'='. &Apache::lonnet::escape($message),$homeserver); } else { $status='no_host'; } &Apache::lonnet::logthis( 'Sending critical email '.$msgid. ', log status: '. &Apache::lonnet::log($ENV{'user.domain'},$ENV{'user.name'}, $ENV{'user.home'}, 'Sending critical '.$msgid.' to '.$user.' at '.$domain.' with status: ' .$status)); return $status; } # =================================================== Critical message received sub user_crit_received { my $msgid=shift; my %message=&Apache::lonnet::get('critical',[$msgid]); my %contents=&unpackagemsg($message{$msgid}); my $status='rec: '.($contents{'sendback'}? &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'); $status.=' trans: '. &Apache::lonnet::put( 'nohist_email',{$contents{'msgid'} => $message{$msgid}}); $status.=' del: '. &Apache::lonnet::del('critical',[$contents{'msgid'}]); &Apache::lonnet::log($ENV{'user.domain'},$ENV{'user.name'}, $ENV{'user.home'},'Received critical message '. $contents{'msgid'}. ', '.$status); return $status; } # ======================================================== Normal communication sub user_normal_msg { my ($user,$domain,$subject,$message,$citation)=@_; # Check if allowed missing my $status=''; my $msgid='undefined'; unless (($message)&&($user)&&($domain)) { $status='empty'; }; my $homeserver=&Apache::lonnet::homeserver($user,$domain); if ($homeserver ne 'no_host') { ($msgid,$message)=&packagemsg($subject,$message,$citation); $status=&Apache::lonnet::critical( 'put:'.$domain.':'.$user.':nohist_email:'. &Apache::lonnet::escape($msgid).'='. &Apache::lonnet::escape($message),$homeserver); } else { $status='no_host'; } &Apache::lonnet::log($ENV{'user.domain'},$ENV{'user.name'}, $ENV{'user.home'}, 'Sending '.$msgid.' to '.$user.' at '.$domain.' with status: '.$status); return $status; } # =============================================================== Status Change sub statuschange { my ($msgid,$newstatus)=@_; my %status=&Apache::lonnet::get('email_status',[$msgid]); if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; } unless ($status{$msgid}) { $status{$msgid}='new'; } unless (($status{$msgid} eq 'replied') || ($status{$msgid} eq 'forwarded')) { &Apache::lonnet::put('email_status',{$msgid => $newstatus}); } if (($newstatus eq 'deleted') || ($newstatus eq 'new')) { &Apache::lonnet::put('email_status',{$msgid => $newstatus}); } } # ======================================================= Display a course list sub discourse { my $r=shift; my %courselist=&Apache::lonnet::dump( 'classlist', $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); my $now=time; $r->print(<    

ENDDISHEADER map { my ($end,$start)=split(/\:/,$courselist{$_}); my $active=1; if (($end) && ($now>$end)) { $active=0; } if ($active) { my ($sname,$sdom)=split(/\:/,$_); my %reply=&Apache::lonnet::get('environment', ['firstname','middlename','lastname','generation'], $sdom,$sname); my $section=&Apache::lonnet::usection ($sdom,$sname,$ENV{'request.course.id'}); $r->print( '
'. $reply{'firstname'}.' '. $reply{'middlename'}.' '. $reply{'lastname'}.' '. $reply{'generation'}. ' ('.$_.') '.$section); } } sort keys %courselist; } # ==================================================== Display Critical Message sub discrit { my $r=shift; $r->print('

Critical Messages

'. '
'. ''); my %what=&Apache::lonnet::dump('critical'); map { my %content=&unpackagemsg($what{$_}); $content{'message'}=~s/\n/\/g; $r->print('
From: '.$content{'sendername'}.'@'. $content{'senderdomain'}.' ('.$content{'time'}. ')
'.$content{'message'}.'
'. ''. ''); } sort keys %what; $r->print( ''); } # =============================================================== Compose reply sub comprep { my ($r,$msgid)=@_; my %message=&Apache::lonnet::get('nohist_email',[$msgid]); my %content=&unpackagemsg($message{$msgid}); my $quotemsg='> '.$content{'message'}; $quotemsg=~s/\r/\n/g; $quotemsg=~s/\f/\n/g; $quotemsg=~s/\n+/\n\> /g; my $subject='Re: '.$content{'subject'}; my $dispcrit=''; if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { $dispcrit= ' Send as critical message
'. ' Send as critical message'. ' and return receipt

'; } $r->print(<<"ENDREPLY");

Subject:

$dispcrit

ENDREPLY } # ======================================================== Display all messages sub disall { my $r=shift; $r->print( '

Display All Messages

'. ''. ''); map { my ($sendtime,$shortsubj,$fromname,$fromdomain,$status)= &Apache::lonmsg::unpackmsgid($_); unless ($status eq 'deleted') { if ($status eq 'new') { $r->print(''); } elsif ($status eq 'read') { $r->print(''); } elsif ($status eq 'replied') { $r->print(''); } else { $r->print(''); } $r->print(''. ''); } } sort split(/\&/,&Apache::lonnet::reply('keys:'. $ENV{'user.domain'}.':'. $ENV{'user.name'}.':nohist_email', $ENV{'user.home'})); $r->print('
 DateUsernameDomainSubjectStatus
OpenDelete'.localtime($sendtime).''. $fromname.''.$fromdomain.''. &Apache::lonnet::unescape($shortsubj).''. $status.'

'. ''. '

'); } # ============================================================== Compose output sub compout { my ($r,$forwarding,$broadcast)=@_; my $dispcrit=''; my $dissub=''; my $dismsg=''; my $func='Send New'; if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { $dispcrit= ' Send as critical message
'. ' Send as critical message'. ' and return receipt

'; } if ($forwarding) { $dispcrit.=''; $func='Forward'; my %message=&Apache::lonnet::get('nohist_email',[$forwarding]); my %content=&unpackagemsg($message{$forwarding}); $dissub='Forwarding: '.$content{'subject'}; $dismsg='Forwarded message from '. $content{'sendername'}.' at '.$content{'senderdomain'}; } my $defdom=$ENV{'user.domain'}; $r->print( '

'. ''); unless (($broadcast eq 'group') || ($broadcast eq 'upload')) { $r->print(<<"ENDREC");
ENDREC } unless ($broadcast eq 'upload') { $r->print(<<"ENDCOMP");
Username:
Domain:
Additional Recipients
username\@domain,username\@domain, ...
Subject:

$dispcrit ENDCOMP } if ($broadcast eq 'upload') { $r->print(<

Generate messages from a file

Subject:
username1\@domain1: text
username2\@domain2: text
username1\@domain1: text
The messages will be assembled from all lines with the respective username\@domain, and appended to the general message text.

General message text:

$dispcrit ENDUPLOAD } if ($broadcast eq 'group') { &discourse; } $r->print('

'); } # ===================================================================== Handler sub handler { my $r=shift; # ----------------------------------------------------------- Set document type $r->content_type('text/html'); $r->send_http_header; return OK if $r->header_only; # --------------------------- Get query string for limited number of parameters 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'})); # --------------------------------------------------------------- Render Output $r->print('EMail and Messaging'); $r->print( ''); $r->print('

EMail

'); 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('Subject: '.$content{'subject'}. '
From: '.$content{'sendername'}.' at '. $content{'senderdomain'}. '
Time: '.$content{'time'}.'

'. ''. ''. ''. ''. ''. '
Functions:ReplyForwardMark UnreadDisplay all Messages

'.
             $content{'message'}.'

'.$content{'citation'}); } elsif ($ENV{'form.replyto'}) { &comprep($r,$ENV{'form.replyto'}); } elsif ($ENV{'form.sendreply'}) { my $msgid=$ENV{'form.sendreply'}; my %message=&Apache::lonnet::get('nohist_email',[$msgid]); my %content=&unpackagemsg($message{$msgid}); &statuschange($msgid,'replied'); if ((($ENV{'form.critmsg'}) || ($ENV{'form.sendbck'})) && (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'}))) { $r->print('Sending critical: '. &user_crit_msg($content{'sendername'}, $content{'senderdomain'}, $ENV{'form.subject'}, $ENV{'form.message'}, $ENV{'form.sendbck'})); } else { $r->print('Sending: '.&user_normal_msg($content{'sendername'}, $content{'senderdomain'}, $ENV{'form.subject'}, $ENV{'form.message'})); } if ($ENV{'form.displayedcrit'}) { &discrit($r); } else { &disall($r); } } elsif ($ENV{'form.confirm'}) { map { if ($_=~/^form\.rec\_(.*)$/) { $r->print('Confirming Receipt: '. &user_crit_received($1).'
'); } if ($_=~/^form\.reprec\_(.*)$/) { my $msgid=$1; $r->print('Confirming Receipt: '. &user_crit_received($msgid).'
'); &comprep($r,$msgid); } } keys %ENV; &discrit($r); } elsif ($ENV{'form.critical'}) { &discrit($r); } elsif ($ENV{'form.forward'}) { &compout($r,$ENV{'form.forward'}); } elsif ($ENV{'form.markread'}) { } elsif ($ENV{'form.markdel'}) { &statuschange($ENV{'form.markdel'},'deleted'); &disall($r); } elsif ($ENV{'form.markeddel'}) { my $total=0; map { if ($_=~/^form\.delmark_(.*)$/) { &statuschange(&Apache::lonnet::unescape($1),'deleted'); $total++; } } keys %ENV; $r->print('Deleted '.$total.' message(s)

'); &disall($r); } elsif ($ENV{'form.markunread'}) { &statuschange($ENV{'form.markunread'},'new'); &disall($r); } elsif ($ENV{'form.compose'}) { &compout($r,'',$ENV{'form.compose'}); } elsif ($ENV{'form.sendmail'}) { my %content=(); undef %content; if ($ENV{'form.forwid'}) { my $msgid=$ENV{'form.forwid'}; my %message=&Apache::lonnet::get('nohist_email',[$msgid]); %content=&unpackagemsg($message{$msgid}); &statuschange($msgid,'forwarded'); $ENV{'form.message'}.="\n\n-- Forwarded message --\n\n". $content{'message'}; } my %toaddr=(); undef %toaddr; if ($ENV{'form.sendmode'} eq 'group') { map { if ($_=~/^form\.send\_to\_\&\&\&[^\&]*\&\&\&\_(.+)$/) { $toaddr{$1}=''; } } keys %ENV; } elsif ($ENV{'form.sendmode'} eq 'upload') { map { 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 { my ($auname,$audom)=split(/\@/,$_); $toaddr{$auname.':'.$audom}=''; } split(/\,/,$ENV{'form.additionalrec'}); } map { my ($recuname,$recdomain)=split(/\:/,$_); my $msgtxt=$ENV{'form.message'}; if ($toaddr{$_}) { $msgtxt.='


'.$toaddr{$_}; } if ((($ENV{'form.critmsg'}) || ($ENV{'form.sendbck'})) && (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'}))) { $r->print('Sending critical: '. &user_crit_msg($recuname,$recdomain, $ENV{'form.subject'}, $msgtxt, $ENV{'form.sendbck'})); } else { $r->print('Sending: '.&user_normal_msg($recuname,$recdomain, $ENV{'form.subject'}, $msgtxt, $content{'citation'})); } $r->print('
'); } keys %toaddr; if ($ENV{'form.displayedcrit'}) { &discrit($r); } else { &disall($r); } } else { &disall($r); } $r->print(''); return OK; } # ================================================= Main program, reset counter sub BEGIN { $msgcount=0; } 1; __END__