3 # Web based Voicemail for Asterisk
5 # Copyright (C) 2002, Linux Support Services, Inc.
7 # Distributed under the terms of the GNU General Public License
9 # Written by Mark Spencer <markster@linux-support.net>
11 # (icky, I know.... if you know better perl please help!)
14 use CGI qw/:standard/;
16 use CGI::Carp qw(fatalsToBrowser);
18 $context=""; # Define here your by default context (so you dont need to put voicemail@context in the login
20 @validfolders = ( "INBOX", "Old", "Work", "Family", "Friends", "Cust1", "Cust2", "Cust3", "Cust4", "Cust5" );
24 name => "Uncompressed WAV",
25 mime => "audio/x-wav",
29 name => "GSM Compressed WAV",
30 mime => "audio/x-wav",
34 name => "Raw GSM Audio",
35 mime => "audio/x-gsm",
40 $astpath = "/_asterisk";
42 $stdcontainerstart = "<table align=center width=600><tr><td>\n";
43 $footer = "<hr><font size=-1><a href=\"http://www.asterisk.org\">The Asterisk Open Source PBX</a> Copyright 2004, <a href=\"http://www.digium.com\">Digium, Inc.</a></a>";
44 $stdcontainerend = "</td></tr><tr><td align=right>$footer</td></tr></table>\n";
51 <TITLE>Asterisk Web-Voicemail</TITLE>
52 <BODY BGCOLOR="white">
55 <input type=hidden name="action" value="login">
57 <tr><td valign=top align=center rowspan=6><img align=center src="$astpath/animlogo.gif"></td></tr>
58 <tr><td align=center colspan=2><font size=+2>Comedian Mail Login</font></td></tr>
59 <tr><td align=center colspan=2><font size=+1>$message</font></td></tr>
60 <tr><td>Mailbox:</td><td><input type=text name="mailbox"></td></tr>
61 <tr><td>Password:</td><td><input type=password name="password"></td></tr>
62 <tr><td align=right colspan=2><input value="Login" type=submit></td></tr>
63 <input type=hidden name="context" value="$context">
74 local ($filename, $startcat) = @_;
75 local ($mbox, $context) = split(/\@/, param('mailbox'));
76 local $pass = param('password');
77 local $category = $startcat;
82 $category = "general";
85 $context = param('context');
91 $filename = "/etc/asterisk/voicemail.conf";
94 # print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
95 open(VMAIL, "<$filename") || die("Bleh, no $filename");
98 if (/include\s\"([^\"]+)\"$/) {
99 ($tmp, $category) = &check_login("/etc/asterisk/$1", $category);
101 # print "Got '$tmp'\n";
102 return ($tmp, $category);
104 } elsif (/\[(.*)\]/) {
106 } elsif (($category ne "general") && ($category ne "zonemessages")) {
107 if (/([^\s]+)\s*\=\>?\s*(.*)/) {
108 @fields = split(/\,\s*/, $2);
109 # print "<p>Mailbox is $1\n";
110 if (($mbox eq $1) && (($pass eq $fields[0]) || ("-${pass}" eq $fields[0])) && ($context eq $category)) {
111 return ($fields[1] ? $fields[1] : "Extension $mbox in $context", $category);
117 return ("", $category);
122 local ($context, $mbox, $filename, $startcat) = @_;
123 local $category = $startcat;
127 $context = param('context');
130 $context = "default";
133 $filename = "/etc/asterisk/voicemail.conf";
136 $category = "general";
138 open(VMAIL, "<$filename") || die("Bleh, no $filename");
141 if (/include\s\"([^\"]+)\"$/) {
142 ($tmp, $category) = &validmailbox($mbox, $context, "/etc/asterisk/$1");
144 return ($tmp, $category);
146 } elsif (/\[(.*)\]/) {
148 } elsif (($category ne "general") && ($category ne "zonemessages") && ($category eq $context)) {
149 if (/([^\s]+)\s*\=\>?\s*(.*)/) {
150 @fields = split(/\,\s*/, $2);
151 if (($mbox eq $1) && ($context eq $category)) {
152 return ($fields[2] ? $fields[2] : "unknown", $category);
157 return ("", $category);
160 sub mailbox_options()
162 local($context, $current, $filename, $category) = @_;
167 $filename = "/etc/asterisk/voicemail.conf";
170 $category = "general";
173 # print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
174 open(VMAIL, "<$filename") || die("Bleh, no voicemail.conf");
178 if (/include\s\"([^\"]+)\"$/) {
179 ($tmp2, $category) = &mailbox_options($context, $current, "/etc/asterisk/$1", $category);
180 # print "Got '$tmp2'...\n";
182 } elsif (/\[(.*)\]/) {
184 } elsif (($category ne "general") && ($category ne "zonemessages")) {
185 if (/([^\s]+)\s*\=\>?\s*(.*)/) {
186 @fields = split(/\,\s*/, $2);
189 $text .= " ($fields[1])";
191 if ($1 eq $current) {
192 $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
194 $tmp .= "<OPTION>$text</OPTION>\n";
201 return ($tmp, $category);
206 local ($name, $context, $current) = @_;
212 $context = "default";
214 $tmp = "<SELECT name=\"$name\">\n";
215 ($opts) = &mailbox_options($context, $current);
217 $tmp .= "</SELECT>\n";
223 my ($context, $mailbox, $folder) = @_;
224 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
225 if (opendir(DIR, $path)) {
226 my @msgs = grep(/^msg....\.txt$/, readdir(DIR));
228 return sprintf "%d", $#msgs + 1;
235 my ($context, $mailbox, $folder) = @_;
236 my $count = &msgcount($context, $mailbox, $folder);
239 } elsif ($count > 0) {
247 my ($context, $mailbox, $folder) = @_;
248 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
249 if (opendir(DIR, $path)) {
250 my @msgs = sort grep(/^msg....\.txt$/, readdir(DIR));
252 return map { s/^msg(....)\.txt$/$1/; $_ } @msgs;
266 cookie(-name => "format", -value =>["$format"], -expires=>"+1y");
271 my ($context, $mailbox, $folder, $msg) = @_;
273 if (open(MSG, "</var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msg}.txt")) {
276 if (/^(\w+)\s*\=\s*(.*)$/) {
281 $fields->{'msgid'} = $msg;
282 } else { print "<BR>Unable to open '$msg' in '$mailbox', '$folder'\n<B>"; }
288 my ($nextaction, $msgid) = @_;
289 my $folder = param('folder');
290 my $mbox = param('mailbox');
291 my $context = param('context');
292 my $passwd = param('password');
293 my $format = param('format');
295 $format = &getcookie('format');
300 <TITLE>Asterisk Web-Voicemail: Preferences</TITLE>
301 <BODY BGCOLOR="white">
304 <table width=100% align=center>
305 <tr><td align=right colspan=3><font size=+2>Web Voicemail Preferences</font></td></tr>
306 <tr><td align=left><font size=+1>Preferred Audio Format:</font></td><td colspan=2></td></tr>
309 foreach $fmt (sort { $formats{$a}->{'pref'} <=> $formats{$b}->{'pref'} } keys %formats) {
310 my $clicked = "checked" if $fmt eq $format;
311 print "<tr><td></td><td align=left><input type=radio name=\"format\" $clicked value=\"$fmt\"></td><td width=100%> $formats{$fmt}->{name}</td></tr>\n";
315 <tr><td align=right colspan=3><input type=submit value="save settings..."></td></tr>
317 <input type=hidden name="action" value="$nextaction">
318 <input type=hidden name="folder" value="$folder">
319 <input type=hidden name="mailbox" value="$mbox">
320 <input type=hidden name="context" value="$context">
321 <input type=hidden name="password" value="$passwd">
322 <input type=hidden name="msgid" value="$msgid">
331 my ($message, $msgid) = @_;
332 my $folder = param('folder');
333 my ($mbox, $context) = split(/\@/, param('mailbox'));
334 my $passwd = param('password');
335 my $format = param('format');
339 $context = param('context');
342 $context = "default";
345 my $folders = &folder_list('newfolder', $context, $mbox, $folder);
346 my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
348 $format = &getcookie('format');
351 &message_prefs("play", $msgid);
353 print header(-cookie => &makecookie($format));
354 $fields = &getfields($context, $mbox, $folder, $msgid);
359 my $duration = $fields->{'duration'};
361 $duration = sprintf "%d:%02d", $duration/60, $duration % 60;
363 $duration = "<i>Unknown</i>";
367 <TITLE>Asterisk Web-Voicemail: $folder Message $msgid</TITLE>
368 <BODY BGCOLOR="white">
371 <table width=100% align=center>
372 <tr><td align=right colspan=3><font size=+1>$folder Message $msgid</font></td></tr>
376 <tr><td align=center colspan=3>
378 <tr><td colspan=2 align=center><font size=+1>$folder <b>$msgid</b></font></td></tr>
379 <tr><td><b>Message:</b></td><td>$msgid</td></tr>\n
380 <tr><td><b>Mailbox:</b></td><td>$mbox\@$context</td></tr>\n
381 <tr><td><b>Folder:</b></td><td>$folder</td></tr>\n
382 <tr><td><b>From:</b></td><td>$fields->{callerid}</td></tr>\n
383 <tr><td><b>Duration:</b></td><td>$duration</td></tr>\n
384 <tr><td><b>Original Date:</b></td><td>$fields->{origdate}</td></tr>\n
385 <tr><td><b>Original Mailbox:</b></td><td>$fields->{origmailbox}</td></tr>\n
386 <tr><td><b>Caller Channel:</b></td><td>$fields->{callerchan}</td></tr>\n
387 <tr><td align=center colspan=2>
388 <input name="action" type=submit value="index">
389 <input name="action" type=submit value="delete ">
390 <input name="action" type=submit value="forward to -> ">
392 <input name="action" type=submit value="save to ->">
394 <input name="action" type=submit value="play ">
395 <input name="action" type=submit value="download">
397 <tr><td colspan=2 align=center>
398 <embed width=400 height=40 src="vmail.cgi?action=audio&folder=$folder&mailbox=$mbox&context=$context&password=$passwd&msgid=$msgid&format=$format&dontcasheme=$$.$format" autostart=yes loop=false></embed>
402 <input type=hidden name="folder" value="$folder">
403 <input type=hidden name="mailbox" value="$mbox">
404 <input type=hidden name="context" value="$context">
405 <input type=hidden name="password" value="$passwd">
406 <input type=hidden name="msgid" value="$msgid">
415 my ($forcedownload) = @_;
416 my $folder = param('folder');
417 my $msgid = param('msgid');
418 my $mailbox = param('mailbox');
419 my $context = param('context');
420 my $format = param('format');
422 $format = &getcookie('format');
424 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msgid}.$format";
426 $msgid =~ /^\d\d\d\d$/ || die("Msgid Liar ($msgid)!");
427 grep(/^${format}$/, keys %formats) || die("Format Liar ($format)!");
429 # Mailbox and folder are already verified
430 if (open(AUDIO, "<$path")) {
433 if ($forcedownload) {
434 print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size, -attachment => "msg${msgid}.$format");
436 print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size);
439 while(($amt = sysread(AUDIO, $data, 4096)) > 0) {
440 syswrite(STDOUT, $data, $amt);
444 die("Hrm, can't seem to open $path\n");
450 my ($folder, $message) = @_;
451 my ($mbox, $context) = split(/\@/, param('mailbox'));
452 my $passwd = param('password');
456 my $newmessages, $oldmessages;
457 my $format = param('format');
459 $format = &getcookie('format');
462 $context = param('context');
465 $context = "default";
468 $msgcount = &msgcountstr($context, $mbox, $folder);
469 $message2 = " Folder '$folder' has " . &msgcountstr($context, $mbox, $folder);
471 $newmessages = &msgcount($context, $mbox, "INBOX");
472 $oldmessages = &msgcount($context, $mbox, "Old");
473 if (($newmessages > 0) || ($oldmessages < 1)) {
478 $message2 = "You have";
479 if ($newmessages > 0) {
480 $message2 .= " <b>$newmessages</b> NEW";
481 if ($oldmessages > 0) {
482 $message2 .= "and <b>$oldmessages</b> OLD";
483 if ($oldmessages != 1) {
484 $message2 .= " messages.";
486 $message2 .= "message.";
489 if ($newmessages != 1) {
490 $message2 .= " messages.";
492 $message2 .= " message.";
496 if ($oldmessages > 0) {
497 $message2 .= " <b>$oldmessages</b> OLD";
498 if ($oldmessages != 1) {
499 $message2 .= " messages.";
501 $message2 .= " message.";
504 $message2 .= " <b>no</b> messages.";
509 my $folders = &folder_list('newfolder', $context, $mbox, $folder);
510 my $cfolders = &folder_list('changefolder', $context, $mbox, $folder);
511 my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
512 print header(-cookie => &makecookie($format));
515 <TITLE>Asterisk Web-Voicemail: $mbox\@$context $folder</TITLE>
516 <BODY BGCOLOR="white">
519 <table width=100% align=center>
520 <tr><td align=center colspan=2><font size=+2><I>$message</I></font></td></tr>
521 <tr><td align=right colspan=2><font size=+1><b>$folder</b> Messages</font> <input type=submit name="action" value="change to ->">$cfolders</td></tr>
522 <tr><td align=left colspan=2><font size=+1>$message2</font></td></tr>
524 <table width=100% align=center cellpadding=0 cellspacing=0>
527 print "<tr><td> Msg</td><td> From</td><td> Duration</td><td> Date</td><td> </td></tr>\n";
528 print "<tr><td><hr></td><td><hr></td><td><hr></td><td><hr></td><td></td></tr>\n";
529 foreach $msg (&messages($context, $mbox, $folder)) {
531 $fields = &getfields($context, $mbox, $folder, $msg);
532 $duration = $fields->{'duration'};
534 $duration = sprintf "%d:%02d", $duration / 60, $duration % 60;
536 $duration = "<i>Unknown</i>";
539 print "<tr><td><input type=checkbox name=\"msgselect\" value=\"$msg\"> <b>$msg</b></td><td>$fields->{'callerid'}</td><td>$duration</td><td>$fields->{'origdate'}</td><td><input name='play$msg' alt=\"Play message $msg\" border=0 type=image align=left src=\"$astpath/play.gif\"></td></tr>\n";
543 print "<tr><td colspan=4 align=center><P><b><i>No messages</i></b><P></td></tr>";
548 <table width=100% align=center>
549 <tr><td align=right colspan=2>
550 <input type="submit" name="action" value="refresh">
555 <input type="submit" name="action" value="delete">
556 <input type="submit" name="action" value="save to ->">
558 <input type="submit" name="action" value="forward to ->">
565 <tr><td align=right colspan=2>
566 <input type="submit" name="action" value="preferences">
567 <input type="submit" name="action" value="logout">
570 <input type=hidden name="folder" value="$folder">
571 <input type=hidden name="mailbox" value="$mbox">
572 <input type=hidden name="context" value="$context">
573 <input type=hidden name="password" value="$passwd">
583 return grep(/^$folder$/, @validfolders);
588 my ($name, $context, $mbox, $selected) = @_;
591 my $tmp = "<SELECT name=\"$name\">\n";
592 foreach $f (@validfolders) {
593 $count = &msgcount($context, $mbox, $f);
594 if ($f eq $selected) {
595 $tmp .= "<OPTION SELECTED>$f ($count)</OPTION>\n";
597 $tmp .= "<OPTION>$f ($count)</OPTION>\n";
605 my ($context, $mbox, $oldfolder, $old, $newfolder, $new) = @_;
606 my $oldfile, $newfile;
607 return if ($old eq $new) && ($oldfolder eq $newfolder);
609 if ($context =~ /^(\w+)$/) {
612 die("Invalid Context<BR>\n");
615 if ($mbox =~ /^(\w+)$/) {
618 die ("Invalid mailbox<BR>\n");
621 if ($oldfolder =~ /^(\w+)$/) {
624 die("Invalid old folder<BR>\n");
627 if ($newfolder =~ /^(\w+)$/) {
630 die("Invalid new folder ($newfolder)<BR>\n");
633 if ($old =~ /^(\d\d\d\d)$/) {
636 die("Invalid old Message<BR>\n");
639 if ($new =~ /^(\d\d\d\d)$/) {
642 die("Invalid old Message<BR>\n");
645 my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder";
647 my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
648 opendir(DIR, $path) || die("Unable to open directory\n");
649 my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
651 foreach $oldfile (@files) {
653 if ($tmp =~ /^(msg${old}.\w+)$/) {
655 $oldfile = $path . "/$tmp";
656 $tmp =~ s/msg${old}/msg${new}/;
657 $newfile = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder/$tmp";
658 # print "Renaming $oldfile to $newfile<BR>\n";
659 rename($oldfile, $newfile);
666 my ($orig, $new) = @_;
669 open(IN, "<$orig") || die("Unable to open '$orig'\n");
670 open(OUT, ">$new") || DIE("Unable to open '$new'\n");
671 while(($res = sysread(IN, $data, 4096)) > 0) {
672 syswrite(OUT, $data, $res);
680 my ($context, $mbox, $newmbox, $oldfolder, $old, $new) = @_;
681 my $oldfile, $newfile;
682 return if ($mbox eq $newmbox);
684 if ($mbox =~ /^(\w+)$/) {
687 die ("Invalid mailbox<BR>\n");
690 if ($newmbox =~ /^(\w+)$/) {
693 die ("Invalid new mailbox<BR>\n");
696 if ($oldfolder =~ /^(\w+)$/) {
699 die("Invalid old folder<BR>\n");
702 if ($old =~ /^(\d\d\d\d)$/) {
705 die("Invalid old Message<BR>\n");
708 if ($new =~ /^(\d\d\d\d)$/) {
711 die("Invalid old Message<BR>\n");
714 my $path = "/var/spool/asterisk/voicemail/$context/$newmbox";
716 my $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
718 my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
719 opendir(DIR, $path) || die("Unable to open directory\n");
720 my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
722 foreach $oldfile (@files) {
724 if ($tmp =~ /^(msg${old}.\w+)$/) {
726 $oldfile = $path . "/$tmp";
727 $tmp =~ s/msg${old}/msg${new}/;
728 $newfile = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX/$tmp";
729 # print "Copying $oldfile to $newfile<BR>\n";
730 &file_copy($oldfile, $newfile);
737 my ($context, $mbox, $folder, $msg) = @_;
738 if ($mbox =~ /^(\w+)$/) {
741 die ("Invalid mailbox<BR>\n");
743 if ($context =~ /^(\w+)$/) {
746 die ("Invalid context<BR>\n");
748 if ($folder =~ /^(\w+)$/) {
751 die("Invalid folder<BR>\n");
753 if ($msg =~ /^(\d\d\d\d)$/) {
756 die("Invalid Message<BR>\n");
758 my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
759 opendir(DIR, $path) || die("Unable to open directory\n");
760 my @files = grep /^msg${msg}\.\w+$/, readdir(DIR);
762 foreach $oldfile (@files) {
763 if ($oldfile =~ /^(msg${msg}.\w+)$/) {
764 $oldfile = $path . "/$1";
765 # print "Deleting $oldfile<BR>\n";
771 sub message_forward()
773 my ($toindex, @msgs) = @_;
774 my $folder = param('folder');
775 my ($mbox, $context) = split(/\@/, param('mailbox'));
776 my $newmbox = param('forwardto');
780 $context = param('context');
783 $context = "default";
785 $newmbox =~ s/(\w+)(\s+.*)?$/$1/;
786 if (!&validmailbox($context, $newmbox)) {
787 die("Bah! Not a valid mailbox '$newmbox'\n");
790 $msgcount = &msgcount($context, $newmbox, "INBOX");
792 if ($newmbox ne $mbox) {
794 foreach $msg (@msgs) {
795 # print "Forwarding $msg from $mbox to $newmbox<BR>\n";
796 &message_copy($context, $mbox, $newmbox, $folder, $msg, sprintf "%04d", $msgcount);
799 $txt = "Forwarded messages " . join(', ', @msgs) . "to $newmbox";
801 $txt = "Can't forward messages to yourself!\n";
804 &message_index($folder, $txt);
806 &message_play($txt, $msgs[0]);
810 sub message_delete_or_move()
812 my ($toindex, $del, @msgs) = @_;
816 my $folder = param('folder');
817 my $newfolder = param('newfolder') unless $del;
818 $newfolder =~ s/^(\w+)\s+.*$/$1/;
819 my ($mbox, $context) = split(/\@/, param('mailbox'));
821 $context = param('context');
824 $context = "default";
826 my $passwd = param('password');
827 my $msgcount = &msgcount($context, $mbox, $folder);
828 my $omsgcount = &msgcount($context, $mbox, $newfolder) if $newfolder;
830 if ($newfolder ne $folder) {
832 for ($x=0;$x<$msgcount;$x++) {
833 my $msg = sprintf "%04d", $x;
834 my $newmsg = sprintf "%04d", $y;
835 if (grep(/^$msg$/, @msgs)) {
837 &message_rename($context, $mbox, $folder, $msg, $newfolder, sprintf "%04d", $omsgcount);
840 &message_delete($context, $mbox, $folder, $msg);
843 &message_rename($context, $mbox, $folder, $msg, $folder, $newmsg);
848 $txt = "Deleted messages " . join (', ', @msgs);
850 $txt = "Moved messages " . join (', ', @msgs) . " to $newfolder";
853 $txt = "Can't move a message to the same folder they're in already";
855 # Not as many messages now
857 if ($toindex || ($msgs[0] >= $msgcount)) {
858 &message_index($folder, $txt);
860 &message_play($txt, $msgs[0]);
865 my $folder = param('folder');
866 my $changefolder = param('changefolder');
867 $changefolder =~ s/(\w+)\s+.*$/$1/;
869 my $newfolder = param('newfolder');
870 $newfolder =~ s/^(\w+)\s+.*$/$1/;
871 if ($newfolder && !&validfolder($newfolder)) {
873 die("Bah! new folder '$newfolder' isn't a folder.");
875 $action = param('action');
876 $msgid = param('msgid');
878 my ($tmp) = grep /^play\d\d\d\d\.x$/, param;
879 if ($tmp =~ /^play(\d\d\d\d)/) {
884 print "No message?<BR>\n";
888 @msgs = param('msgselect');
889 @msgs = ($msgid) unless @msgs;
891 ($mailbox) = &check_login();
892 if (length($mailbox)) {
893 if ($action eq 'login') {
894 &message_index($folder, "Welcome, $mailbox");
895 } elsif (($action eq 'refresh') || ($action eq 'index')) {
896 &message_index($folder, "Welcome, $mailbox");
897 } elsif ($action eq 'change to ->') {
898 if (&validfolder($changefolder)) {
899 $folder = $changefolder;
900 &message_index($folder, "Welcome, $mailbox");
902 die("Bah! Not a valid change to folder '$changefolder'\n");
904 } elsif ($action eq 'play') {
905 &message_play("$mailbox $folder $msgid", $msgid);
906 } elsif ($action eq 'preferences') {
907 &message_prefs("refresh", $msgid);
908 } elsif ($action eq 'download') {
910 } elsif ($action eq 'play ') {
912 } elsif ($action eq 'audio') {
914 } elsif ($action eq 'delete') {
915 &message_delete_or_move(1, 1, @msgs);
916 } elsif ($action eq 'delete ') {
917 &message_delete_or_move(0, 1, @msgs);
918 } elsif ($action eq 'forward to ->') {
919 &message_forward(1, @msgs);
920 } elsif ($action eq 'forward to -> ') {
921 &message_forward(0, @msgs);
922 } elsif ($action eq 'save to ->') {
923 &message_delete_or_move(1, 0, @msgs);
924 } elsif ($action eq 'save to -> ') {
925 &message_delete_or_move(0, 0, @msgs);
926 } elsif ($action eq 'logout') {
927 &login_screen("Logged out!\n");
931 &login_screen("Login Incorrect!\n");
935 &login_screen("\ ");