![]() ![]() | ![]() |
Only show action links if info is available
1: # The LearningOnline Network with CAPA 2: # Routines for messaging 3: # 4: # $Id: lonmsg.pm,v 1.149 2005/06/07 13:42:51 www Exp $ 5: # 6: # Copyright Michigan State University Board of Trustees 7: # 8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA). 9: # 10: # LON-CAPA is free software; you can redistribute it and/or modify 11: # it under the terms of the GNU General Public License as published by 12: # the Free Software Foundation; either version 2 of the License, or 13: # (at your option) any later version. 14: # 15: # LON-CAPA is distributed in the hope that it will be useful, 16: # but WITHOUT ANY WARRANTY; without even the implied warranty of 17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18: # GNU General Public License for more details. 19: # 20: # You should have received a copy of the GNU General Public License 21: # along with LON-CAPA; if not, write to the Free Software 22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23: # 24: # /home/httpd/html/adm/gpl.txt 25: # 26: # http://www.lon-capa.org/ 27: # 28: 29: 30: package Apache::lonmsg; 31: 32: =pod 33: 34: =head1 NAME 35: 36: Apache::lonmsg: supports internal messaging 37: 38: =head1 SYNOPSIS 39: 40: lonmsg provides routines for sending messages, receiving messages, and 41: a handler to allow users to read, send, and delete messages. 42: 43: =head1 OVERVIEW 44: 45: =head2 Messaging Overview 46: 47: X<messages>LON-CAPA provides an internal messaging system similar to 48: email, but customized for LON-CAPA's usage. LON-CAPA implements its 49: own messaging system, rather then building on top of email, because of 50: the features LON-CAPA messages can offer that conventional e-mail can 51: not: 52: 53: =over 4 54: 55: =item * B<Critical messages>: A message the recipient B<must> 56: acknowlegde receipt of before they are allowed to continue using the 57: system, preventing a user from claiming they never got a message 58: 59: =item * B<Receipts>: LON-CAPA can reliably send reciepts informing the 60: sender that it has been read; again, useful for preventing students 61: from claiming they did not see a message. (While conventional e-mail 62: has some reciept support, it's sporadic, e-mail client-specific, and 63: generally the receiver can opt to not send one, making it useless in 64: this case.) 65: 66: =item * B<Context>: LON-CAPA knows about the sender, such as where 67: they are in a course. When a student mails an instructor asking for 68: help on the problem, the instructor receives not just the student's 69: question, but all submissions the student has made up to that point, 70: the user's rendering of the problem, and the complete view the student 71: saw of the resource, including discussion up to that point. Finally, 72: the instructor is reading all of this inside of LON-CAPA, not their 73: email program, so they have full access to LON-CAPA's grading 74: interface, or other features they may wish to use in response to the 75: student's query. 76: 77: =item * B<Blocking>: LON-CAPA can block display of e-mails that are 78: sent to a student during an online exam. A course coordinator or 79: instructor can set an open and close date/time for scheduled online 80: exams in a course. If a user uses the LON-CAPA internal messaging 81: system to display e-mails during the scheduled blocking event, 82: display of all e-mail sent during the blocking period will be 83: suppressed, and a message of explanation, including details of the 84: currently active blocking periods will be displayed instead. A user 85: who has a course coordinator or instructor role in a course will be 86: unaffected by any blocking periods for the course, unless the user 87: also has a student role in the course, AND has selected the student role. 88: 89: =back 90: 91: Users can ask LON-CAPA to forward messages to conventional e-mail 92: addresses on their B<PREF> screen, but generally, LON-CAPA messages 93: are much more useful than traditional email can be made to be, even 94: with HTML support. 95: 96: Right now, this document will cover just how to send a message, since 97: it is likely you will not need to programmatically read messages, 98: since lonmsg already implements that functionality. 99: 100: =head1 FUNCTIONS 101: 102: =over 4 103: 104: =cut 105: 106: use strict; 107: use Apache::lonnet; 108: use vars qw($msgcount); 109: use HTML::TokeParser(); 110: use Apache::Constants qw(:common); 111: use Apache::loncommon(); 112: use Apache::lontexconvert(); 113: use HTML::Entities(); 114: use Mail::Send; 115: use Apache::lonlocal; 116: use Apache::loncommunicate; 117: 118: # Querystring component with sorting type 119: my $sqs; 120: my $startdis; 121: my $interdis; 122: 123: # ===================================================================== Package 124: 125: sub packagemsg { 126: my ($subject,$message,$citation,$baseurl,$attachmenturl, 127: $recuser,$recdomain)=@_; 128: $message =&HTML::Entities::encode($message,'<>&"'); 129: $citation=&HTML::Entities::encode($citation,'<>&"'); 130: $subject =&HTML::Entities::encode($subject,'<>&"'); 131: #remove machine specification 132: $baseurl =~ s|^http://[^/]+/|/|; 133: $baseurl =&HTML::Entities::encode($baseurl,'<>&"'); 134: #remove machine specification 135: $attachmenturl =~ s|^http://[^/]+/|/|; 136: $attachmenturl =&HTML::Entities::encode($attachmenturl,'<>&"'); 137: 138: my $now=time; 139: $msgcount++; 140: my $partsubj=$subject; 141: $partsubj=&Apache::lonnet::escape($partsubj); 142: my $msgid=&Apache::lonnet::escape( 143: $now.':'.$partsubj.':'.$env{'user.name'}.':'. 144: $env{'user.domain'}.':'.$msgcount.':'. 145: $env{'request.course.id'}.':'.$$); 146: my $result='<sendername>'.$env{'user.name'}.'</sendername>'. 147: '<senderdomain>'.$env{'user.domain'}.'</senderdomain>'. 148: '<subject>'.$subject.'</subject>'. 149: '<time>'.&Apache::lonlocal::locallocaltime($now).'</time>'. 150: '<servername>'.$ENV{'SERVER_NAME'}.'</servername>'. 151: '<host>'.$ENV{'HTTP_HOST'}.'</host>'. 152: '<client>'.$ENV{'REMOTE_ADDR'}.'</client>'. 153: '<browsertype>'.$env{'browser.type'}.'</browsertype>'. 154: '<browseros>'.$env{'browser.os'}.'</browseros>'. 155: '<browserversion>'.$env{'browser.version'}.'</browserversion>'. 156: '<browsermathml>'.$env{'browser.mathml'}.'</browsermathml>'. 157: '<browserraw>'.$ENV{'HTTP_USER_AGENT'}.'</browserraw>'. 158: '<courseid>'.$env{'request.course.id'}.'</courseid>'. 159: '<coursesec>'.$env{'request.course.sec'}.'</coursesec>'. 160: '<role>'.$env{'request.role'}.'</role>'. 161: '<resource>'.$env{'request.filename'}.'</resource>'. 162: '<msgid>'.$msgid.'</msgid>'. 163: '<recuser>'.$recuser.'</recuser>'. 164: '<recdomain>'.$recdomain.'</recdomain>'. 165: '<message>'.$message.'</message>'; 166: if (defined($citation)) { 167: $result.='<citation>'.$citation.'</citation>'; 168: } 169: if (defined($baseurl)) { 170: $result.= '<baseurl>'.$baseurl.'</baseurl>'; 171: } 172: if (defined($attachmenturl)) { 173: $result.= '<attachmenturl>'.$attachmenturl.'</attachmenturl>'; 174: } 175: return $msgid,$result; 176: } 177: 178: # ================================================== Unpack message into a hash 179: 180: sub unpackagemsg { 181: my ($message,$notoken)=@_; 182: my %content=(); 183: my $parser=HTML::TokeParser->new(\$message); 184: my $token; 185: while ($token=$parser->get_token) { 186: if ($token->[0] eq 'S') { 187: my $entry=$token->[1]; 188: my $value=$parser->get_text('/'.$entry); 189: $content{$entry}=$value; 190: } 191: } 192: if ($content{'attachmenturl'}) { 193: my ($fname)=($content{'attachmenturl'}=~m|/([^/]+)$|); 194: if ($notoken) { 195: $content{'message'}.='<p>'.&mt('Attachment').': <tt>'.$fname.'</tt>'; 196: } else { 197: &Apache::lonnet::allowuploaded('/adm/msg', 198: $content{'attachmenturl'}); 199: $content{'message'}.='<p>'.&mt('Attachment'). 200: ': <a href="'.$content{'attachmenturl'}.'"><tt>'. 201: $fname.'</tt></a>'; 202: } 203: } 204: return %content; 205: } 206: 207: # ======================================================= Get info out of msgid 208: 209: sub unpackmsgid { 210: my ($msgid,$folder)=@_; 211: $msgid=&Apache::lonnet::unescape($msgid); 212: my $suffix=&foldersuffix($folder); 213: my ($sendtime,$shortsubj,$fromname,$fromdomain,$count,$fromcid)=split(/\:/, 214: &Apache::lonnet::unescape($msgid)); 215: my %status=&Apache::lonnet::get('email_status'.$suffix,[$msgid]); 216: if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; } 217: unless ($status{$msgid}) { $status{$msgid}='new'; } 218: return ($sendtime,$shortsubj,$fromname,$fromdomain,$status{$msgid},$fromcid); 219: } 220: 221: 222: sub sendemail { 223: my ($to,$subject,$body)=@_; 224: $body= 225: "*** ".&mt('This is an automatic message generated by the LON-CAPA system.')."\n". 226: "*** ".&mt('Please do not reply to this address.')."\n\n".$body; 227: my $msg = new Mail::Send; 228: $msg->to($to); 229: $msg->subject('[LON-CAPA] '.$subject); 230: if (my $fh = $msg->open()) { 231: print $fh $body; 232: $fh->close; 233: } 234: } 235: 236: # ==================================================== Send notification emails 237: 238: sub sendnotification { 239: my ($to,$touname,$toudom,$subj,$crit,$text)=@_; 240: my $sender=$env{'environment.firstname'}.' '.$env{'environment.lastname'}; 241: unless ($sender=~/\w/) { 242: $sender=$env{'user.name'}.'@'.$env{'user.domain'}; 243: } 244: my $critical=($crit?' critical':''); 245: $text=~s/\<\;/\</gs; 246: $text=~s/\>\;/\>/gs; 247: $text=~s/\<\/*[^\>]+\>//gs; 248: my $url='http://'. 249: $Apache::lonnet::hostname{&Apache::lonnet::homeserver($touname,$toudom)}. 250: '/adm/email?username='.$touname.'&domain='.$toudom; 251: my $body=(<<ENDMSG); 252: You received a$critical message from $sender in LON-CAPA. The subject is 253: 254: $subj 255: 256: === Excerpt ============================================================ 257: $text 258: ======================================================================== 259: 260: Use 261: 262: $url 263: 264: to access the full message. 265: ENDMSG 266: &sendemail($to,'New'.$critical.' message from '.$sender,$body); 267: } 268: # ============================================================= Check for email 269: 270: sub newmail { 271: if ((time-$env{'user.mailcheck.time'})>300) { 272: my %what=&Apache::lonnet::get('email_status',['recnewemail']); 273: &Apache::lonnet::appenv('user.mailcheck.time'=>time); 274: if ($what{'recnewemail'}>0) { return 1; } 275: } 276: return 0; 277: } 278: 279: # =============================== Automated message to the author of a resource 280: 281: =pod 282: 283: =item * B<author_res_msg($filename, $message)>: Sends message $message to the owner 284: of the resource with the URI $filename. 285: 286: =cut 287: 288: sub author_res_msg { 289: my ($filename,$message)=@_; 290: unless ($message) { return 'empty'; } 291: $filename=&Apache::lonnet::declutter($filename); 292: my ($domain,$author,@dummy)=split(/\//,$filename); 293: my $homeserver=&Apache::lonnet::homeserver($author,$domain); 294: if ($homeserver ne 'no_host') { 295: my $id=unpack("%32C*",$message); 296: my $msgid; 297: ($msgid,$message)=&packagemsg($filename,$message); 298: return &Apache::lonnet::reply('put:'.$domain.':'.$author. 299: ':nohist_res_msgs:'. 300: &Apache::lonnet::escape($filename.'_'.$id).'='. 301: &Apache::lonnet::escape($message),$homeserver); 302: } 303: return 'no_host'; 304: } 305: 306: # =========================================== Retrieve author resource messages 307: 308: sub retrieve_author_res_msg { 309: my $url=shift; 310: $url=&Apache::lonnet::declutter($url); 311: my ($domain,$author)=($url=~/^(\w+)\/(\w+)\//); 312: my %errormsgs=&Apache::lonnet::dump('nohist_res_msgs',$domain,$author); 313: my $msgs=''; 314: foreach (keys %errormsgs) { 315: if ($_=~/^\Q$url\E\_\d+$/) { 316: my %content=&unpackagemsg($errormsgs{$_}); 317: $msgs.='<p><img src="/adm/lonMisc/bomb.gif" /><b>'. 318: $content{'time'}.'</b>: '.$content{'message'}. 319: '<br /></p>'; 320: } 321: } 322: return $msgs; 323: } 324: 325: 326: # =============================== Delete all author messages related to one URL 327: 328: sub del_url_author_res_msg { 329: my $url=shift; 330: $url=&Apache::lonnet::declutter($url); 331: my ($domain,$author)=($url=~/^(\w+)\/(\w+)\//); 332: my @delmsgs=(); 333: foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) { 334: if ($_=~/^\Q$url\E\_\d+$/) { 335: push (@delmsgs,$_); 336: } 337: } 338: return &Apache::lonnet::del('nohist_res_msgs',\@delmsgs,$domain,$author); 339: } 340: 341: # ================= Return hash with URLs for which there is a resource message 342: 343: sub all_url_author_res_msg { 344: my ($author,$domain)=@_; 345: my %returnhash=(); 346: foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) { 347: $_=~/^(.+)\_\d+/; 348: $returnhash{$1}=1; 349: } 350: return %returnhash; 351: } 352: 353: # ================================================== Critical message to a user 354: 355: sub user_crit_msg_raw { 356: my ($user,$domain,$subject,$message,$sendback,$toperm)=@_; 357: # Check if allowed missing 358: my $status=''; 359: my $msgid='undefined'; 360: unless (($message)&&($user)&&($domain)) { $status='empty'; }; 361: my $text=$message; 362: my $homeserver=&Apache::lonnet::homeserver($user,$domain); 363: if ($homeserver ne 'no_host') { 364: ($msgid,$message)=&packagemsg($subject,$message); 365: if ($sendback) { $message.='<sendback>true</sendback>'; } 366: $status=&Apache::lonnet::critical( 367: 'put:'.$domain.':'.$user.':critical:'. 368: &Apache::lonnet::escape($msgid).'='. 369: &Apache::lonnet::escape($message),$homeserver); 370: if ($env{'request.course.id'}) { 371: &user_normal_msg_raw( 372: $env{'course.'.$env{'request.course.id'}.'.num'}, 373: $env{'course.'.$env{'request.course.id'}.'.domain'}, 374: 'Critical ['.$user.':'.$domain.']', 375: $message); 376: } 377: } else { 378: $status='no_host'; 379: } 380: # Notifications 381: my %userenv = &Apache::lonnet::get('environment',['critnotification', 382: 'permanentemail'], 383: $domain,$user); 384: if ($userenv{'critnotification'}) { 385: &sendnotification($userenv{'critnotification'},$user,$domain,$subject,1, 386: $text); 387: } 388: if ($toperm && $userenv{'permanentemail'}) { 389: &sendnotification($userenv{'permanentemail'},$user,$domain,$subject,1, 390: $text); 391: } 392: # Log this 393: &Apache::lonnet::logthis( 394: 'Sending critical email '.$msgid. 395: ', log status: '. 396: &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, 397: $env{'user.home'}, 398: 'Sending critical '.$msgid.' to '.$user.' at '.$domain.' with status: ' 399: .$status)); 400: return $status; 401: } 402: 403: # New routine that respects "forward" and calls old routine 404: 405: =pod 406: 407: =item * B<user_crit_msg($user, $domain, $subject, $message, $sendback)>: Sends 408: a critical message $message to the $user at $domain. If $sendback is true, 409: a reciept will be sent to the current user when $user recieves the message. 410: 411: =cut 412: 413: sub user_crit_msg { 414: my ($user,$domain,$subject,$message,$sendback,$toperm)=@_; 415: my $status=''; 416: my %userenv = &Apache::lonnet::get('environment',['msgforward'], 417: $domain,$user); 418: my $msgforward=$userenv{'msgforward'}; 419: if ($msgforward) { 420: foreach (split(/\,/,$msgforward)) { 421: my ($forwuser,$forwdomain)=split(/\:/,$_); 422: $status.= 423: &user_crit_msg_raw($forwuser,$forwdomain,$subject,$message, 424: $sendback,$toperm).' '; 425: } 426: } else { 427: $status=&user_crit_msg_raw($user,$domain,$subject,$message,$sendback,$toperm); 428: } 429: return $status; 430: } 431: 432: # =================================================== Critical message received 433: 434: sub user_crit_received { 435: my $msgid=shift; 436: my %message=&Apache::lonnet::get('critical',[$msgid]); 437: my %contents=&unpackagemsg($message{$msgid},1); 438: my $status='rec: '.($contents{'sendback'}? 439: &user_normal_msg($contents{'sendername'},$contents{'senderdomain'}, 440: &mt('Receipt').': '.$env{'user.name'}.' '.&mt('at').' '.$env{'user.domain'}.', '.$contents{'subject'}, 441: &mt('User').' '.$env{'user.name'}.' '.&mt('at').' '.$env{'user.domain'}. 442: ' acknowledged receipt of message'."\n".' "'. 443: $contents{'subject'}.'"'."\n".&mt('dated').' '. 444: $contents{'time'}.".\n" 445: ):'no msg req'); 446: $status.=' trans: '. 447: &Apache::lonnet::put( 448: 'nohist_email',{$contents{'msgid'} => $message{$msgid}}); 449: $status.=' del: '. 450: &Apache::lonnet::del('critical',[$contents{'msgid'}]); 451: &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, 452: $env{'user.home'},'Received critical message '. 453: $contents{'msgid'}. 454: ', '.$status); 455: return $status; 456: } 457: 458: # ======================================================== Normal communication 459: 460: sub user_normal_msg_raw { 461: my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl, 462: $toperm)=@_; 463: # Check if allowed missing 464: my $status=''; 465: my $msgid='undefined'; 466: my $text=$message; 467: unless (($message)&&($user)&&($domain)) { $status='empty'; }; 468: my $homeserver=&Apache::lonnet::homeserver($user,$domain); 469: if ($homeserver ne 'no_host') { 470: ($msgid,$message)=&packagemsg($subject,$message,$citation,$baseurl, 471: $attachmenturl,$user,$domain); 472: # Store in user folder 473: $status=&Apache::lonnet::critical( 474: 'put:'.$domain.':'.$user.':nohist_email:'. 475: &Apache::lonnet::escape($msgid).'='. 476: &Apache::lonnet::escape($message),$homeserver); 477: # Save new message received time 478: &Apache::lonnet::put 479: ('email_status',{'recnewemail'=>time},$domain,$user); 480: # Into sent-mail folder 481: $status.=' '.&Apache::lonnet::critical( 482: 'put:'.$env{'user.domain'}.':'.$env{'user.name'}. 483: ':nohist_email_sent:'. 484: &Apache::lonnet::escape($msgid).'='. 485: &Apache::lonnet::escape($message),$env{'user.home'}); 486: } else { 487: $status='no_host'; 488: } 489: # Notifications 490: my %userenv = &Apache::lonnet::get('environment',['notification', 491: 'permanentemail'], 492: $domain,$user); 493: if ($userenv{'notification'}) { 494: &sendnotification($userenv{'notification'},$user,$domain,$subject,0, 495: $text); 496: } 497: if ($toperm && $userenv{'permanentemail'}) { 498: &sendnotification($userenv{'permanentemail'},$user,$domain,$subject,0, 499: $text); 500: } 501: &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, 502: $env{'user.home'}, 503: 'Sending '.$msgid.' to '.$user.' at '.$domain.' with status: '.$status); 504: return $status; 505: } 506: 507: # New routine that respects "forward" and calls old routine 508: 509: =pod 510: 511: =item * B<user_normal_msg($user, $domain, $subject, $message, 512: $citation, $baseurl, $attachmenturl)>: Sends a message to the 513: $user at $domain, with subject $subject and message $message. 514: 515: =cut 516: 517: sub user_normal_msg { 518: my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl, 519: $toperm)=@_; 520: my $status=''; 521: my %userenv = &Apache::lonnet::get('environment',['msgforward'], 522: $domain,$user); 523: my $msgforward=$userenv{'msgforward'}; 524: if ($msgforward) { 525: foreach (split(/\,/,$msgforward)) { 526: my ($forwuser,$forwdomain)=split(/\:/,$_); 527: $status.= 528: &user_normal_msg_raw($forwuser,$forwdomain,$subject,$message, 529: $citation,$baseurl,$attachmenturl,$toperm).' '; 530: } 531: } else { 532: $status=&user_normal_msg_raw($user,$domain,$subject,$message, 533: $citation,$baseurl,$attachmenturl,$toperm); 534: } 535: return $status; 536: } 537: 538: 539: # ============================================================ List all folders 540: 541: sub folderlist { 542: my $folder=shift; 543: my @allfolders=&Apache::lonnet::getkeys('email_folders'); 544: if ($allfolders[0]=~/^error:/) { @allfolders=(); } 545: return '<form method="post" action="/adm/email">'. 546: &mt('Folder').': '. 547: &Apache::loncommon::select_form($folder,'folder', 548: ('' => &mt('INBOX'),'trash' => &mt('TRASH'), 549: 'new' => &mt('New Messages Only'), 550: 'critical' => &mt('Critical'), 551: 'sent' => &mt('Sent Messages'), 552: map { $_ => $_ } @allfolders)). 553: ' '.&mt('Show'). 554: '<select name="interdis">'. 555: join("\n",map { '<option value="'.$_.'"'. 556: ($_==$interdis?' selected="selected"':'').'>'.$_.'</option>' } 557: (10,20,50,100,200)).'</select>'. 558: '<input type="submit" value="'.&mt('View Folder').'" /><br />'. 559: '<input type="hidden" name="sortedby" value="'.$env{'form.sortedby'}.'" />'. 560: ($folder=~/^(new|critical)/?'</form>':''); 561: } 562: 563: sub scrollbuttons { 564: my ($start,$maxdis,$first,$finish,$total)=@_; 565: unless ($total>0) { return ''; } 566: $start++; $maxdis++;$first++;$finish++; 567: return 568: '<input type="submit" name="firstview" value="'.&mt('First').'" />'. 569: '<input type="submit" name="prevview" value="'.&mt('Previous').'" />'. 570: '<input type="text" size="5" name="startdis" value="'.$start.'" onChange="this.form.submit()" /> of '.$maxdis. 571: '<input type="submit" name="nextview" value="'.&mt('Next').'" />'. 572: '<input type="submit" name="lastview" value="'.&mt('Last').'" /><br />'. 573: &mt('Messages [_1] through [_2] of [_3]',$first,$finish,$total).'</form>'; 574: } 575: 576: # =============================================================== Folder suffix 577: 578: sub foldersuffix { 579: my $folder=shift; 580: unless ($folder) { return ''; } 581: return '_'.&Apache::lonnet::escape($folder); 582: } 583: 584: # =============================================================== Status Change 585: 586: sub statuschange { 587: my ($msgid,$newstatus,$folder)=@_; 588: my $suffix=&foldersuffix($folder); 589: my %status=&Apache::lonnet::get('email_status'.$suffix,[$msgid]); 590: if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; } 591: unless ($status{$msgid}) { $status{$msgid}='new'; } 592: unless (($status{$msgid} eq 'replied') || 593: ($status{$msgid} eq 'forwarded')) { 594: &Apache::lonnet::put('email_status'.$suffix,{$msgid => $newstatus}); 595: } 596: if (($newstatus eq 'deleted') || ($newstatus eq 'new')) { 597: &Apache::lonnet::put('email_status'.$suffix,{$msgid => $newstatus}); 598: } 599: if ($newstatus eq 'deleted') { 600: &movemsg(&Apache::lonnet::unescape($msgid),$folder,'trash'); 601: } 602: } 603: 604: # ============================================================= Make new folder 605: 606: sub makefolder { 607: my ($newfolder)=@_; 608: if (($newfolder eq 'sent') 609: || ($newfolder eq 'critical') 610: || ($newfolder eq 'trash') 611: || ($newfolder eq 'new')) { return; } 612: &Apache::lonnet::put('email_folders',{$newfolder => time}); 613: } 614: 615: # ======================================================== Move between folders 616: 617: sub movemsg { 618: my ($msgid,$srcfolder,$trgfolder)=@_; 619: if ($srcfolder eq 'new') { $srcfolder=''; } 620: my $srcsuffix=&foldersuffix($srcfolder); 621: my $trgsuffix=&foldersuffix($trgfolder); 622: 623: # Copy message 624: my %message=&Apache::lonnet::get('nohist_email'.$srcsuffix,[$msgid]); 625: &Apache::lonnet::put('nohist_email'.$trgsuffix,{$msgid => $message{$msgid}}); 626: 627: # Copy status 628: unless ($trgfolder eq 'trash') { 629: my %status=&Apache::lonnet::get('email_status'.$srcsuffix,[$msgid]); 630: &Apache::lonnet::put('email_status'.$trgsuffix,{$msgid => $status{$msgid}}); 631: } 632: # Delete orginals 633: &Apache::lonnet::del('nohist_email'.$srcsuffix,[$msgid]); 634: &Apache::lonnet::del('email_status'.$srcsuffix,[$msgid]); 635: } 636: 637: # ======================================================= Display a course list 638: 639: sub discourse { 640: my $r=shift; 641: my $classlist = &Apache::loncoursedata::get_classlist(); 642: my $now=time; 643: my %lt=&Apache::lonlocal::texthash('cfa' => 'Check All', 644: 'cfs' => 'Check Section/Group', 645: 'cfn' => 'Uncheck All'); 646: $r->print(<<ENDDISHEADER); 647: <input type="hidden" name="sendmode" value="group" /> 648: <script> 649: function checkall() { 650: for (i=0; i<document.forms.compemail.elements.length; i++) { 651: if 652: (document.forms.compemail.elements[i].name.indexOf('send_to_')==0) { 653: document.forms.compemail.elements[i].checked=true; 654: } 655: } 656: } 657: 658: function checksec() { 659: for (i=0; i<document.forms.compemail.elements.length; i++) { 660: if 661: (document.forms.compemail.elements[i].name.indexOf 662: ('send_to_&&&'+document.forms.compemail.chksec.value)==0) { 663: document.forms.compemail.elements[i].checked=true; 664: } 665: } 666: } 667: 668: function uncheckall() { 669: for (i=0; i<document.forms.compemail.elements.length; i++) { 670: if 671: (document.forms.compemail.elements[i].name.indexOf('send_to_')==0) { 672: document.forms.compemail.elements[i].checked=false; 673: } 674: } 675: } 676: </script> 677: <input type="button" onClick="checkall()" value="$lt{'cfa'}" /> 678: <input type="button" onClick="checksec()" value="$lt{'cfs'}" /> 679: <input type="text" size="5" name="chksec" /> 680: <input type="button" onClick="uncheckall()" value="$lt{'cfn'}" /> 681: <p> 682: ENDDISHEADER 683: my %coursepersonnel=&Apache::lonnet::get_course_adv_roles(); 684: $r->print('<table>'); 685: foreach my $role (sort keys %coursepersonnel) { 686: foreach (split(/\,/,$coursepersonnel{$role})) { 687: my ($puname,$pudom)=split(/\:/,$_); 688: $r->print('<tr><td><label>'. 689: '<input type="checkbox" name="send_to_&&&&&&_'. 690: $puname.':'.$pudom.'" /> '. 691: &Apache::loncommon::plainname($puname,$pudom). 692: '</label></td>'. 693: '<td>('.$_.'),</td><td><i>'.$role.'</i></td></tr>'); 694: } 695: } 696: $r->print('</table><table>'); 697: my $sort = sub { 698: my $aname=lc($classlist->{$a}[&Apache::loncoursedata::CL_FULLNAME()]); 699: if (!$aname) { $aname=$a; } 700: my $bname=lc($classlist->{$b}[&Apache::loncoursedata::CL_FULLNAME()]); 701: if (!$bname) { $bname=$b; } 702: return $aname cmp $bname; 703: }; 704: foreach my $student (sort $sort (keys(%{$classlist}))) { 705: my $info=$classlist->{$student}; 706: my ($sname,$sdom,$status,$fullname,$section) = 707: (@{$info}[&Apache::loncoursedata::CL_SNAME(), 708: &Apache::loncoursedata::CL_SDOM(), 709: &Apache::loncoursedata::CL_STATUS(), 710: &Apache::loncoursedata::CL_FULLNAME(), 711: &Apache::loncoursedata::CL_SECTION()]); 712: next if ($status ne 'Active'); 713: next if ($env{'request.course.sec'} && 714: $section ne $env{'request.course.sec'}); 715: my $key = 'send_to_&&&'.$section.'&&&_'.$student; 716: if (! defined($fullname) || $fullname eq '') { $fullname = $sname; } 717: $r->print('<tr><td><label>'. 718: qq{<input type="checkbox" name="$key" />}.(' 'x2). 719: $fullname.'</label></td><td>'.$sname.'@'.$sdom.'</td><td>'.$section. 720: '</td></tr>'); 721: } 722: $r->print('</table>'); 723: } 724: 725: # ==================================================== Display Critical Message 726: 727: sub discrit { 728: my $r=shift; 729: my $header = '<h1><font color=red>'.&mt('Critical Messages').'</font></h1>'. 730: '<form action="/adm/email" method="POST">'. 731: '<input type="hidden" name="confirm" value="true" />'; 732: my %what=&Apache::lonnet::dump('critical'); 733: my $result = ''; 734: foreach (sort keys %what) { 735: my %content=&unpackagemsg($what{$_}); 736: next if ($content{'senderdomain'} eq ''); 737: $result.='<hr />'.&mt('From').': <b>'. 738: &Apache::loncommon::aboutmewrapper( 739: &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}),$content{'sendername'},$content{'senderdomain'}).'</b> ('. 740: $content{'sendername'}.'@'. 741: $content{'senderdomain'}.') '.$content{'time'}. 742: '<br />'.&mt('Subject').': '.$content{'subject'}. 743: '<br /><pre>'. 744: &Apache::lontexconvert::msgtexconverted($content{'message'}). 745: '</pre><small>'. 746: &mt('You have to confirm that you received this message. After confirmation, this message will be moved to your regular inbox'). 747: '</small><br />'. 748: '<input type="submit" name="rec_'.$_.'" value="'.&mt('Confirm Receipt').'" />'. 749: '<input type="submit" name="reprec_'.$_.'" '. 750: 'value="'.&mt('Confirm Receipt and Reply').'" />'; 751: } 752: # Check to see if there were any messages. 753: if ($result eq '') { 754: $result = "<h2>".&mt('You have no critical messages.')."</h2>". 755: '<a href="/adm/roles">'.&mt('Select a course').'</a><br />'. 756: '<a href="/adm/email">'.&mt('Communicate').'</a>'; 757: } else { 758: $r->print($header); 759: } 760: $r->print($result); 761: $r->print('<input type="hidden" name="displayedcrit" value="true" /></form>'); 762: } 763: 764: sub sortedmessages { 765: my ($blocked,$startblock,$endblock,$numblocked,$folder) = @_; 766: my $suffix=&foldersuffix($folder); 767: my @messages = &Apache::lonnet::getkeys('nohist_email'.$suffix); 768: #unpack the varibles and repack into temp for sorting 769: my @temp; 770: foreach (@messages) { 771: my $msgid=&Apache::lonnet::escape($_); 772: my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid)= 773: &Apache::lonmsg::unpackmsgid($msgid,$folder); 774: my @temp1 = ($sendtime,$shortsubj,$fromname,$fromdomain,$status, 775: $msgid); 776: # Check whether message was sent during blocking period. 777: if ($sendtime >= $startblock && ($sendtime <= $endblock && $endblock > 0) ) { 778: my $escid = &Apache::lonnet::unescape($msgid); 779: $$blocked{$escid} = 'ON'; 780: $$numblocked ++; 781: } else { 782: push @temp ,\@temp1; 783: } 784: } 785: #default sort 786: @temp = sort {$a->[0] <=> $b->[0]} @temp; 787: if ($env{'form.sortedby'} eq "date"){ 788: @temp = sort {$a->[0] <=> $b->[0]} @temp; 789: } 790: if ($env{'form.sortedby'} eq "revdate"){ 791: @temp = sort {$b->[0] <=> $a->[0]} @temp; 792: } 793: if ($env{'form.sortedby'} eq "user"){ 794: @temp = sort {lc($a->[2]) cmp lc($b->[2])} @temp; 795: } 796: if ($env{'form.sortedby'} eq "revuser"){ 797: @temp = sort {lc($b->[2]) cmp lc($a->[2])} @temp; 798: } 799: if ($env{'form.sortedby'} eq "domain"){ 800: @temp = sort {$a->[3] cmp $b->[3]} @temp; 801: } 802: if ($env{'form.sortedby'} eq "revdomain"){ 803: @temp = sort {$b->[3] cmp $a->[3]} @temp; 804: } 805: if ($env{'form.sortedby'} eq "subject"){ 806: @temp = sort {lc($a->[1]) cmp lc($b->[1])} @temp; 807: } 808: if ($env{'form.sortedby'} eq "revsubject"){ 809: @temp = sort {lc($b->[1]) cmp lc($a->[1])} @temp; 810: } 811: if ($env{'form.sortedby'} eq "status"){ 812: @temp = sort {$a->[4] cmp $b->[4]} @temp; 813: } 814: if ($env{'form.sortedby'} eq "revstatus"){ 815: @temp = sort {$b->[4] cmp $a->[4]} @temp; 816: } 817: return @temp; 818: } 819: 820: # ======================================================== Display new messages 821: 822: 823: sub disnew { 824: my $r=shift; 825: my %lt=&Apache::lonlocal::texthash( 826: 'nm' => 'New Messages', 827: 'su' => 'Subject', 828: 'da' => 'Date', 829: 'us' => 'Username', 830: 'op' => 'Open', 831: 'do' => 'Domain' 832: ); 833: my @msgids = sort split(/\&/,&Apache::lonnet::reply 834: ('keys:'.$env{'user.domain'}.':'. 835: $env{'user.name'}.':nohist_email', 836: $env{'user.home'})); 837: my @newmsgs; 838: my %setters = (); 839: my $startblock = 0; 840: my $endblock = 0; 841: my %blocked = (); 842: my $numblocked = 0; 843: # Check for blocking of display because of scheduled online exams. 844: &blockcheck(\%setters,\$startblock,\$endblock); 845: foreach (@msgids) { 846: my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)= 847: &Apache::lonmsg::unpackmsgid($_); 848: if (defined($sendtime) && $sendtime!~/error/) { 849: my $numsendtime = $sendtime; 850: $sendtime = &Apache::lonlocal::locallocaltime($sendtime); 851: if ($status eq 'new') { 852: if ($numsendtime >= $startblock && ($numsendtime <= $endblock && $endblock > 0) ) { 853: $blocked{$_} = 'ON'; 854: $numblocked ++; 855: } else { 856: push @newmsgs, { 857: msgid => $_, 858: sendtime => $sendtime, 859: shortsub => &Apache::lonnet::unescape($shortsubj), 860: from => $fromname, 861: fromdom => $fromdom 862: } 863: } 864: } 865: } 866: } 867: if ($#newmsgs >= 0) { 868: $r->print(<<TABLEHEAD); 869: <h2>$lt{'nm'}</h2> 870: <table border=2><tr><th> </th> 871: <th>$lt{'da'}</th><th>$lt{'us'}</th><th>$lt{'do'}</th><th>$lt{'su'}</th></tr> 872: TABLEHEAD 873: foreach my $msg (@newmsgs) { 874: $r->print(<<"ENDLINK"); 875: <tr bgcolor="#FFBB77"> 876: <td><a href="/adm/email?dismode=new&display=$msg->{'msgid'}">$lt{'op'}</a></td> 877: ENDLINK 878: foreach ('sendtime','from','fromdom','shortsub') { 879: $r->print("<td>$msg->{$_}</td>"); 880: } 881: $r->print("</td></tr>"); 882: } 883: $r->print('</table>'.&Apache::loncommon::endbodytag().'</html>'); 884: } elsif ($numblocked == 0) { 885: $r->print("<h3>".&mt('You have no unread messages')."</h3>"); 886: } 887: if ($numblocked > 0) { 888: my $beginblock = &Apache::lonlocal::locallocaltime($startblock); 889: my $finishblock = &Apache::lonlocal::locallocaltime($endblock); 890: if ($numblocked == 1) { 891: $r->print("<h3>".&mt('You have').' '.$numblocked.' '.&mt('blocked unread message').".</h3>"); 892: $r->print(&mt('This message is not viewable because').' '); 893: } else { 894: $r->print("<h3>".&mt('You have').' '.$numblocked.' '.&mt('blocked unread messages').".</h3>"); 895: $r->print(&mt('These').' '.$numblocked.' '.&mt('messages are not viewable because ')); 896: } 897: $r->print( 898: &mt('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').'.'); 899: &build_block_table($r,$startblock,$endblock,\%setters); 900: } 901: } 902: 903: 904: # ======================================================== Display all messages 905: 906: sub disall { 907: my ($r,$folder)=@_; 908: $r->print(&folderlist($folder)); 909: if ($folder eq 'new') { 910: &disnew($r); 911: } elsif ($folder eq 'critical') { 912: &discrit($r); 913: } else { 914: &disfolder($r,$folder); 915: } 916: } 917: 918: # ============================================================ Display a folder 919: 920: sub disfolder { 921: my ($r,$folder)=@_; 922: my %blocked = (); 923: my %setters = (); 924: my $startblock; 925: my $endblock; 926: my $numblocked = 0; 927: &blockcheck(\%setters,\$startblock,\$endblock); 928: $r->print(<<ENDDISHEADER); 929: <script> 930: function checkall() { 931: for (i=0; i<document.forms.disall.elements.length; i++) { 932: if 933: (document.forms.disall.elements[i].name.indexOf('delmark_')==0) { 934: document.forms.disall.elements[i].checked=true; 935: } 936: } 937: } 938: 939: function uncheckall() { 940: for (i=0; i<document.forms.disall.elements.length; i++) { 941: if 942: (document.forms.disall.elements[i].name.indexOf('delmark_')==0) { 943: document.forms.disall.elements[i].checked=false; 944: } 945: } 946: } 947: </script> 948: ENDDISHEADER 949: my $fsqs='&folder='.$folder; 950: my @temp=sortedmessages(\%blocked,$startblock,$endblock,\$numblocked,$folder); 951: my $totalnumber=$#temp+1; 952: unless ($totalnumber>0) { 953: $r->print('<h2>'.&mt('Empty Folder').'</h2>'); 954: return; 955: } 956: unless ($interdis) { 957: $interdis=20; 958: } 959: my $number=int($totalnumber/$interdis); 960: if (($startdis<0) || ($startdis>$number)) { $startdis=$number; } 961: my $firstdis=$interdis*$startdis; 962: if ($firstdis>$#temp) { $firstdis=$#temp-$interdis+1; } 963: my $lastdis=$firstdis+$interdis-1; 964: if ($lastdis>$#temp) { $lastdis=$#temp; } 965: $r->print(&scrollbuttons($startdis,$number,$firstdis,$lastdis,$totalnumber)); 966: $r->print('<form method="post" name="disall" action="/adm/email">'. 967: '<table border=2><tr><th colspan="3"> </th><th>'); 968: if ($env{'form.sortedby'} eq "revdate") { 969: $r->print('<a href = "?sortedby=date'.$fsqs.'">'.&mt('Date').'</a></th>'); 970: } else { 971: $r->print('<a href = "?sortedby=revdate'.$fsqs.'">'.&mt('Date').'</a></th>'); 972: } 973: $r->print('<th>'); 974: if ($env{'form.sortedby'} eq "revuser") { 975: $r->print('<a href = "?sortedby=user'.$fsqs.'">'.&mt('Username').'</a>'); 976: } else { 977: $r->print('<a href = "?sortedby=revuser'.$fsqs.'">'.&mt('Username').'</a>'); 978: } 979: $r->print('</th><th>'); 980: if ($env{'form.sortedby'} eq "revdomain") { 981: $r->print('<a href = "?sortedby=domain'.$fsqs.'">'.&mt('Domain').'</a>'); 982: } else { 983: $r->print('<a href = "?sortedby=revdomain'.$fsqs.'">'.&mt('Domain').'</a>'); 984: } 985: $r->print('</th><th>'); 986: if ($env{'form.sortedby'} eq "revsubject") { 987: $r->print('<a href = "?sortedby=subject'.$fsqs.'">'.&mt('Subject').'</a>'); 988: } else { 989: $r->print('<a href = "?sortedby=revsubject'.$fsqs.'">'.&mt('Subject').'</a>'); 990: } 991: $r->print('</th><th>'); 992: if ($env{'form.sortedby'} eq "revstatus") { 993: $r->print('<a href = "?sortedby=status'.$fsqs.'">'.&mt('Status').'</a></th>'); 994: } else { 995: $r->print('<a href = "?sortedby=revstatus'.$fsqs.'">'.&mt('Status').'</a></th>'); 996: } 997: $r->print("</tr>\n"); 998: for (my $n=$firstdis;$n<=$lastdis;$n++) { 999: my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$origID)= @{$temp[$n]}; 1000: if (($status ne 'deleted') && defined($sendtime) && $sendtime!~/error/) { 1001: if ($status eq 'new') { 1002: $r->print('<tr bgcolor="#FFBB77">'); 1003: } elsif ($status eq 'read') { 1004: $r->print('<tr bgcolor="#BBBB77">'); 1005: } elsif ($status eq 'replied') { 1006: $r->print('<tr bgcolor="#AAAA88">'); 1007: } else { 1008: $r->print('<tr bgcolor="#99BBBB">'); 1009: } 1010: $r->print('<td><input type="checkbox" name="delmark_'.$origID.'" /></td><td><a href="/adm/email?display='.$origID.$sqs. 1011: '">'.&mt('Open').'</a></td><td>'. 1012: ($folder ne 'trash'?'<a href="/adm/email?markdel='.$origID.$sqs. 1013: '">'.&mt('Delete'):' ').'</a></td>'. 1014: '<td>'.&Apache::lonlocal::locallocaltime($sendtime).'</td><td>'. 1015: $fromname.'</td><td>'.$fromdomain.'</td><td>'. 1016: &Apache::lonnet::unescape($shortsubj).'</td><td>'. 1017: $status."</td></tr>\n"); 1018: } elsif ($status eq 'deleted') { 1019: # purge 1020: &movemsg(&Apache::lonnet::unescape($origID),$folder,'trash'); 1021: } 1022: } 1023: $r->print("</table>\n<p>". 1024: '<a href="javascript:checkall()">'.&mt('Check All').'</a> '. 1025: '<a href="javascript:uncheckall()">'.&mt('Uncheck All').'</a></p>'. 1026: '<input type="hidden" name="sortedby" value="'.$env{'form.sortedby'}.'" />'); 1027: if ($folder ne 'trash') { 1028: $r->print( 1029: '<p><input type="submit" name="markeddel" value="'.&mt('Delete Checked').'" /></p>'); 1030: } 1031: $r->print('<p><input type="submit" name="markedmove" value="'.&mt('Move Checked to Folder').'" />'); 1032: my @allfolders=&Apache::lonnet::getkeys('email_folders'); 1033: if ($allfolders[0]=~/^error:/) { @allfolders=(); } 1034: $r->print( 1035: &Apache::loncommon::select_form('','movetofolder', 1036: ( map { $_ => $_ } @allfolders)) 1037: ); 1038: my $postedstartdis=$startdis+1; 1039: $r->print('<input type="hidden" name="folder" value="'.$folder.'" /><input type="hidden" name="startdis" value="'.$postedstartdis.'" /><input type="hidden" name="interdis" value="'.$env{'form.interdis'}.'" /></form>'); 1040: if ($numblocked > 0) { 1041: my $beginblock = &Apache::lonlocal::locallocaltime($startblock); 1042: my $finishblock = &Apache::lonlocal::locallocaltime($endblock); 1043: $r->print('<br /><br />'. 1044: $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.')); 1045: &build_block_table($r,$startblock,$endblock,\%setters); 1046: } 1047: } 1048: 1049: # ============================================================== Compose output 1050: 1051: sub compout { 1052: my ($r,$forwarding,$replying,$broadcast,$replycrit,$folder,$dismode)=@_; 1053: my $suffix=&foldersuffix($folder); 1054: 1055: if ($broadcast eq 'individual') { 1056: &printheader($r,'/adm/email?compose=individual', 1057: 'Send a Message'); 1058: } elsif ($broadcast) { 1059: &printheader($r,'/adm/email?compose=group', 1060: 'Broadcast Message'); 1061: } elsif ($forwarding) { 1062: &Apache::lonhtmlcommon::add_breadcrumb 1063: ({href=>"/adm/email?display=".&Apache::lonnet::escape($forwarding), 1064: text=>"Display Message"}); 1065: &printheader($r,'/adm/email?forward='.&Apache::lonnet::escape($forwarding), 1066: 'Forwarding a Message'); 1067: } elsif ($replying) { 1068: &Apache::lonhtmlcommon::add_breadcrumb 1069: ({href=>"/adm/email?display=".&Apache::lonnet::escape($replying), 1070: text=>"Display Message"}); 1071: &printheader($r,'/adm/email?replyto='.&Apache::lonnet::escape($replying), 1072: 'Replying to a Message'); 1073: } elsif ($replycrit) { 1074: $r->print('<h3>'.&mt('Replying to a Critical Message').'</h3>'); 1075: $replying=$replycrit; 1076: } else { 1077: &printheader($r,'/adm/email?compose=upload', 1078: 'Distribute from Uploaded File'); 1079: } 1080: 1081: my $dispcrit=''; 1082: my $dissub=''; 1083: my $dismsg=''; 1084: my $disbase=''; 1085: my $func=&mt('Send New'); 1086: my %lt=&Apache::lonlocal::texthash('us' => 'Username', 1087: 'do' => 'Domain', 1088: 'ad' => 'Additional Recipients', 1089: 'sb' => 'Subject', 1090: 'ca' => 'Cancel', 1091: 'ma' => 'Mail'); 1092: 1093: if (&Apache::lonnet::allowed('srm',$env{'request.course.id'})) { 1094: my $crithelp = Apache::loncommon::help_open_topic("Course_Critical_Message"); 1095: $dispcrit= 1096: '<p><label><input type="checkbox" name="critmsg" /> '.&mt('Send as critical message').'</label> ' . $crithelp . 1097: '</p><p>'. 1098: '<label><input type="checkbox" name="sendbck" /> '.&mt('Send as critical message').' ' . 1099: &mt('and return receipt') . '</label>' . $crithelp . 1100: '</p><p><label><input type="checkbox" name="permanent" /> '. 1101: &mt('Send copy to permanent email address (if known)').'</label></p>'; 1102: } 1103: my %message; 1104: my %content; 1105: my $defdom=$env{'user.domain'}; 1106: if ($forwarding) { 1107: %message=&Apache::lonnet::get('nohist_email'.$suffix,[$forwarding]); 1108: %content=&unpackagemsg($message{$forwarding},$folder); 1109: $dispcrit.='<input type="hidden" name="forwid" value="'. 1110: $forwarding.'" />'; 1111: $func=&mt('Forward'); 1112: 1113: $dissub=&mt('Forwarding').': '.$content{'subject'}; 1114: $dismsg=&mt('Forwarded message from').' '. 1115: $content{'sendername'}.' '.&mt('at').' '.$content{'senderdomain'}; 1116: if ($content{'baseurl'}) { 1117: $disbase='<input type="hidden" name="baseurl" value="'.&Apache::lonnet::escape($content{'baseurl'}).'" />'; 1118: } 1119: } 1120: if ($replying) { 1121: %message=&Apache::lonnet::get('nohist_email'.$suffix,[$replying]); 1122: %content=&unpackagemsg($message{$replying},$folder); 1123: $dispcrit.='<input type="hidden" name="replyid" value="'. 1124: $replying.'" />'; 1125: $func=&mt('Send Reply to'); 1126: 1127: $dissub=&mt('Reply').': '.$content{'subject'}; 1128: $dismsg='> '.$content{'message'}; 1129: $dismsg=~s/\r/\n/g; 1130: $dismsg=~s/\f/\n/g; 1131: $dismsg=~s/\n+/\n\> /g; 1132: if ($content{'baseurl'}) { 1133: $disbase='<input type="hidden" name="baseurl" value="'.&Apache::lonnet::escape($content{'baseurl'}).'" />'; 1134: if ($env{'user.adv'}) { 1135: $disbase.='<label><input type="checkbox" name="storebasecomment" />'.&mt('Store message for re-use'). 1136: '</label> <a href="/adm/email?showcommentbaseurl='. 1137: &Apache::lonnet::escape($content{'baseurl'}).'" target="comments">'. 1138: &mt('Show re-usable messages').'</a><br />'; 1139: } 1140: } 1141: } 1142: my $citation=&displayresource(%content); 1143: if ($env{'form.recdom'}) { $defdom=$env{'form.recdom'}; } 1144: $r->print( 1145: '<form action="/adm/email" name="compemail" method="post"'. 1146: ' enctype="multipart/form-data">'."\n". 1147: '<input type="hidden" name="sendmail" value="on" />'."\n". 1148: '<table>'); 1149: unless (($broadcast eq 'group') || ($broadcast eq 'upload')) { 1150: if ($replying) { 1151: $r->print('<tr><td colspan="2">'.&mt('Replying to').' '. 1152: &Apache::loncommon::aboutmewrapper( 1153: &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}),$content{'sendername'},$content{'senderdomain'}).' ('. 1154: $content{'sendername'}.'@'. 1155: $content{'senderdomain'}.')'. 1156: '<input type="hidden" name="recuname" value="'.$content{'sendername'}.'" />'. 1157: '<input type="hidden" name="recdomain" value="'.$content{'senderdomain'}.'" />'. 1158: '</td></tr>'); 1159: } else { 1160: my $domform = &Apache::loncommon::select_dom_form($defdom,'recdomain'); 1161: my $selectlink=&Apache::loncommon::selectstudent_link 1162: ('compemail','recuname','recdomain'); 1163: $r->print(<<"ENDREC"); 1164: <tr><td>$lt{'us'}:</td><td><input type="text" size="12" name="recuname" value="$env{'form.recname'}" /></td><td rowspan="2">$selectlink</td></tr> 1165: <tr><td>$lt{'do'}:</td> 1166: <td>$domform</td></tr> 1167: ENDREC 1168: } 1169: } 1170: my $latexHelp = Apache::loncommon::helpLatexCheatsheet(); 1171: if ($broadcast ne 'upload') { 1172: $r->print(<<"ENDCOMP"); 1173: <tr><td>$lt{'ad'}<br /><tt>username\@domain,username\@domain, ... 1174: </tt></td><td> 1175: <input type="text" size="50" name="additionalrec" /></td></tr> 1176: <tr><td>$lt{'sb'}:</td><td><input type="text" size="50" name="subject" value="$dissub" /> 1177: </td></tr></table> 1178: $latexHelp 1179: <textarea name="message" id="message" cols="80" rows="15" wrap="hard">$dismsg 1180: </textarea></p><br /> 1181: $dispcrit 1182: $disbase 1183: <input type="hidden" name="folder" value="$folder" /> 1184: <input type="hidden" name="dismode" value="$dismode" /> 1185: <input type="submit" name="send" value="$func $lt{'ma'}" /> 1186: <input type="submit" name="cancel" value="$lt{'ca'}" /><hr /> 1187: $citation 1188: ENDCOMP 1189: } else { # $broadcast is 'upload' 1190: $r->print(<<ENDUPLOAD); 1191: <input type="hidden" name="sendmode" value="upload" /> 1192: <input type="hidden" name="send" value="on" /> 1193: <h3>Generate messages from a file</h3> 1194: <p> 1195: Subject: <input type="text" size="50" name="subject" /> 1196: </p> 1197: <p>General message text<br /> 1198: <textarea name="message" id="message" cols="60" rows="10" wrap="hard">$dismsg 1199: </textarea></p> 1200: <p> 1201: The file format for the uploaded portion of the message is: 1202: <pre> 1203: username1\@domain1: text 1204: username2\@domain2: text 1205: username3\@domain1: text 1206: </pre> 1207: </p> 1208: <p> 1209: The messages will be assembled from all lines with the respective 1210: <tt>username\@domain</tt>, and appended to the general message text.</p> 1211: <p> 1212: <input type="file" name="upfile" size="40" /></p><p> 1213: $dispcrit 1214: <input type="submit" value="Upload and Send" /></p> 1215: ENDUPLOAD 1216: } 1217: if ($broadcast eq 'group') { 1218: &discourse; 1219: } 1220: $r->print('</form>'. 1221: &Apache::lonhtmlcommon::htmlareaselectactive('message')); 1222: } 1223: 1224: # ---------------------------------------------------- Display all face to face 1225: 1226: sub retrieve_instructor_comments { 1227: my ($user,$domain)=@_; 1228: my $target=$env{'form.grade_target'}; 1229: if (! $env{'request.course.id'}) { return; } 1230: if (! &Apache::lonnet::allowed('srm',$env{'request.course.id'})) { 1231: return; 1232: } 1233: my %records=&Apache::lonnet::dump('nohist_email', 1234: $env{'course.'.$env{'request.course.id'}.'.domain'}, 1235: $env{'course.'.$env{'request.course.id'}.'.num'}, 1236: '%255b'.$user.'%253a'.$domain.'%255d'); 1237: my $result=''; 1238: foreach (sort(keys(%records))) { 1239: my %content=&unpackagemsg($records{$_}); 1240: next if ($content{'senderdomain'} eq ''); 1241: next if ($content{'subject'} !~ /^Record/); 1242: # &Apache::lonfeedback::newline_to_br(\$content{'message'}); 1243: $result.='Recorded by '. 1244: $content{'sendername'}.'@'.$content{'senderdomain'}."\n"; 1245: $result.= 1246: &Apache::lontexconvert::msgtexconverted($content{'message'})."\n"; 1247: } 1248: return $result; 1249: } 1250: 1251: sub disfacetoface { 1252: my ($r,$user,$domain)=@_; 1253: my $target=$env{'form.grade_target'}; 1254: unless ($env{'request.course.id'}) { return; } 1255: unless (&Apache::lonnet::allowed('srm',$env{'request.course.id'})) { 1256: return; 1257: } 1258: my %records=&Apache::lonnet::dump('nohist_email', 1259: $env{'course.'.$env{'request.course.id'}.'.domain'}, 1260: $env{'course.'.$env{'request.course.id'}.'.num'}, 1261: '%255b'.$user.'%253a'.$domain.'%255d'); 1262: my $result=''; 1263: foreach (sort keys %records) { 1264: my %content=&unpackagemsg($records{$_}); 1265: next if ($content{'senderdomain'} eq ''); 1266: &Apache::lonfeedback::newline_to_br(\$content{'message'}); 1267: if ($content{'subject'}=~/^Record/) { 1268: $result.='<h3>'.&mt('Record').'</h3>'; 1269: } elsif ($content{'subject'}=~/^Broadcast/) { 1270: $result .='<h3>'.&mt('Broadcast Message').'</h3>'; 1271: } else { 1272: $result.='<h3>'.&mt('Critical Message').'</h3>'; 1273: %content=&unpackagemsg($content{'message'}); 1274: $content{'message'}= 1275: '<b>'.&mt('Subject').': '.$content{'subject'}.'</b><br />'. 1276: $content{'message'}; 1277: } 1278: $result.=&mt('By').': <b>'. 1279: &Apache::loncommon::aboutmewrapper( 1280: &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}),$content{'sendername'},$content{'senderdomain'}).'</b> ('. 1281: $content{'sendername'}.'@'. 1282: $content{'senderdomain'}.') '.$content{'time'}. 1283: '<br /><pre>'. 1284: &Apache::lontexconvert::msgtexconverted($content{'message'}). 1285: '</pre>'; 1286: } 1287: # Check to see if there were any messages. 1288: if ($result eq '') { 1289: if ($target ne 'tex') { 1290: $r->print("<p><b>".&mt("No notes, face-to-face discussion records, critical messages, or broadcast messages in this course.")."</b></p>"); 1291: } else { 1292: $r->print('\textbf{'.&mt("No notes, face-to-face discussion records, critical messages or broadcast messages in this course.").'}\\\\'); 1293: } 1294: } else { 1295: $r->print($result); 1296: } 1297: } 1298: 1299: # ---------------------------------------------------------------- Face to face 1300: 1301: sub facetoface { 1302: my ($r,$stage)=@_; 1303: unless (&Apache::lonnet::allowed('srm',$env{'request.course.id'})) { 1304: return; 1305: } 1306: &printheader($r, 1307: '/adm/email?recordftf=query', 1308: "User Notes, Face-to-Face, Critical Messages, Broadcast Messages"); 1309: # from query string 1310: 1311: if ($env{'form.recname'}) { $env{'form.recuname'}=$env{'form.recname'}; } 1312: if ($env{'form.recdom'}) { $env{'form.recdomain'}=$env{'form.recdom'}; } 1313: 1314: my $defdom=$env{'user.domain'}; 1315: # already filled in 1316: if ($env{'form.recdomain'}) { $defdom=$env{'form.recdomain'}; } 1317: # generate output 1318: my $domform = &Apache::loncommon::select_dom_form($defdom,'recdomain'); 1319: my $stdbrws = &Apache::loncommon::selectstudent_link 1320: ('stdselect','recuname','recdomain'); 1321: my %lt=&Apache::lonlocal::texthash('user' => 'Username', 1322: 'dom' => 'Domain', 1323: 'head' => 'User Notes, Records of Face-To-Face Discussions, Critical Messages, and Broadcast Messages in Course', 1324: 'subm' => 'Retrieve discussion and message records', 1325: 'newr' => 'New Record (record is visible to course faculty and staff)', 1326: 'post' => 'Post this Record'); 1327: $r->print(<<"ENDTREC"); 1328: <h3>$lt{'head'}</h3> 1329: <form method="post" action="/adm/email" name="stdselect"> 1330: <input type="hidden" name="recordftf" value="retrieve" /> 1331: <table> 1332: <tr><td>$lt{'user'}:</td><td><input type="text" size="12" name="recuname" value="$env{'form.recuname'}" /></td> 1333: <td rowspan="2"> 1334: $stdbrws 1335: <input type="submit" value="$lt{'subm'}" /></td> 1336: </tr> 1337: <tr><td>$lt{'dom'}:</td> 1338: <td>$domform</td></tr> 1339: </table> 1340: </form> 1341: ENDTREC 1342: if (($stage ne 'query') && 1343: ($env{'form.recdomain'}) && ($env{'form.recuname'})) { 1344: chomp($env{'form.newrecord'}); 1345: if ($env{'form.newrecord'}) { 1346: &user_normal_msg_raw( 1347: $env{'course.'.$env{'request.course.id'}.'.num'}, 1348: $env{'course.'.$env{'request.course.id'}.'.domain'}, 1349: &mt('Record'). 1350: ' ['.$env{'form.recuname'}.':'.$env{'form.recdomain'}.']', 1351: $env{'form.newrecord'}); 1352: } 1353: $r->print('<h3>'.&Apache::loncommon::plainname($env{'form.recuname'}, 1354: $env{'form.recdomain'}).'</h3>'); 1355: &disfacetoface($r,$env{'form.recuname'},$env{'form.recdomain'}); 1356: $r->print(<<ENDRHEAD); 1357: <form method="post" action="/adm/email"> 1358: <input name="recdomain" value="$env{'form.recdomain'}" type="hidden" /> 1359: <input name="recuname" value="$env{'form.recuname'}" type="hidden" /> 1360: ENDRHEAD 1361: $r->print(<<ENDBFORM); 1362: <hr />$lt{'newr'}<br /> 1363: <textarea name="newrecord" cols="80" rows="10" wrap="hard"></textarea> 1364: <br /> 1365: <input type="hidden" name="recordftf" value="post" /> 1366: <input type="submit" value="$lt{'post'}" /> 1367: </form> 1368: ENDBFORM 1369: } 1370: } 1371: 1372: # ----------------------------------------------------------- Blocking during exams 1373: 1374: sub examblock { 1375: my ($r,$action) = @_; 1376: unless ($env{'request.course.id'}) { return;} 1377: unless (&Apache::lonnet::allowed('srm',$env{'request.course.id'})) { $r->print('Not allowed'); } 1378: my %lt=&Apache::lonlocal::texthash( 1379: 'comb' => 'Communication Blocking', 1380: 'cbds' => 'Communication blocking during scheduled exams', 1381: 'desc' => 'You can use communication blocking to prevent students enrolled in this course from displaying LON-CAPA messages sent by other students during an online exam. As blocking of communication could potentially interrupt legitimate communication between students who are also both enrolled in a different LON-CAPA course, please be careful that you select the correct start and end times for your scheduled exam when setting or modifying these parameters.', 1382: 'mecb' => 'Modify existing communication blocking periods', 1383: 'ncbc' => 'No communication blocks currently stored' 1384: ); 1385: 1386: my %ltext = &Apache::lonlocal::texthash( 1387: 'dura' => 'Duration', 1388: 'setb' => 'Set by', 1389: 'even' => 'Event', 1390: 'actn' => 'Action', 1391: 'star' => 'Start', 1392: 'endd' => 'End' 1393: ); 1394: 1395: &printheader($r,'/adm/email?block=display',$lt{'comb'}); 1396: $r->print('<h3>'.$lt{'cbds'}.'</h3>'); 1397: 1398: if ($action eq 'store') { 1399: &blockstore($r); 1400: } 1401: 1402: $r->print($lt{'desc'}.'<br /><br /> 1403: <form name="blockform" method="post" action="/adm/email?block=store"> 1404: '); 1405: 1406: $r->print('<h4>'.$lt{'mecb'}.'</h4>'); 1407: my %records = (); 1408: my $blockcount = 0; 1409: my $parmcount = 0; 1410: &get_blockdates(\%records,\$blockcount); 1411: if ($blockcount > 0) { 1412: $parmcount = &display_blocker_status($r,\%records,\%ltext); 1413: } else { 1414: $r->print($lt{'ncbc'}.'<br /><br />'); 1415: } 1416: &display_addblocker_table($r,$parmcount,\%ltext); 1417: my $endbody=&Apache::loncommon::endbodytag(); 1418: $r->print(<<"END"); 1419: <br /> 1420: <input type="hidden" name="blocktotal" value="$blockcount" /> 1421: <input type ="submit" value="Save Changes" /> 1422: </form> 1423: $endbody 1424: </html> 1425: END 1426: return; 1427: } 1428: 1429: sub blockstore { 1430: my $r = shift; 1431: my %lt=&Apache::lonlocal::texthash( 1432: 'tfcm' => 'The following changes were made', 1433: 'cbps' => 'communication blocking period(s)', 1434: 'werm' => 'was/were removed', 1435: 'wemo' => 'was/were modified', 1436: 'wead' => 'was/were added', 1437: 'ncwm' => 'No changes were made.' 1438: ); 1439: my %adds = (); 1440: my %removals = (); 1441: my %cancels = (); 1442: my $modtotal = 0; 1443: my $canceltotal = 0; 1444: my $addtotal = 0; 1445: my %blocking = (); 1446: $r->print('<h3>'.$lt{'head'}.'</h3>'); 1447: foreach (keys %env) { 1448: if ($_ =~ m/^form\.modify_(\w+)$/) { 1449: $adds{$1} = $1; 1450: $removals{$1} = $1; 1451: $modtotal ++; 1452: } elsif ($_ =~ m/^form\.cancel_(\d+)$/) { 1453: $cancels{$1} = $1; 1454: unless ( defined($removals{$1}) ) { 1455: $removals{$1} = $1; 1456: $canceltotal ++; 1457: } 1458: } elsif ($_ =~ m/^form\.add_(\d+)$/) { 1459: $adds{$1} = $1; 1460: $addtotal ++; 1461: } 1462: } 1463: 1464: foreach (keys %removals) { 1465: my $hashkey = $env{'form.key_'.$_}; 1466: &Apache::lonnet::del('comm_block',["$hashkey"], 1467: $env{'course.'.$env{'request.course.id'}.'.domain'}, 1468: $env{'course.'.$env{'request.course.id'}.'.num'} 1469: ); 1470: } 1471: foreach (keys %adds) { 1472: unless ( defined($cancels{$_}) ) { 1473: my ($newstart,$newend) = &get_dates_from_form($_); 1474: my $newkey = $newstart.'____'.$newend; 1475: $blocking{$newkey} = $env{'user.name'}.'@'.$env{'user.domain'}.':'.$env{'form.title_'.$_}; 1476: } 1477: } 1478: if ($addtotal + $modtotal > 0) { 1479: &Apache::lonnet::put('comm_block',\%blocking, 1480: $env{'course.'.$env{'request.course.id'}.'.domain'}, 1481: $env{'course.'.$env{'request.course.id'}.'.num'} 1482: ); 1483: } 1484: my $chgestotal = $canceltotal + $modtotal + $addtotal; 1485: if ($chgestotal > 0) { 1486: $r->print($lt{'tfcm'}.'<ul>'); 1487: if ($canceltotal > 0) { 1488: $r->print('<li>'.$canceltotal.' '.$lt{'cbps'},' '.$lt{'werm'}.'</li>'); 1489: } 1490: if ($modtotal > 0) { 1491: $r->print('<li>'.$modtotal.' '.$lt{'cbps'},' '.$lt{'wemo'}.'</li>'); 1492: } 1493: if ($addtotal > 0) { 1494: $r->print('<li>'.$addtotal.' '.$lt{'cbps'},' '.$lt{'wead'}.'</li>'); 1495: } 1496: $r->print('</ul>'); 1497: } else { 1498: $r->print($lt{'ncwm'}); 1499: } 1500: $r->print('<br />'); 1501: return; 1502: } 1503: 1504: sub get_dates_from_form { 1505: my $item = shift; 1506: my $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate_'.$item); 1507: my $enddate = &Apache::lonhtmlcommon::get_date_from_form('enddate_'.$item); 1508: return ($startdate,$enddate); 1509: } 1510: 1511: sub get_blockdates { 1512: my ($records,$blockcount) = @_; 1513: $$blockcount = 0; 1514: %{$records} = &Apache::lonnet::dump('comm_block', 1515: $env{'course.'.$env{'request.course.id'}.'.domain'}, 1516: $env{'course.'.$env{'request.course.id'}.'.num'} 1517: ); 1518: $$blockcount = keys %{$records}; 1519: 1520: foreach (keys %{$records}) { 1521: if ($_ eq 'error: 2 tie(GDBM) Failed while attempting dump') { 1522: $$blockcount = 0; 1523: last; 1524: } 1525: } 1526: } 1527: 1528: sub display_blocker_status { 1529: my ($r,$records,$ltext) = @_; 1530: my $parmcount = 0; 1531: my @bgcols = ("#eeeeee","#dddddd"); 1532: my $function = &Apache::loncommon::get_users_function(); 1533: my $color = &Apache::loncommon::designparm($function.'.tabbg', 1534: $env{'user.domain'}); 1535: my %lt = &Apache::lonlocal::texthash( 1536: 'modi' => 'Modify', 1537: 'canc' => 'Cancel', 1538: ); 1539: $r->print(<<"END"); 1540: <table border="0" cellpadding="0" cellspacing="0"> 1541: <tr> 1542: <td width="100%" bgcolor="#000000"> 1543: <table width="100%" border="0" cellpadding="1" cellspacing="0"> 1544: <tr> 1545: <td width="100%" bgcolor="#000000"> 1546: <table border="0" cellpadding="3" cellspacing="3" bgcolor="#FFFFFF"> 1547: <tr bgcolor="$color"> 1548: <td><b>$$ltext{'dura'}</b></td> 1549: <td><b>$$ltext{'setb'}</b></td> 1550: <td><b>$$ltext{'even'}</b></td> 1551: <td><b>$$ltext{'actn'}?</b></td> 1552: </tr> 1553: END 1554: foreach (sort keys %{$records}) { 1555: my $iter = $parmcount%2; 1556: my $onchange = 'onFocus="javascript:window.document.forms['. 1557: "'blockform'].elements['modify_".$parmcount."'].". 1558: 'checked=true;"'; 1559: my ($start,$end) = split/____/,$_; 1560: my $startform = &Apache::lonhtmlcommon::date_setter('blockform','startdate_'.$parmcount,$start,$onchange); 1561: my $endform = &Apache::lonhtmlcommon::date_setter('blockform','enddate_'.$parmcount,$end,$onchange); 1562: my ($setter,$title) = split/:/,$$records{$_}; 1563: my ($setuname,$setudom) = split/@/,$setter; 1564: my $settername = &Apache::loncommon::plainname($setuname,$setudom); 1565: $r->print(<<"END"); 1566: <tr bgcolor="$bgcols[$iter]"> 1567: <td>$$ltext{'star'}: $startform<br/>$$ltext{'endd'}: $endform</td> 1568: <td>$settername</td> 1569: <td><input type="text" name="title_$parmcount" size="15" value="$title" /><input type="hidden" name="key_$parmcount" value="$_" /></td> 1570: <td><label>$lt{'modi'}? <input type="checkbox" name="modify_$parmcount" /></label><br /><label>$lt{'canc'}? <input type="checkbox" name="cancel_$parmcount" /></label> 1571: </tr> 1572: END 1573: $parmcount ++; 1574: } 1575: $r->print(<<"END"); 1576: </table> 1577: </td> 1578: </tr> 1579: </table> 1580: </td> 1581: </tr> 1582: </table> 1583: <br /> 1584: <br /> 1585: END 1586: return $parmcount; 1587: } 1588: 1589: sub display_addblocker_table { 1590: my ($r,$parmcount,$ltext) = @_; 1591: my $start = time; 1592: my $end = $start + (60 * 60 * 2); #Default is an exam of 2 hours duration. 1593: my $onchange = 'onFocus="javascript:window.document.forms['. 1594: "'blockform'].elements['add_".$parmcount."'].". 1595: 'checked=true;"'; 1596: my $startform = &Apache::lonhtmlcommon::date_setter('blockform','startdate_'.$parmcount,$start,$onchange); 1597: my $endform = &Apache::lonhtmlcommon::date_setter('blockform','enddate_'.$parmcount,$end,$onchange); 1598: my $function = &Apache::loncommon::get_users_function(); 1599: my $color = &Apache::loncommon::designparm($function.'.tabbg', 1600: $env{'user.domain'}); 1601: my %lt = &Apache::lonlocal::texthash( 1602: 'addb' => 'Add block', 1603: 'exam' => 'e.g., Exam 1', 1604: 'addn' => 'Add new communication blocking periods' 1605: ); 1606: $r->print(<<"END"); 1607: <h4>$lt{'addn'}</h4> 1608: <table border="0" cellpadding="0" cellspacing="0"> 1609: <tr> 1610: <td width="100%" bgcolor="#000000"> 1611: <table width="100%" border="0" cellpadding="1" cellspacing="0"> 1612: <tr> 1613: <td width="100%" bgcolor="#000000"> 1614: <table border="0" cellpadding="3" cellspacing="3" bgcolor="#FFFFFF"> 1615: <tr bgcolor="#CCCCFF"> 1616: <td><b>$$ltext{'dura'}</b></td> 1617: <td><b>$$ltext{'even'} $lt{'exam'}</b></td> 1618: <td><b>$$ltext{'actn'}?</b></td> 1619: </tr> 1620: <tr bgcolor="#eeeeee"> 1621: <td>$$ltext{'star'}: $startform<br />$$ltext{'endd'}: $endform</td> 1622: <td><input type="text" name="title_$parmcount" size="15" value="" /></td> 1623: <td><label>$lt{'addb'}? <input type="checkbox" name="add_$parmcount" value="1" /></label></td> 1624: </tr> 1625: </table> 1626: </td> 1627: </tr> 1628: </table> 1629: </td> 1630: </tr> 1631: </table> 1632: END 1633: return; 1634: } 1635: 1636: sub blockcheck { 1637: my ($setters,$startblock,$endblock) = @_; 1638: # Retrieve active student roles and active course coordinator/instructor roles 1639: my @livecses = (); 1640: my @staffcses = (); 1641: $$startblock = 0; 1642: $$endblock = 0; 1643: foreach (keys %env) { 1644: if ($_ =~ m-^user\.role\.(st|cc|in)\./(.+)$-) { 1645: my $role = $1; 1646: my $cse = $2; 1647: $cse =~ s|/|_|; 1648: if ($env{$_} =~ m/^(\d*)\.(\d*)$/) { 1649: unless (($2 > 0 && $2 < time) || ($1 > time)) { 1650: if ($role eq 'st') { 1651: push @livecses, $cse; 1652: } else { 1653: unless (grep/^$cse$/,@staffcses) { 1654: push @staffcses, $cse; 1655: } 1656: } 1657: } 1658: } 1659: } elsif ($_ =~ m-user\.role\.cr/(\w+)/(\w+)/([^/]+)\./(.+)$- ) { 1660: my $rolepriv = $env{'user.role..rolesdef_'.$3}; 1661: } 1662: } 1663: # Retrieve blocking times and identity of blocker for active courses for students. 1664: if (@livecses > 0) { 1665: foreach my $cse (@livecses) { 1666: my ($cdom,$crs) = split/_/,$cse; 1667: if ( (grep/^$cse$/,@staffcses) && ($env{'request.role'} !~ m-^st\./$cdom/$crs$-) ) { 1668: next; 1669: } else { 1670: %{$$setters{$cse}} = (); 1671: @{$$setters{$cse}{'staff'}} = (); 1672: @{$$setters{$cse}{'times'}} = (); 1673: my %records = &Apache::lonnet::dump('comm_block',$cdom,$crs); 1674: foreach (keys %records) { 1675: if ($_ =~ m/^(\d+)____(\d+)$/) { 1676: if ($1 <= time && $2 >= time) { 1677: my ($staff,$title) = split/:/,$records{$_}; 1678: push @{$$setters{$cse}{'staff'}}, $staff; 1679: push @{$$setters{$cse}{'times'}}, $_; 1680: if ( ($$startblock == 0) || ($$startblock > $1) ) { 1681: $$startblock = $1; 1682: } 1683: if ( ($$endblock == 0) || ($$endblock < $2) ) { 1684: $$endblock = $2; 1685: } 1686: } 1687: } 1688: } 1689: } 1690: } 1691: } 1692: } 1693: 1694: sub build_block_table { 1695: my ($r,$startblock,$endblock,$setters) = @_; 1696: my $function = &Apache::loncommon::get_users_function(); 1697: my $color = &Apache::loncommon::designparm($function.'.tabbg', 1698: $env{'user.domain'}); 1699: my %lt = &Apache::lonlocal::texthash( 1700: 'cacb' => 'Currently active communication blocks', 1701: 'cour' => 'Course', 1702: 'dura' => 'Duration', 1703: 'blse' => 'Block set by' 1704: ); 1705: $r->print(<<"END"); 1706: <br /<br />$lt{'cacb'}:<br /><br /> 1707: <table border="0" cellpadding="0" cellspacing="0"> 1708: <tr> 1709: <td width="100%" bgcolor="#000000"> 1710: <table width="100%" border="0" cellpadding="1" cellspacing="0"> 1711: <tr> 1712: <td width="100%" bgcolor="#000000"> 1713: <table border="0" cellpadding="3" cellspacing="3" bgcolor="#FFFFFF"> 1714: <tr bgcolor="$color"> 1715: <td><b>$lt{'cour'}</b></td> 1716: <td><b>$lt{'dura'}</b></td> 1717: <td><b>$lt{'blse'}</b></td> 1718: </tr> 1719: END 1720: foreach (keys %{$setters}) { 1721: my %courseinfo=&Apache::lonnet::coursedescription($_); 1722: for (my $i=0; $i<@{$$setters{$_}{staff}}; $i++) { 1723: my ($uname,$udom) = split/\@/,$$setters{$_}{staff}[$i]; 1724: my $fullname = &Apache::loncommon::plainname($uname,$udom); 1725: my ($openblock,$closeblock) = split/____/,$$setters{$_}{times}[$i]; 1726: $openblock = &Apache::lonlocal::locallocaltime($openblock); 1727: $closeblock= &Apache::lonlocal::locallocaltime($closeblock); 1728: $r->print('<tr><td>'.$courseinfo{'description'}.'</td>'. 1729: '<td>'.$openblock.' to '.$closeblock.'</td>'. 1730: '<td>'.$fullname.' ('.$uname.'@'.$udom. 1731: ')</td></tr>'); 1732: } 1733: } 1734: $r->print('</table></td></tr></table></td></tr></table>'); 1735: } 1736: 1737: # ----------------------------------------------------------- Display a message 1738: 1739: sub displaymessage { 1740: my ($r,$msgid,$folder)=@_; 1741: my $suffix=&foldersuffix($folder); 1742: my %blocked = (); 1743: my %setters = (); 1744: my $startblock = 0; 1745: my $endblock = 0; 1746: my $numblocked = 0; 1747: # info to generate "next" and "previous" buttons and check if message is blocked 1748: &blockcheck(\%setters,\$startblock,\$endblock); 1749: my @messages=&sortedmessages(\%blocked,$startblock,$endblock,\$numblocked,$folder); 1750: if ( $blocked{$msgid} eq 'ON' ) { 1751: &printheader($r,'/adm/email',&mt('Display a Message')); 1752: $r->print(&mt('You attempted to display a message that is currently blocked because you are enrolled in one or more courses for which there is an ongoing online exam.')); 1753: &build_block_table($r,$startblock,$endblock,\%setters); 1754: return; 1755: } 1756: &statuschange($msgid,'read',$folder); 1757: my %message=&Apache::lonnet::get('nohist_email'.$suffix,[$msgid]); 1758: my %content=&unpackagemsg($message{$msgid}); 1759: 1760: my $counter=0; 1761: $r->print('<pre>'); 1762: my $escmsgid=&Apache::lonnet::escape($msgid); 1763: foreach (@messages) { 1764: if ($_->[5] eq $escmsgid){ 1765: last; 1766: } 1767: $counter++; 1768: } 1769: $r->print('</pre>'); 1770: my $number_of_messages = scalar(@messages); #subtract 1 for last index 1771: # start output 1772: &printheader($r,'/adm/email?display='.&Apache::lonnet::escape($msgid),'Display a Message','',$content{'baseurl'}); 1773: my %courseinfo=&Apache::lonnet::coursedescription($content{'courseid'}); 1774: # Functions 1775: $r->print('<table border="2" width="100%"><tr bgcolor="#FFFFAA"><td>'.&mt('Functions').':</td>'. 1776: '<td><a href="/adm/email?replyto='.&Apache::lonnet::escape($msgid).$sqs. 1777: '"><b>'.&mt('Reply').'</b></a></td>'. 1778: '<td><a href="/adm/email?forward='.&Apache::lonnet::escape($msgid).$sqs. 1779: '"><b>'.&mt('Forward').'</b></a></td>'. 1780: '<td><a href="/adm/email?markunread='.&Apache::lonnet::escape($msgid).$sqs. 1781: '"><b>'.&mt('Mark Unread').'</b></a></td>'. 1782: '<td><a href="/adm/email?markdel='.&Apache::lonnet::escape($msgid).$sqs. 1783: '"><b>'.&mt('Delete').'</b></a></td>'. 1784: '<td><a href="/adm/email?'.$sqs. 1785: ($env{'form.dismode'} eq 'new'?'&folder=new':''). 1786: '"><b>'.&mt('Back to Folder Display').'</b></a></td>'); 1787: if ($counter > 0){ 1788: $r->print('<td><a href="/adm/email?display='.$messages[$counter-1]->[5].$sqs. 1789: '"><b>'.&mt('Previous').'</b></a></td>'); 1790: } 1791: if ($counter < $number_of_messages - 1){ 1792: $r->print('<td><a href="/adm/email?display='.$messages[$counter+1]->[5].$sqs. 1793: '"><b>'.&mt('Next').'</b></a></td>'); 1794: } 1795: $r->print('</tr></table>'); 1796: if ($env{'user.adv'}) { 1797: $r->print('<table border="2" width="100%"><tr bgcolor="#FFAAAA"><td>'.&mt('Currently available actions (will open extra window)').':</td>'); 1798: 1799: if (&Apache::lonnet::allowed('vgr',$env{'request.course.id'})) { 1800: $r->print('<td><b>'.&Apache::loncommon::track_student_link(&mt('View recent activity'),$content{'sendername'},$content{'senderdomain'},'check').'</b></td>'); 1801: } 1802: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'}) && $symb) { 1803: my $symb=&Apache::lonnet::symbread($content{'baseurl'}); 1804: $r->print('<td><b>'.&Apache::loncommon::pprmlink(&mt('Set/Change parameters'),$content{'sendername'},$content{'senderdomain'},$symb,'check').'</b></td>'); 1805: } 1806: if ((&Apache::lonnet::allowed('mgr',$env{'request.course.id'}) && $symb) { 1807: my $symb=&Apache::lonnet::symbread($content{'baseurl'}); 1808: $r->print('<td><b>'.&Apache::loncommon::pgrdlink(&mt('Set/Change grades'),$content{'sendername'},$content{'senderdomain'},$symb,'check').'</b></td>'); 1809: } 1810: $r->print('</tr></table>'); 1811: } 1812: $r->print('<br /><b>'.&mt('Subject').':</b> '.$content{'subject'}. 1813: ($folder ne 'sent'?'<br /><b>'.&mt('From').':</b> '. 1814: &Apache::loncommon::aboutmewrapper( 1815: &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}), 1816: $content{'sendername'},$content{'senderdomain'}).' ('. 1817: $content{'sendername'}.' at '. 1818: $content{'senderdomain'}.') ':'<br /><b>'.&mt('To').':</b> '. 1819: &Apache::loncommon::aboutmewrapper( 1820: &Apache::loncommon::plainname($content{'recuser'},$content{'recdomain'}), 1821: $content{'recuser'},$content{'recdomain'}).' ('. 1822: $content{'recuser'}.' at '. 1823: $content{'recdomain'}.') '). 1824: ($content{'courseid'}?'<br /><b>'.&mt('Course').':</b> '.$courseinfo{'description'}. 1825: ($content{'coursesec'}?' ('.&mt('Group/Section').': '.$content{'coursesec'}.')':''):''). 1826: '<br /><b>'.&mt('Time').':</b> '.$content{'time'}. 1827: ($content{'baseurl'}?'<br /><b>'.&mt('Refers to').':</b> <a href="'.$content{'baseurl'}.'">'. 1828: $content{'baseurl'}.' ('.&Apache::lonnet::gettitle($content{'baseurl'}).')</a>':''). 1829: '<p><pre>'. 1830: &Apache::lontexconvert::msgtexconverted($content{'message'},1). 1831: '</pre><hr />'.&displayresource(%content).'</p>'); 1832: return; 1833: } 1834: 1835: # =========================================================== Show the citation 1836: 1837: sub displayresource { 1838: my %content=@_; 1839: # 1840: # If the recipient is in the same course that the message was sent from and 1841: # has sufficient privileges, show "all details," else show citation 1842: # 1843: if (($env{'request.course.id'} eq $content{'courseid'}) 1844: && (&Apache::lonnet::allowed('vgr',$content{'courseid'}))) { 1845: my $symb=&Apache::lonnet::symbread($content{'baseurl'}); 1846: # Could not get a symb, give up 1847: unless ($symb) { return $content{'citation'}; } 1848: # Have a symb, can render 1849: return '<h2>'.&mt('Current attempts of student (if applicable)').'</h2>'. 1850: &Apache::loncommon::get_previous_attempt($symb, 1851: $content{'sendername'}, 1852: $content{'senderdomain'}, 1853: $content{'courseid'}). 1854: '<hr /><h2>'.&mt('Current screen output (if applicable)').'</h2>'. 1855: &Apache::loncommon::get_student_view($symb, 1856: $content{'sendername'}, 1857: $content{'senderdomain'}, 1858: $content{'courseid'}). 1859: '<h2>'.&mt('Correct Answer(s) (if applicable)').'</h2>'. 1860: &Apache::loncommon::get_student_answers($symb, 1861: $content{'sendername'}, 1862: $content{'senderdomain'}, 1863: $content{'courseid'}); 1864: } else { 1865: return $content{'citation'}; 1866: } 1867: } 1868: 1869: # ================================================================== The Header 1870: 1871: sub header { 1872: my ($r,$title,$baseurl)=@_; 1873: $r->print(&Apache::lonxml::xmlbegin(). 1874: '<head>'.&Apache::lonxml::fontsettings(). 1875: '<title>Communication and Messages</title>'. 1876: &Apache::lonhtmlcommon::htmlareaheaders()); 1877: if ($baseurl) { 1878: $r->print("<base href=\"http://$ENV{'SERVER_NAME'}/$baseurl\" />"); 1879: } 1880: $r->print(&Apache::loncommon::studentbrowser_javascript().'</head>'. 1881: &Apache::loncommon::bodytag('Communication and Messages')); 1882: $r->print(&Apache::lonhtmlcommon::breadcrumbs 1883: (undef,($title?$title:'Communication and Messages'))); 1884: 1885: } 1886: 1887: # ---------------------------------------------------------------- Print header 1888: 1889: sub printheader { 1890: my ($r,$url,$desc,$title,$baseurl)=@_; 1891: &Apache::lonhtmlcommon::add_breadcrumb 1892: ({href=>$url, 1893: text=>$desc}); 1894: &header($r,$title,$baseurl); 1895: } 1896: 1897: # ------------------------------------------------------------ Store the comment 1898: 1899: sub storecomment { 1900: my ($r)=@_; 1901: my $msgtxt=&Apache::lonfeedback::clear_out_html($env{'form.message'}); 1902: my $cleanmsgtxt=''; 1903: foreach (split(/[\n\r]/,$msgtxt)) { 1904: unless ($_=~/^\s*(\>|\>\;)/) { 1905: $cleanmsgtxt.=$_."\n"; 1906: } 1907: } 1908: my $key=&Apache::lonnet::escape($env{'form.baseurl'}).'___'.time; 1909: &Apache::lonnet::put('nohist_stored_comments',{ $key => $cleanmsgtxt }); 1910: } 1911: 1912: sub storedcommentlisting { 1913: my ($r)=@_; 1914: my %msgs=&Apache::lonnet::dump('nohist_stored_comments',undef,undef, 1915: '^'.&Apache::lonnet::escape(&Apache::lonnet::escape($env{'form.showcommentbaseurl'}))); 1916: $r->print(&Apache::lonxml::xmlbegin().'<head>'. 1917: &Apache::lonxml::fontsettings().'</head><body>'); 1918: if ((keys %msgs)[0]=~/^error\:/) { 1919: $r->print(&mt('No stored comments yet.')); 1920: } else { 1921: my $found=0; 1922: foreach (sort keys %msgs) { 1923: $r->print("\n".$msgs{$_}."<hr />"); 1924: $found=1; 1925: } 1926: unless ($found) { 1927: $r->print(&mt('No stored comments yet for this resource.')); 1928: } 1929: } 1930: } 1931: 1932: # ---------------------------------------------------------------- Send an email 1933: 1934: sub sendoffmail { 1935: my ($r,$folder)=@_; 1936: my $suffix=&foldersuffix($folder); 1937: my $sendstatus=''; 1938: if ($env{'form.send'}) { 1939: &printheader($r,'','Messages being sent.'); 1940: $r->rflush(); 1941: my %content=(); 1942: undef %content; 1943: if ($env{'form.forwid'}) { 1944: my $msgid=$env{'form.forwid'}; 1945: my %message=&Apache::lonnet::get('nohist_email'.$suffix,[$msgid]); 1946: %content=&unpackagemsg($message{$msgid},1); 1947: &statuschange($msgid,'forwarded',$folder); 1948: $env{'form.message'}.="\n\n-- Forwarded message --\n\n". 1949: $content{'message'}; 1950: } 1951: if ($env{'form.replyid'}) { 1952: my $msgid=$env{'form.replyid'}; 1953: my %message=&Apache::lonnet::get('nohist_email'.$suffix,[$msgid]); 1954: %content=&unpackagemsg($message{$msgid},1); 1955: &statuschange($msgid,'replied',$folder); 1956: } 1957: my %toaddr=(); 1958: undef %toaddr; 1959: if ($env{'form.sendmode'} eq 'group') { 1960: foreach (keys %env) { 1961: if ($_=~/^form\.send\_to\_\&\&\&[^\&]*\&\&\&\_(.+)$/) { 1962: $toaddr{$1}=''; 1963: } 1964: } 1965: } elsif ($env{'form.sendmode'} eq 'upload') { 1966: foreach (split(/[\n\r\f]+/,$env{'form.upfile'})) { 1967: my ($rec,$txt)=split(/\s*\:\s*/,$_); 1968: if ($txt) { 1969: $rec=~s/\@/\:/; 1970: $toaddr{$rec}.=$txt."\n"; 1971: } 1972: } 1973: } else { 1974: $toaddr{$env{'form.recuname'}.':'.$env{'form.recdomain'}}=''; 1975: } 1976: if ($env{'form.additionalrec'}) { 1977: foreach (split(/\,/,$env{'form.additionalrec'})) { 1978: my ($auname,$audom)=split(/\@/,$_); 1979: $toaddr{$auname.':'.$audom}=''; 1980: } 1981: } 1982: 1983: foreach (keys %toaddr) { 1984: my ($recuname,$recdomain)=split(/\:/,$_); 1985: my $msgtxt; 1986: if ((($env{'form.critmsg'}) || ($env{'form.sendbck'})) && 1987: (&Apache::lonnet::allowed('srm',$env{'request.course.id'}))) { 1988: $msgtxt=&Apache::lonfeedback::clear_out_html($env{'form.message'},1); 1989: } else { 1990: $msgtxt=&Apache::lonfeedback::clear_out_html($env{'form.message'}); 1991: } 1992: if ($toaddr{$_}) { $msgtxt.='<hr />'.$toaddr{$_}; } 1993: my $thismsg; 1994: if ((($env{'form.critmsg'}) || ($env{'form.sendbck'})) && 1995: (&Apache::lonnet::allowed('srm',$env{'request.course.id'}))) { 1996: $r->print(&mt('Sending critical message').' '.$recuname.'@'.$recdomain.': '); 1997: $thismsg=&user_crit_msg($recuname,$recdomain, 1998: &Apache::lonfeedback::clear_out_html($env{'form.subject'}), 1999: $msgtxt, 2000: $env{'form.sendbck'},$env{'form.permanent'}); 2001: } else { 2002: $r->print(&mt('Sending').' '.$recuname.'@'.$recdomain.': '); 2003: $thismsg=&user_normal_msg($recuname,$recdomain, 2004: &Apache::lonfeedback::clear_out_html($env{'form.subject'}), 2005: $msgtxt, 2006: $content{'citation'},undef,undef,$env{'form.permanent'}); 2007: if (($env{'request.course.id'}) && ($env{'form.sendmode'} eq 'group')) { 2008: &user_normal_msg_raw( 2009: $env{'course.'.$env{'request.course.id'}.'.num'}, 2010: $env{'course.'.$env{'request.course.id'}.'.domain'}, 2011: 'Broadcast ['.$recuname.':'.$recdomain.']', 2012: $msgtxt); 2013: } 2014: } 2015: $r->print($thismsg.'<br />'); 2016: $sendstatus.=' '.$thismsg; 2017: } 2018: } else { 2019: &printheader($r,'','No messages sent.'); 2020: } 2021: if ($sendstatus=~/^(\s*(?:ok|con_delayed)\s*)*$/) { 2022: $r->print('<br /><font color="green">'.&mt('Completed.').'</font>'); 2023: if ($env{'form.displayedcrit'}) { 2024: &discrit($r); 2025: } else { 2026: &Apache::loncommunicate::menu($r); 2027: } 2028: } else { 2029: $r->print( 2030: '<h2><font color="red">'.&mt('Could not deliver message').'</font></h2>'. 2031: &mt('Please use the browser "Back" button and correct the recipient addresses') 2032: ); 2033: } 2034: } 2035: 2036: # ===================================================================== Handler 2037: 2038: sub handler { 2039: my $r=shift; 2040: 2041: # ----------------------------------------------------------- Set document type 2042: 2043: &Apache::loncommon::content_type($r,'text/html'); 2044: $r->send_http_header; 2045: 2046: return OK if $r->header_only; 2047: 2048: # --------------------------- Get query string for limited number of parameters 2049: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, 2050: ['display','replyto','forward','markread','markdel','markunread', 2051: 'sendreply','compose','sendmail','critical','recname','recdom', 2052: 'recordftf','sortedby','block','folder','startdis','interdis', 2053: 'showcommentbaseurl','dismode']); 2054: $sqs='&sortedby='.$env{'form.sortedby'}; 2055: 2056: # ------------------------------------------------------ They checked for email 2057: unless ($env{'form.block'}) { 2058: &Apache::lonnet::put('email_status',{'recnewemail'=>0}); 2059: } 2060: 2061: # ----------------------------------------------------------------- Breadcrumbs 2062: 2063: &Apache::lonhtmlcommon::clear_breadcrumbs(); 2064: &Apache::lonhtmlcommon::add_breadcrumb 2065: ({href=>"/adm/communicate", 2066: text=>"Communication/Messages", 2067: faq=>12,bug=>'Communication Tools',}); 2068: 2069: # ------------------------------------------------------------------ Get Folder 2070: 2071: my $folder=$env{'form.folder'}; 2072: unless ($folder) { 2073: $folder=''; 2074: } else { 2075: $sqs.='&folder='.&Apache::lonnet::escape($folder); 2076: } 2077: # ------------------------------------------------------------ Get Display Mode 2078: 2079: my $dismode=$env{'form.dismode'}; 2080: unless ($dismode) { 2081: $dismode=''; 2082: } else { 2083: $sqs.='&dismode='.&Apache::lonnet::escape($dismode); 2084: } 2085: 2086: # --------------------------------------------------------------------- Display 2087: 2088: $startdis=$env{'form.startdis'}; 2089: $startdis--; 2090: unless ($startdis) { $startdis=0; } 2091: 2092: $interdis=$env{'form.interdis'}; 2093: unless ($interdis) { $interdis=20; } 2094: $sqs.='&interdis='.$interdis; 2095: 2096: if ($env{'form.firstview'}) { 2097: $startdis=0; 2098: } 2099: if ($env{'form.lastview'}) { 2100: $startdis=-1; 2101: } 2102: if ($env{'form.prevview'}) { 2103: $startdis--; 2104: } 2105: if ($env{'form.nextview'}) { 2106: $startdis++; 2107: } 2108: my $postedstartdis=$startdis+1; 2109: $sqs.='&startdis='.$postedstartdis; 2110: 2111: # --------------------------------------------------------------- Render Output 2112: 2113: if ($env{'form.display'}) { 2114: &displaymessage($r,$env{'form.display'},$folder); 2115: } elsif ($env{'form.replyto'}) { 2116: &compout($r,'',$env{'form.replyto'},undef,undef,$folder,$dismode); 2117: } elsif ($env{'form.confirm'}) { 2118: &printheader($r,'','Confirmed Receipt'); 2119: foreach (keys %env) { 2120: if ($_=~/^form\.rec\_(.*)$/) { 2121: $r->print('<b>'.&mt('Confirming Receipt').':</b> '. 2122: &user_crit_received($1).'<br>'); 2123: } 2124: if ($_=~/^form\.reprec\_(.*)$/) { 2125: my $msgid=$1; 2126: $r->print('<b>'.&mt('Confirming Receipt').':</b> '. 2127: &user_crit_received($msgid).'<br>'); 2128: &compout($r,'','','',$msgid); 2129: } 2130: } 2131: &discrit($r); 2132: } elsif ($env{'form.critical'}) { 2133: &printheader($r,'','Displaying Critical Messages'); 2134: &discrit($r); 2135: } elsif ($env{'form.forward'}) { 2136: &compout($r,$env{'form.forward'},undef,undef,undef,$folder); 2137: } elsif ($env{'form.markdel'}) { 2138: &printheader($r,'','Deleted Message'); 2139: &statuschange($env{'form.markdel'},'deleted',$folder); 2140: &Apache::loncommunicate::menu($r); 2141: &disall($r,($folder?$folder:$dismode)); 2142: } elsif ($env{'form.markedmove'}) { 2143: my $total=0; 2144: foreach (keys %env) { 2145: if ($_=~/^form\.delmark_(.*)$/) { 2146: &movemsg(&Apache::lonnet::unescape($1),$folder, 2147: $env{'form.movetofolder'}); 2148: $total++; 2149: } 2150: } 2151: &printheader($r,'','Moved Messages'); 2152: $r->print('Moved '.$total.' message(s)<p>'); 2153: &Apache::loncommunicate::menu($r); 2154: &disall($r,($folder?$folder:$dismode)); 2155: } elsif ($env{'form.markeddel'}) { 2156: my $total=0; 2157: foreach (keys %env) { 2158: if ($_=~/^form\.delmark_(.*)$/) { 2159: &statuschange(&Apache::lonnet::unescape($1),'deleted',$folder); 2160: $total++; 2161: } 2162: } 2163: &printheader($r,'','Deleted Messages'); 2164: $r->print('Deleted '.$total.' message(s)<p>'); 2165: &Apache::loncommunicate::menu($r); 2166: &disall($r,($folder?$folder:$dismode)); 2167: } elsif ($env{'form.markunread'}) { 2168: &printheader($r,'','Marked Message as Unread'); 2169: &statuschange($env{'form.markunread'},'new'); 2170: &Apache::loncommunicate::menu($r); 2171: &disall($r,($folder?$folder:$dismode)); 2172: } elsif ($env{'form.compose'}) { 2173: &compout($r,'','',$env{'form.compose'}); 2174: } elsif ($env{'form.recordftf'}) { 2175: &facetoface($r,$env{'form.recordftf'}); 2176: } elsif ($env{'form.block'}) { 2177: &examblock($r,$env{'form.block'}); 2178: } elsif ($env{'form.sendmail'}) { 2179: &sendoffmail($r,$folder); 2180: if ($env{'form.storebasecomment'}) { 2181: &storecomment($r); 2182: } 2183: &disall($r,($folder?$folder:$dismode)); 2184: } elsif ($env{'form.newfolder'}) { 2185: &printheader($r,'','New Folder'); 2186: &makefolder($env{'form.newfolder'}); 2187: &Apache::loncommunicate::menu($r); 2188: &disall($r,$env{'form.newfolder'}); 2189: } elsif ($env{'form.showcommentbaseurl'}) { 2190: &storedcommentlisting($r); 2191: } else { 2192: &printheader($r,'','Display All Messages'); 2193: &Apache::loncommunicate::menu($r); 2194: &disall($r,($folder?$folder:$dismode)); 2195: } 2196: $r->print(&Apache::loncommon::endbodytag().'</html>'); 2197: return OK; 2198: } 2199: # ================================================= Main program, reset counter 2200: 2201: BEGIN { 2202: $msgcount=0; 2203: } 2204: 2205: =pod 2206: 2207: =back 2208: 2209: =cut 2210: 2211: 1; 2212: 2213: __END__ 2214: 2215: 2216: 2217: 2218: 2219: 2220: