--- loncom/interface/lonmsg.pm 2001/08/03 14:00:07 1.12
+++ loncom/interface/lonmsg.pm 2004/09/28 14:12:40 1.109
@@ -1,51 +1,151 @@
# The LearningOnline Network with CAPA
-#
# Routines for messaging
#
-# (Routines to control the menu
+# $Id: lonmsg.pm,v 1.109 2004/09/28 14:12:40 matthew Exp $
+#
+# Copyright Michigan State University Board of Trustees
+#
+# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
+#
+# LON-CAPA is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# LON-CAPA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
#
-# (TeX Conversion Module
+# You should have received a copy of the GNU General Public License
+# along with LON-CAPA; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-# 05/29/00,05/30 Gerd Kortemeyer)
+# /home/httpd/html/adm/gpl.txt
#
-# 10/05 Gerd Kortemeyer)
+# http://www.lon-capa.org/
#
-# 10/19,10/20,10/30,
-# 02/06/01 Gerd Kortemeyer
-# 07/27 Guy Albertelli
-# 07/27,07/28,07/30,08/03 Gerd Kortemeyer
+
package Apache::lonmsg;
+=pod
+
+=head1 NAME
+
+Apache::lonmsg: supports internal messaging
+
+=head1 SYNOPSIS
+
+lonmsg provides routines for sending messages, receiving messages, and
+a handler to allow users to read, send, and delete messages.
+
+=head1 OVERVIEW
+
+=head2 Messaging Overview
+
+XLON-CAPA provides an internal messaging system similar to
+email, but customized for LON-CAPA's usage. LON-CAPA implements its
+own messaging system, rather then building on top of email, because of
+the features LON-CAPA messages can offer that conventional e-mail can
+not:
+
+=over 4
+
+=item * B: A message the recipient B
+acknowlegde receipt of before they are allowed to continue using the
+system, preventing a user from claiming they never got a message
+
+=item * B: LON-CAPA can reliably send reciepts informing the
+sender that it has been read; again, useful for preventing students
+from claiming they did not see a message. (While conventional e-mail
+has some reciept support, it's sporadic, e-mail client-specific, and
+generally the receiver can opt to not send one, making it useless in
+this case.)
+
+=item * B: LON-CAPA knows about the sender, such as where
+they are in a course. When a student mails an instructor asking for
+help on the problem, the instructor receives not just the student's
+question, but all submissions the student has made up to that point,
+the user's rendering of the problem, and the complete view the student
+saw of the resource, including discussion up to that point. Finally,
+the instructor is reading all of this inside of LON-CAPA, not their
+email program, so they have full access to LON-CAPA's grading
+interface, or other features they may wish to use in response to the
+student's query.
+
+=item * B: LON-CAPA can block display of e-mails that are
+sent to a student during an online exam. A course coordinator or
+instructor can set an open and close date/time for scheduled online
+exams in a course. If a user uses the LON-CAPA internal messaging
+system to display e-mails during the scheduled blocking event,
+display of all e-mail sent during the blocking period will be
+suppressed, and a message of explanation, including details of the
+currently active blocking periods will be displayed instead. A user
+who has a course coordinator or instructor role in a course will be
+unaffected by any blocking periods for the course, unless the user
+also has a student role in the course, AND has selected the student role.
+
+=back
+
+Users can ask LON-CAPA to forward messages to conventional e-mail
+addresses on their B screen, but generally, LON-CAPA messages
+are much more useful then traditional email can be made to be, even
+with HTML support.
+
+Right now, this document will cover just how to send a message, since
+it is likely you will not need to programmatically read messages,
+since lonmsg already implements that functionality.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=cut
+
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();
+use Mail::Send;
+use Apache::lonlocal;
+use Apache::loncommunicate;
+
+# Querystring component with sorting type
+my $sqs;
+my $startdis;
+my $interdis;
# ===================================================================== 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;
+ my ($subject,$message,$citation,$baseurl,$attachmenturl,
+ $recuser,$recdomain)=@_;
+ $message =&HTML::Entities::encode($message,'<>&"');
+ $citation=&HTML::Entities::encode($citation,'<>&"');
+ $subject =&HTML::Entities::encode($subject,'<>&"');
+ #remove machine specification
+ $baseurl =~ s|^http://[^/]+/|/|;
+ $baseurl =&HTML::Entities::encode($baseurl,'<>&"');
+ #remove machine specification
+ $attachmenturl =~ s|^http://[^/]+/|/|;
+ $attachmenturl =&HTML::Entities::encode($attachmenturl,'<>&"');
+
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'}.' '.
+ my $result=''.$ENV{'user.name'}.' '.
''.$ENV{'user.domain'}.' '.
''.$subject.' '.
- ''.localtime($now).' '.
+ ''.&Apache::lonlocal::locallocaltime($now).' '.
''.$ENV{'SERVER_NAME'}.' '.
''.$ENV{'HTTP_HOST'}.' '.
''.$ENV{'REMOTE_ADDR'}.' '.
@@ -55,17 +155,29 @@ sub packagemsg {
''.$ENV{'browser.mathml'}.' '.
''.$ENV{'HTTP_USER_AGENT'}.' '.
''.$ENV{'request.course.id'}.' '.
+ ''.$ENV{'request.course.sec'}.' '.
''.$ENV{'request.role'}.' '.
''.$ENV{'request.filename'}.' '.
''.$msgid.' '.
- ''.$message.' '.
- ''.$citation.' ';
+ ''.$recuser.' '.
+ ''.$recdomain.' '.
+ ''.$message.' ';
+ if (defined($citation)) {
+ $result.=''.$citation.' ';
+ }
+ if (defined($baseurl)) {
+ $result.= ''.$baseurl.' ';
+ }
+ if (defined($attachmenturl)) {
+ $result.= ''.$attachmenturl.' ';
+ }
+ return $msgid,$result;
}
# ================================================== Unpack message into a hash
sub unpackagemsg {
- my $message=shift;
+ my ($message,$notoken)=@_;
my %content=();
my $parser=HTML::TokeParser->new(\$message);
my $token;
@@ -76,23 +188,96 @@ sub unpackagemsg {
$content{$entry}=$value;
}
}
+ if ($content{'attachmenturl'}) {
+ my ($fname)=($content{'attachmenturl'}=~m|/([^/]+)$|);
+ if ($notoken) {
+ $content{'message'}.=''.&mt('Attachment').': '.$fname.' ';
+ } else {
+ &Apache::lonnet::allowuploaded('/adm/msg',
+ $content{'attachmenturl'});
+ $content{'message'}.='
'.&mt('Attachment').
+ ': '.
+ $fname.' ';
+ }
+ }
return %content;
}
# ======================================================= Get info out of msgid
sub unpackmsgid {
- my $msgid=&Apache::lonnet::unescape(shift);
+ my ($msgid,$folder)=@_;
+ $msgid=&Apache::lonnet::unescape($msgid);
+ my $suffix=&foldersuffix($folder);
my ($sendtime,$shortsubj,$fromname,$fromdomain)=split(/\:/,
&Apache::lonnet::unescape($msgid));
- my %status=&Apache::lonnet::get('email_status',[$msgid]);
+ my %status=&Apache::lonnet::get('email_status'.$suffix,[$msgid]);
if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; }
unless ($status{$msgid}) { $status{$msgid}='new'; }
return ($sendtime,$shortsubj,$fromname,$fromdomain,$status{$msgid});
}
+
+sub sendemail {
+ my ($to,$subject,$body)=@_;
+ $body=
+ "*** ".&mt('This is an automatic message generated by the LON-CAPA system.')."\n".
+ "*** ".&mt('Please do not reply to this address.')."\n\n".$body;
+ my $msg = new Mail::Send;
+ $msg->to($to);
+ $msg->subject('[LON-CAPA] '.$subject);
+ my %oldENV=%ENV;
+ undef(%ENV);
+ if (my $fh = $msg->open()) {
+ print $fh $body;
+ $fh->close;
+ }
+ %ENV=%oldENV;
+ undef(%oldENV);
+}
+
+# ==================================================== Send notification emails
+
+sub sendnotification {
+ my ($to,$touname,$toudom,$subj,$crit)=@_;
+ my $sender=$ENV{'environment.firstname'}.' '.$ENV{'environment.lastname'};
+ my $critical=($crit?' critical':'');
+ my $url='http://'.
+ $Apache::lonnet::hostname{&Apache::lonnet::homeserver($touname,$toudom)}.
+ '/adm/email?username='.$touname.'&domain='.$toudom;
+ my $body=(<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
+=pod
+
+=item * B: Sends message $message to the owner
+ of the resource with the URI $filename.
+
+=cut
+
sub author_res_msg {
my ($filename,$message)=@_;
unless ($message) { return 'empty'; }
@@ -111,25 +296,86 @@ sub author_res_msg {
return 'no_host';
}
+# =========================================== Retrieve author resource messages
+
+sub retrieve_author_res_msg {
+ my $url=shift;
+ $url=&Apache::lonnet::declutter($url);
+ my ($domain,$author)=($url=~/^(\w+)\/(\w+)\//);
+ my %errormsgs=&Apache::lonnet::dump('nohist_res_msgs',$domain,$author);
+ my $msgs='';
+ foreach (keys %errormsgs) {
+ if ($_=~/^\Q$url\E\_\d+$/) {
+ my %content=&unpackagemsg($errormsgs{$_});
+ $msgs.=''.
+ $content{'time'}.' : '.$content{'message'}.
+ '
';
+ }
+ }
+ return $msgs;
+}
+
+
+# =============================== Delete all author messages related to one URL
+
+sub del_url_author_res_msg {
+ my $url=shift;
+ $url=&Apache::lonnet::declutter($url);
+ my ($domain,$author)=($url=~/^(\w+)\/(\w+)\//);
+ my @delmsgs=();
+ foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) {
+ if ($_=~/^\Q$url\E\_\d+$/) {
+ push (@delmsgs,$_);
+ }
+ }
+ return &Apache::lonnet::del('nohist_res_msgs',\@delmsgs,$domain,$author);
+}
+
+# ================= Return hash with URLs for which there is a resource message
+
+sub all_url_author_res_msg {
+ my ($author,$domain)=@_;
+ my %returnhash=();
+ foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) {
+ $_=~/^(.+)\_\d+/;
+ $returnhash{$1}=1;
+ }
+ return %returnhash;
+}
+
# ================================================== Critical message to a user
-sub user_crit_msg {
- my ($user,$domain,$subject,$message)=@_;
+sub user_crit_msg_raw {
+ 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') {
- my $msgid;
($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);
+ if ($ENV{'request.course.id'}) {
+ &user_normal_msg_raw(
+ $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+ 'Critical ['.$user.':'.$domain.']',
+ $message);
+ }
} else {
$status='no_host';
}
+# Notifications
+ my %userenv = &Apache::lonnet::get('environment',['critnotification'],
+ $domain,$user);
+ if ($userenv{'critnotification'}) {
+ &sendnotification($userenv{'critnotification'},$user,$domain,$subject,1);
+ }
+# Log this
&Apache::lonnet::logthis(
'Sending critical email '.$msgid.
', log status: '.
@@ -140,19 +386,49 @@ sub user_crit_msg {
return $status;
}
+# New routine that respects "forward" and calls old routine
+
+=pod
+
+=item * B: Sends
+ a critical message $message to the $user at $domain. If $sendback is true,
+ a reciept will be sent to the current user when $user recieves the message.
+
+=cut
+
+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 {
my $msgid=shift;
my %message=&Apache::lonnet::get('critical',[$msgid]);
- my %contents=&unpackagemsg($message{$msgid});
- my $status='rec: '.
+ my %contents=&unpackagemsg($message{$msgid},1);
+ 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'});
+ &mt('Receipt').': '.$ENV{'user.name'}.' '.&mt('at').' '.$ENV{'user.domain'}.', '.$contents{'subject'},
+ &mt('User').' '.$ENV{'user.name'}.' '.&mt('at').' '.$ENV{'user.domain'}.
+ ' acknowledged receipt of message'."\n".' "'.
+ $contents{'subject'}.'"'."\n".&mt('dated').' '.
+ $contents{'time'}.".\n"
+ ):'no msg req');
$status.=' trans: '.
&Apache::lonnet::put(
'nohist_email',{$contents{'msgid'} => $message{$msgid}});
@@ -167,214 +443,1457 @@ sub user_crit_received {
# ======================================================== Normal communication
-sub user_normal_msg {
- my ($user,$domain,$subject,$message,$citation)=@_;
+sub user_normal_msg_raw {
+ my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl)=@_;
# 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') {
- my $msgid;
- ($msgid,$message)=&packagemsg($subject,$message,$citation);
+ ($msgid,$message)=&packagemsg($subject,$message,$citation,$baseurl,
+ $attachmenturl,$user,$domain);
+# Store in user folder
$status=&Apache::lonnet::critical(
'put:'.$domain.':'.$user.':nohist_email:'.
&Apache::lonnet::escape($msgid).'='.
&Apache::lonnet::escape($message),$homeserver);
+# 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'});
} else {
$status='no_host';
}
+# Notifications
+ my %userenv = &Apache::lonnet::get('environment',['notification'],
+ $domain,$user);
+ if ($userenv{'notification'}) {
+ &sendnotification($userenv{'notification'},$user,$domain,$subject,0);
+ }
&Apache::lonnet::log($ENV{'user.domain'},$ENV{'user.name'},
$ENV{'user.home'},
'Sending '.$msgid.' to '.$user.' at '.$domain.' with status: '.$status);
return $status;
}
+# New routine that respects "forward" and calls old routine
+
+=pod
+
+=item * B: Sends a message to the
+ $user at $domain, with subject $subject and message $message.
+
+=cut
+
+sub user_normal_msg {
+ my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl)=@_;
+ 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,$baseurl,$attachmenturl).' ';
+ }
+ } else {
+ $status=&user_normal_msg_raw($user,$domain,$subject,$message,
+ $citation,$baseurl,$attachmenturl);
+ }
+ return $status;
+}
+
+
+# ============================================================ List all folders
+
+sub folderlist {
+ my $folder=shift;
+ my @allfolders=&Apache::lonnet::getkeys('email_folders');
+ if ($allfolders[0]=~/^error:/) { @allfolders=(); }
+ return '';
+}
+
+# =============================================================== Folder suffix
+
+sub foldersuffix {
+ my $folder=shift;
+ unless ($folder) { return ''; }
+ return '_'.&Apache::lonnet::escape($folder);
+}
+
# =============================================================== Status Change
sub statuschange {
- my ($msgid,$newstatus)=@_;
- my %status=&Apache::lonnet::get('email_status',[$msgid]);
+ my ($msgid,$newstatus,$folder)=@_;
+ my $suffix=&foldersuffix($folder);
+ my %status=&Apache::lonnet::get('email_status'.$suffix,[$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});
+ &Apache::lonnet::put('email_status'.$suffix,{$msgid => $newstatus});
+ }
+ if (($newstatus eq 'deleted') || ($newstatus eq 'new')) {
+ &Apache::lonnet::put('email_status'.$suffix,{$msgid => $newstatus});
}
}
-# ===================================================================== Handler
-sub discrit {
+# ============================================================= Make new folder
+
+sub makefolder {
+ my ($newfolder)=@_;
+ &Apache::lonnet::put('email_folders',{$newfolder => time});
+}
+
+# ======================================================== Move between folders
+
+sub movemsg {
+ my ($msgid,$srcfolder,$trgfolder)=@_;
+ my $unmsgid=&Apache::lonnet::unescape($msgid);
+ my $srcsuffix=&foldersuffix($srcfolder);
+ my $trgsuffix=&foldersuffix($trgfolder);
+
+# Copy message
+ my %message=&Apache::lonnet::get('nohist_email'.$srcsuffix,[$msgid]);
+ &Apache::lonnet::put('nohist_email'.$trgsuffix,{$msgid => $message{$msgid}});
+
+# Copy status
+ my %status=&Apache::lonnet::get('email_status'.$srcsuffix,[$unmsgid]);
+ &Apache::lonnet::put('email_status'.$trgsuffix,{$unmsgid => $status{$unmsgid}});
+# See if was deleted -> becomes "read" in trash
+ my $currentstatus=(&unpackmsgid($status{$unmsgid}),$srcfolder);
+ if ($currentstatus eq 'deleted') {
+ &statuschange($msgid,'read',$trgfolder);
+ }
+# Delete orginals
+ &Apache::lonnet::del('nohist_email'.$srcsuffix,[$msgid]);
+ &Apache::lonnet::del('email_status'.$srcsuffix,[$unmsgid]);
+}
+
+# ======================================================= Display a course list
+
+sub discourse {
my $r=shift;
- $r->print('Critical Messages '.
- '');
+ my $classlist = &Apache::loncoursedata::get_classlist();
+ my $now=time;
+ my %lt=&Apache::lonlocal::texthash('cfa' => 'Check for All',
+ 'cfs' => 'Check for Section/Group',
+ 'cfn' => 'Check for None');
+ $r->print(<
+
+
+
+
+
+
+ENDDISHEADER
+ my %coursepersonnel=&Apache::lonnet::get_course_adv_roles();
+ $r->print('
');
}
-sub handler {
+# ==================================================== Display Critical Message
+
+sub discrit {
my $r=shift;
+ my $header = ''.&mt('Critical Messages').' '.
+ '');
+}
-# ----------------------------------------------------------- Set document type
+sub sortedmessages {
+ my ($blocked,$startblock,$endblock,$numblocked,$folder) = @_;
+ my $suffix=&foldersuffix($folder);
+ my @messages = &Apache::lonnet::getkeys('nohist_email'.$suffix);
+ #unpack the varibles and repack into temp for sorting
+ my @temp;
+ foreach (@messages) {
+ my $msgid=&Apache::lonnet::escape($_);
+ my ($sendtime,$shortsubj,$fromname,$fromdomain,$status)=
+ &Apache::lonmsg::unpackmsgid($msgid,$folder);
+ my @temp1 = ($sendtime,$shortsubj,$fromname,$fromdomain,$status,
+ $msgid);
+ # Check whether message was sent during blocking period.
+ if ($sendtime >= $startblock && ($sendtime <= $endblock && $endblock > 0) ) {
+ my $escid = &Apache::lonnet::unescape($msgid);
+ $$blocked{$escid} = 'ON';
+ $$numblocked ++;
+ } else {
+ push @temp ,\@temp1;
+ }
+ }
+ #default sort
+ @temp = sort {$a->[0] <=> $b->[0]} @temp;
+ if ($ENV{'form.sortedby'} eq "date"){
+ @temp = sort {$a->[0] <=> $b->[0]} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "revdate"){
+ @temp = sort {$b->[0] <=> $a->[0]} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "user"){
+ @temp = sort {lc($a->[2]) cmp lc($b->[2])} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "revuser"){
+ @temp = sort {lc($b->[2]) cmp lc($a->[2])} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "domain"){
+ @temp = sort {$a->[3] cmp $b->[3]} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "revdomain"){
+ @temp = sort {$b->[3] cmp $a->[3]} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "subject"){
+ @temp = sort {lc($a->[1]) cmp lc($b->[1])} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "revsubject"){
+ @temp = sort {lc($b->[1]) cmp lc($a->[1])} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "status"){
+ @temp = sort {$a->[4] cmp $b->[4]} @temp;
+ }
+ if ($ENV{'form.sortedby'} eq "revstatus"){
+ @temp = sort {$b->[4] cmp $a->[4]} @temp;
+ }
+ return @temp;
+}
- $r->content_type('text/html');
- $r->send_http_header;
+# ======================================================== Display all messages
- return OK if $r->header_only;
+sub disall {
+ my ($r,$folder)=@_;
+ my %blocked = ();
+ my %setters = ();
+ my $startblock;
+ my $endblock;
+ my $numblocked = 0;
+ &blockcheck(\%setters,\$startblock,\$endblock);
+ $r->print(<
+ function checkall() {
+ for (i=0; i
+ENDDISHEADER
+ my $fsqs='&folder='.$folder;
+ my @temp=sortedmessages(\%blocked,$startblock,$endblock,\$numblocked,$folder);
+ my $totalnumber=$#temp+1;
+ my $number=int($totalnumber/$interdis)+1;
+ my $firstdis=$interdis*$startdis;
+ if ($firstdis>$#temp) { $firstdis=$#temp-$interdis+1; }
+ my $lastdis=$firstdis+$interdis-1;
+ if ($lastdis>$#temp) { $lastdis=$#temp; }
+ $r->print(''.&mt('Display All Messages').' '.
+ &folderlist($folder).
+ '');
+ if ($numblocked > 0) {
+ my $beginblock = &Apache::lonlocal::locallocaltime($startblock);
+ my $finishblock = &Apache::lonlocal::locallocaltime($endblock);
+ $r->print(' '.
+ $numblocked.' '.&mt('message(s) is/are not viewable because display of LON-CAPA messages sent to you by other students between').' '.$beginblock.' '.&mt('and').' '.$finishblock.' '.&mt('is currently being blocked because of online exams.'));
+ &build_block_table($r,$startblock,$endblock,\%setters);
+ }
+}
- 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 'mark') ||
- ($name eq 'sendreply') || ($name eq 'compose') ||
- ($name eq 'sendmail') || ($name eq 'critical')) {
- unless ($ENV{'form.'.$name}) {
- $ENV{'form.'.$name}=$value;
- }
- }
- } (split(/&/,$ENV{'QUERY_STRING'}));
+# ============================================================== Compose output
-# --------------------------------------------------------------- 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: '.
- 'Reply '.
- $content{'message'}.' '.$content{'citation'});
- } elsif ($ENV{'form.replyto'}) {
- my $msgid=$ENV{'form.replyto'};
- 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';
- }
- $r->print(<<"ENDREPLY");
-
-ENDREPLY
- } 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'}) &&
- (&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'}));
- } else {
- $r->print('Sending: '.&user_normal_msg($content{'sendername'},
- $content{'senderdomain'},
- $ENV{'form.subject'},
- $ENV{'form.message'}));
- }
- } elsif ($ENV{'form.confirm'}) {
- map {
- if ($_=~/^form\.rec\_(.*)$/) {
- $r->print('Confirming Receipt: '.
- &user_crit_received($1).' ');
- }
- } keys %ENV;
- &discrit($r);
- } elsif ($ENV{'form.critical'}) {
- &discrit($r);
- } elsif ($ENV{'form.forward'}) {
- } elsif ($ENV{'form.mark'}) {
- } elsif ($ENV{'form.compose'}) {
- my $dispcrit='';
- if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) {
+sub compout {
+ my ($r,$forwarding,$replying,$broadcast,$replycrit,$folder)=@_;
+
+ if ($broadcast eq 'individual') {
+ &printheader($r,'/adm/email?compose=individual',
+ 'Send a Message');
+ } elsif ($broadcast) {
+ &printheader($r,'/adm/email?compose=group',
+ 'Broadcast Message');
+ } elsif ($forwarding) {
+ &Apache::lonhtmlcommon::add_breadcrumb
+ ({href=>"/adm/email?display=".&Apache::lonnet::escape($forwarding),
+ text=>"Display Message"});
+ &printheader($r,'/adm/email?forward='.&Apache::lonnet::escape($forwarding),
+ 'Forwarding a Message');
+ } elsif ($replying) {
+ &Apache::lonhtmlcommon::add_breadcrumb
+ ({href=>"/adm/email?display=".&Apache::lonnet::escape($replying),
+ text=>"Display Message"});
+ &printheader($r,'/adm/email?replyto='.&Apache::lonnet::escape($replying),
+ 'Replying to a Message');
+ } elsif ($replycrit) {
+ $r->print(''.&mt('Replying to a Critical Message').' ');
+ $replying=$replycrit;
+ } else {
+ &printheader($r,'/adm/email?compose=upload',
+ 'Distribute from Uploaded File');
+ }
+
+ my $dispcrit='';
+ my $dissub='';
+ my $dismsg='';
+ my $func=&mt('Send New');
+ my %lt=&Apache::lonlocal::texthash('us' => 'Username',
+ 'do' => 'Domain',
+ 'ad' => 'Additional Recipients',
+ 'sb' => 'Subject',
+ 'ca' => 'Cancel',
+ 'ma' => 'Mail');
+
+ if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) {
+ my $crithelp = Apache::loncommon::help_open_topic("Course_Critical_Message");
$dispcrit=
- ' Send as critical message';
- }
- $r->print(<<"ENDCOMP");
-
-
-Subject:
-
-
+ ' '.&mt('Send as critical message').' ' . $crithelp .
+ ' '.
+ ' '.&mt('Send as critical message').' ' .
+ &mt('and return receipt') . $crithelp . '
';
+ }
+ my %message;
+ my %content;
+ my $defdom=$ENV{'user.domain'};
+ if ($forwarding) {
+ %message=&Apache::lonnet::get('nohist_email',[$forwarding]);
+ %content=&unpackagemsg($message{$forwarding},$folder);
+ $dispcrit.=' ';
+ $func=&mt('Forward');
+
+ $dissub=&mt('Forwarding').': '.$content{'subject'};
+ $dismsg=&mt('Forwarded message from').' '.
+ $content{'sendername'}.' '.&mt('at').' '.$content{'senderdomain'};
+ }
+ if ($replying) {
+ %message=&Apache::lonnet::get('nohist_email',[$replying]);
+ %content=&unpackagemsg($message{$replying},$folder);
+ $dispcrit.=' ';
+ $func=&mt('Send Reply to');
+
+ $dissub=&mt('Reply').': '.$content{'subject'};
+ $dismsg='> '.$content{'message'};
+ $dismsg=~s/\r/\n/g;
+ $dismsg=~s/\f/\n/g;
+ $dismsg=~s/\n+/\n\> /g;
+ }
+ if ($ENV{'form.recdom'}) { $defdom=$ENV{'form.recdom'}; }
+ $r->print(
+ '
'."\n".
+ ' '."\n".
+ '
+$latexHelp
+$dismsg
+
$dispcrit
-
-
+
+
ENDCOMP
- } elsif ($ENV{'form.sendmail'}) {
- } else {
- $r->print('  Date '.
- 'Username Domain Subject Status ');
- map {
- my ($sendtime,$shortsubj,$fromname,$fromdomain,$status)=
- &Apache::lonmsg::unpackmsgid($_);
- if ($status eq 'new') {
- $r->print('');
- } elsif ($status eq 'read') {
- $r->print(' ');
- } elsif ($status eq 'replied') {
- $r->print(' ');
+ } else { # $broadcast is 'upload'
+ $r->print(<
+
+Generate messages from a file
+
+Subject:
+
+General message text
+$dismsg
+
+
+The file format for the uploaded portion of the message is:
+
+username1\@domain1: text
+username2\@domain2: text
+username3\@domain1: text
+
+
+
+The messages will be assembled from all lines with the respective
+username\@domain , and appended to the general message text.
+
+
+$dispcrit
+
+ENDUPLOAD
+ }
+ if ($broadcast eq 'group') {
+ &discourse;
+ }
+ $r->print('');
+}
+
+# ---------------------------------------------------- Display all face to face
+
+sub retrieve_instructor_comments {
+ my ($user,$domain)=@_;
+ my $target=$ENV{'form.grade_target'};
+ if (! $ENV{'request.course.id'}) { return; }
+ if (! &Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) {
+ return;
+ }
+ my %records=&Apache::lonnet::dump('nohist_email',
+ $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
+ '%255b'.$user.'%253a'.$domain.'%255d');
+ my $result='';
+ foreach (sort(keys(%records))) {
+ my %content=&unpackagemsg($records{$_});
+ next if ($content{'senderdomain'} eq '');
+ next if ($content{'subject'} !~ /^Record/);
+ # $content{'message'}=~s/\n/\ /g;
+ $result.='Recorded by '.
+ $content{'sendername'}.'@'.$content{'senderdomain'}."\n";
+ $result.=
+ &Apache::lontexconvert::msgtexconverted($content{'message'})."\n";
+ }
+ return $result;
+}
+
+sub disfacetoface {
+ my ($r,$user,$domain)=@_;
+ my $target=$ENV{'form.grade_target'};
+ unless ($ENV{'request.course.id'}) { return; }
+ unless (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) {
+ return;
+ }
+ my %records=&Apache::lonnet::dump('nohist_email',
+ $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
+ '%255b'.$user.'%253a'.$domain.'%255d');
+ my $result='';
+ foreach (sort keys %records) {
+ my %content=&unpackagemsg($records{$_});
+ next if ($content{'senderdomain'} eq '');
+ $content{'message'}=~s/\n/\ /g;
+ if ($content{'subject'}=~/^Record/) {
+ $result.=''.&mt('Record').' ';
+ } elsif ($content{'subject'}=~/^Broadcast/) {
+ $result .=''.&mt('Broadcast Message').' ';
+ } else {
+ $result.=''.&mt('Critical Message').' ';
+ %content=&unpackagemsg($content{'message'});
+ $content{'message'}=
+ ''.&mt('Subject').': '.$content{'subject'}.' '.
+ $content{'message'};
+ }
+ $result.=&mt('By').': '.
+&Apache::loncommon::aboutmewrapper(
+ &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}),$content{'sendername'},$content{'senderdomain'}).' ('.
+$content{'sendername'}.'@'.
+ $content{'senderdomain'}.') '.$content{'time'}.
+ ''.
+ &Apache::lontexconvert::msgtexconverted($content{'message'}).
+ ' ';
+ }
+ # Check to see if there were any messages.
+ if ($result eq '') {
+ if ($target ne 'tex') {
+ $r->print("".&mt("No notes, face-to-face discussion records, critical messages, or broadcast messages in this course.")."
");
} else {
- $r->print(' ');
+ $r->print('\textbf{'.&mt("No notes, face-to-face discussion records, critical messages or broadcast messages in this course.").'}\\\\');
+ }
+ } else {
+ $r->print($result);
+ }
+}
+
+# ---------------------------------------------------------------- Face to face
+
+sub facetoface {
+ my ($r,$stage)=@_;
+ unless (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) {
+ return;
+ }
+ &printheader($r,
+ '/adm/email?recordftf=query',
+ "User Notes, Face-to-Face, Critical Messages, Broadcast Messages");
+# from query string
+
+ if ($ENV{'form.recname'}) { $ENV{'form.recuname'}=$ENV{'form.recname'}; }
+ if ($ENV{'form.recdom'}) { $ENV{'form.recdomain'}=$ENV{'form.recdom'}; }
+
+ my $defdom=$ENV{'user.domain'};
+# already filled in
+ if ($ENV{'form.recdomain'}) { $defdom=$ENV{'form.recdomain'}; }
+# generate output
+ my $domform = &Apache::loncommon::select_dom_form($defdom,'recdomain');
+ my $stdbrws = &Apache::loncommon::selectstudent_link
+ ('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',
+ 'subm' => 'Retrieve discussion and message records',
+ 'newr' => 'New Record (record is visible to course faculty and staff)',
+ 'post' => 'Post this Record');
+ $r->print(<<"ENDTREC");
+$lt{'head'}
+
+
+
+
+ENDTREC
+ if (($stage ne 'query') &&
+ ($ENV{'form.recdomain'}) && ($ENV{'form.recuname'})) {
+ chomp($ENV{'form.newrecord'});
+ if ($ENV{'form.newrecord'}) {
+ &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'}.']',
+ $ENV{'form.newrecord'});
}
- $r->print('Open '.localtime($sendtime).' '.
- $fromname.' '.$fromdomain.' '.
- &Apache::lonnet::unescape($shortsubj).' '.
- $status.' ');
- } sort split(/\&/,&Apache::lonnet::reply('keys:'.
- $ENV{'user.domain'}.':'.
- $ENV{'user.name'}.':nohist_email',
- $ENV{'user.home'}));
- $r->print('
');
-
- }
- $r->print('