Let's also include aclocal.m4
[asterisk-bristuff.git] / contrib / scripts / vmail.cgi
blobde51a4dc73841c6bee527625d75c7c913cc4f74c
1 #!/usr/bin/perl
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 # Synchronization added by GDS Partners (www.gdspartners.com)
15 # Stojan Sljivic (stojan.sljivic@gdspartners.com)
17 use CGI qw/:standard/;
18 use Carp::Heavy;
19 use CGI::Carp qw(fatalsToBrowser);
20 use DBI;
21 use Fcntl qw ( O_WRONLY O_CREAT O_EXCL );
22 use Time::HiRes qw ( usleep );
24 $context=""; # Define here your by default context (so you dont need to put voicemail@context in the login)
26 @validfolders = ( "INBOX", "Old", "Work", "Family", "Friends", "Cust1", "Cust2", "Cust3", "Cust4", "Cust5" );
28 %formats = (
29 "wav" => {
30 name => "Uncompressed WAV",
31 mime => "audio/x-wav",
32 pref => 1
34 "WAV" => {
35 name => "GSM Compressed WAV",
36 mime => "audio/x-wav",
37 pref => 2
39 "gsm" => {
40 name => "Raw GSM Audio",
41 mime => "audio/x-gsm",
42 pref => 3
46 $astpath = "/_asterisk";
48 $stdcontainerstart = "<table align=center width=600><tr><td>\n";
49 $footer = "<hr><font size=-1><a href=\"http://www.asterisk.org\">The Asterisk Open Source PBX</a> Copyright 2004-2008, <a href=\"http://www.digium.com\">Digium, Inc.</a></a>";
50 $stdcontainerend = "</td></tr><tr><td align=right>$footer</td></tr></table>\n";
52 sub lock_path($) {
54 my($path) = @_;
55 my $rand;
56 my $rfile;
57 my $start;
58 my $res;
60 $rand = rand 99999999;
61 $rfile = "$path/.lock-$rand";
63 sysopen(RFILE, $rfile, O_WRONLY | O_CREAT | O_EXCL, 0666) or return -1;
64 close(RFILE);
66 $res = link($rfile, "$path/.lock");
67 $start = time;
68 if ($res == 0) {
69 while (($res == 0) && (time - $start <= 5)) {
70 $res = link($rfile, "$path/.lock");
71 usleep(1);
74 unlink($rfile);
76 if ($res == 0) {
77 return -1;
78 } else {
79 return 0;
83 sub unlock_path($) {
85 my($path) = @_;
87 unlink("$path/.lock");
90 sub untaint($) {
92 my($data) = @_;
94 if ($data =~ /^([-\@\w.]+)$/) {
95 $data = $1;
96 } else {
97 die "Security violation.";
100 return $data;
103 sub login_screen($) {
104 print header;
105 my ($message) = @_;
106 print <<_EOH;
108 <TITLE>Asterisk Web-Voicemail</TITLE>
109 <BODY BGCOLOR="white">
110 $stdcontainerstart
111 <FORM METHOD="post">
112 <input type=hidden name="action" value="login">
113 <table align=center>
114 <tr><td valign=top align=center rowspan=6><img align=center src="$astpath/animlogo.gif"></td></tr>
115 <tr><td align=center colspan=2><font size=+2>Comedian Mail Login</font></td></tr>
116 <tr><td align=center colspan=2><font size=+1>$message</font></td></tr>
117 <tr><td>Mailbox:</td><td><input type=text name="mailbox"></td></tr>
118 <tr><td>Password:</td><td><input type=password name="password"></td></tr>
119 <tr><td align=right colspan=2><input value="Login" type=submit></td></tr>
120 <input type=hidden name="context" value="$context">
121 </table>
122 </FORM>
123 $stdcontainerend
124 </BODY>\n
125 _EOH
129 sub check_login($$)
131 local ($filename, $startcat) = @_;
132 local ($mbox, $context) = split(/\@/, param('mailbox'));
133 local $pass = param('password');
134 local $category = $startcat;
135 local @fields;
136 local $tmp;
137 local (*VMAIL);
138 if (!$category) {
139 $category = "general";
141 if (!$context) {
142 $context = param('context');
144 if (!$context) {
145 $context = "default";
147 if (!$filename) {
148 $filename = "/etc/asterisk/voicemail.conf";
150 # print header;
151 # print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
152 open(VMAIL, "<$filename") || die("Bleh, no $filename");
153 while(<VMAIL>) {
154 chomp;
155 if (/include\s\"([^\"]+)\"$/) {
156 ($tmp, $category) = &check_login("/etc/asterisk/$1", $category);
157 if (length($tmp)) {
158 # print "Got '$tmp'\n";
159 return ($tmp, $category);
161 } elsif (/\[(.*)\]/) {
162 $category = $1;
163 } elsif ($category eq "general") {
164 if (/([^\s]+)\s*\=\s*(.*)/) {
165 if ($1 eq "dbname") {
166 $dbname = $2;
167 } elsif ($1 eq "dbpass") {
168 $dbpass = $2;
169 } elsif ($1 eq "dbhost") {
170 $dbhost = $2;
171 } elsif ($1 eq "dbuser") {
172 $dbuser = $2;
175 if ($dbname and $dbpass and $dbhost and $dbuser) {
177 # db variables are present. Use db for authentication.
178 my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
179 my $sth = $dbh->prepare(qq{select fullname,context from voicemail where mailbox='$mbox' and password='$pass' and context='$context'});
180 $sth->execute();
181 if (($fullname, $category) = $sth->fetchrow_array()) {
182 return ($fullname ? $fullname : "Extension $mbox in $context",$category);
185 } elsif (($category ne "general") && ($category ne "zonemessages")) {
186 if (/([^\s]+)\s*\=\>?\s*(.*)/) {
187 @fields = split(/\,\s*/, $2);
188 # print "<p>Mailbox is $1\n";
189 if (($mbox eq $1) && (($pass eq $fields[0]) || ("-${pass}" eq $fields[0])) && ($context eq $category)) {
190 return ($fields[1] ? $fields[1] : "Extension $mbox in $context", $category);
195 close(VMAIL);
196 return check_login_users();
199 sub check_login_users {
200 my ($mbox, $context) = split(/\@/, param('mailbox'));
201 my $pass = param('password');
202 my ($found, $fullname) = (0, "");
203 open VMAIL, "</etc/asterisk/users.conf";
204 while (<VMAIL>) {
205 chomp;
206 if (m/\[(.*)\]/) {
207 if ($1 eq $mbox) {
208 $found = 1;
209 } elsif ($found == 2) {
210 close VMAIL;
211 return (($fullname ? $fullname : "Extension $mbox in $context"), $context);
212 } else {
213 $found = 0;
215 } elsif ($found) {
216 my ($var, $value) = split /\s*=\s*/, $_, 2;
217 if ($var eq 'vmsecret' and $value eq $pass) {
218 $found = 2;
219 } elsif ($var eq 'fullname') {
220 $fullname = $value;
221 if ($found == 2) {
222 close VMAIL;
223 return ($fullname, $context);
228 close VMAIL;
229 return ("", "");
232 sub validmailbox($$$$)
234 local ($context, $mbox, $filename, $startcat) = @_;
235 local $category = $startcat;
236 local @fields;
237 local (*VMAIL);
238 if (!$context) {
239 $context = param('context');
241 if (!$context) {
242 $context = "default";
244 if (!$filename) {
245 $filename = "/etc/asterisk/voicemail.conf";
247 if (!$category) {
248 $category = "general";
250 open(VMAIL, "<$filename") || die("Bleh, no $filename");
251 while (<VMAIL>) {
252 chomp;
253 if (/include\s\"([^\"]+)\"$/) {
254 ($tmp, $category) = &validmailbox($mbox, $context, "/etc/asterisk/$1");
255 if ($tmp) {
256 return ($tmp, $category);
258 } elsif (/\[(.*)\]/) {
259 $category = $1;
260 } elsif ($category eq "general") {
261 if (/([^\s]+)\s*\=\s*(.*)/) {
262 if ($1 eq "dbname") {
263 $dbname = $2;
264 } elsif ($1 eq "dbpass") {
265 $dbpass = $2;
266 } elsif ($1 eq "dbhost") {
267 $dbhost = $2;
268 } elsif ($1 eq "dbuser") {
269 $dbuser = $2;
272 if ($dbname and $dbpass and $dbhost and $dbuser) {
274 # db variables are present. Use db for authentication.
275 my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
276 my $sth = $dbh->prepare(qq{select fullname,context from voicemail where mailbox='$mbox' and password='$pass' and context='$context'});
277 $sth->execute();
278 if (($fullname, $context) = $sth->fetchrow_array()) {
279 return ($fullname ? $fullname : "unknown", $category);
282 } elsif (($category ne "general") && ($category ne "zonemessages") && ($category eq $context)) {
283 if (/([^\s]+)\s*\=\>?\s*(.*)/) {
284 @fields = split(/\,\s*/, $2);
285 if (($mbox eq $1) && ($context eq $category)) {
286 return ($fields[2] ? $fields[2] : "unknown", $category);
291 return ("", $category);
294 sub mailbox_options()
296 local($context, $current, $filename, $category) = @_;
297 local (*VMAIL);
298 local $tmp2;
299 local $tmp;
300 if (!$filename) {
301 $filename = "/etc/asterisk/voicemail.conf";
303 if (!$category) {
304 $category = "general";
306 # print header;
307 # print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
308 open(VMAIL, "<$filename") || die("Bleh, no voicemail.conf");
309 while(<VMAIL>) {
310 chomp;
311 s/\;.*$//;
312 if (/include\s\"([^\"]+)\"$/) {
313 ($tmp2, $category) = &mailbox_options($context, $current, "/etc/asterisk/$1", $category);
314 # print "Got '$tmp2'...\n";
315 $tmp .= $tmp2;
316 } elsif (/\[(.*)\]/) {
317 $category = $1;
318 } elsif ($category eq "general") {
319 if (/([^\s]+)\s*\=\s*(.*)/) {
320 if ($1 eq "dbname") {
321 $dbname = $2;
322 } elsif ($1 eq "dbpass") {
323 $dbpass = $2;
324 } elsif ($1 eq "dbhost") {
325 $dbhost = $2;
326 } elsif ($1 eq "dbuser") {
327 $dbuser = $2;
330 if ($dbname and $dbpass and $dbhost and $dbuser) {
332 # db variables are present. Use db for authentication.
333 my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
334 my $sth = $dbh->prepare(qq{select mailbox,fullname,context from voicemail where context='$context' order by mailbox});
335 $sth->execute();
336 while (($mailbox, $fullname, $category) = $sth->fetchrow_array()) {
337 $text = $mailbox;
338 if ($fullname) {
339 $text .= " (".$fullname.")";
341 if ($mailbox eq $current) {
342 $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
343 } else {
344 $tmp .= "<OPTION>$text</OPTION>\n";
347 return ($tmp, $category);
349 } elsif (($category ne "general") && ($category ne "zonemessages")) {
350 if (/([^\s]+)\s*\=\>?\s*(.*)/) {
351 @fields = split(/\,\s*/, $2);
352 $text = "$1";
353 if ($fields[1]) {
354 $text .= " ($fields[1])";
356 if ($1 eq $current) {
357 $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
358 } else {
359 $tmp .= "<OPTION>$text</OPTION>\n";
365 close(VMAIL);
366 return ($tmp, $category);
369 sub mailbox_list()
371 local ($name, $context, $current) = @_;
372 local $tmp;
373 local $text;
374 local $tmp;
375 local $opts;
376 if (!$context) {
377 $context = "default";
379 $tmp = "<SELECT name=\"$name\">\n";
380 ($opts) = &mailbox_options($context, $current);
381 $tmp .= $opts;
382 $tmp .= "</SELECT>\n";
386 sub msgcount()
388 my ($context, $mailbox, $folder) = @_;
389 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
390 if (opendir(DIR, $path)) {
391 my @msgs = grep(/^msg....\.txt$/, readdir(DIR));
392 closedir(DIR);
393 return sprintf "%d", $#msgs + 1;
395 return "0";
398 sub msgcountstr()
400 my ($context, $mailbox, $folder) = @_;
401 my $count = &msgcount($context, $mailbox, $folder);
402 if ($count > 1) {
403 "$count messages";
404 } elsif ($count > 0) {
405 "$count message";
406 } else {
407 "no messages";
410 sub messages()
412 my ($context, $mailbox, $folder) = @_;
413 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
414 if (opendir(DIR, $path)) {
415 my @msgs = sort grep(/^msg....\.txt$/, readdir(DIR));
416 closedir(DIR);
417 return map { s/^msg(....)\.txt$/$1/; $_ } @msgs;
419 return ();
422 sub getcookie()
424 my ($var) = @_;
425 return cookie($var);
428 sub makecookie()
430 my ($format) = @_;
431 cookie(-name => "format", -value =>["$format"], -expires=>"+1y");
434 sub getfields()
436 my ($context, $mailbox, $folder, $msg) = @_;
437 my $fields;
438 if (open(MSG, "</var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msg}.txt")) {
439 while(<MSG>) {
440 s/\#.*$//g;
441 if (/^(\w+)\s*\=\s*(.*)$/) {
442 $fields->{$1} = $2;
445 close(MSG);
446 $fields->{'msgid'} = $msg;
447 } else { print "<BR>Unable to open '$msg' in '$mailbox', '$folder'\n<B>"; }
448 $fields;
451 sub message_prefs()
453 my ($nextaction, $msgid) = @_;
454 my $folder = param('folder');
455 my $mbox = param('mailbox');
456 my $context = param('context');
457 my $passwd = param('password');
458 my $format = param('format');
459 if (!$format) {
460 $format = &getcookie('format');
462 print header;
463 print <<_EOH;
465 <TITLE>Asterisk Web-Voicemail: Preferences</TITLE>
466 <BODY BGCOLOR="white">
467 $stdcontainerstart
468 <FORM METHOD="post">
469 <table width=100% align=center>
470 <tr><td align=right colspan=3><font size=+2>Web Voicemail Preferences</font></td></tr>
471 <tr><td align=left><font size=+1>Preferred&nbsp;Audio&nbsp;Format:</font></td><td colspan=2></td></tr>
472 _EOH
474 foreach $fmt (sort { $formats{$a}->{'pref'} <=> $formats{$b}->{'pref'} } keys %formats) {
475 my $clicked = "checked" if $fmt eq $format;
476 print "<tr><td></td><td align=left><input type=radio name=\"format\" $clicked value=\"$fmt\"></td><td width=100%>&nbsp;$formats{$fmt}->{name}</td></tr>\n";
479 print <<_EOH;
480 <tr><td align=right colspan=3><input type=submit value="save settings..."></td></tr>
481 </table>
482 <input type=hidden name="action" value="$nextaction">
483 <input type=hidden name="folder" value="$folder">
484 <input type=hidden name="mailbox" value="$mbox">
485 <input type=hidden name="context" value="$context">
486 <input type=hidden name="password" value="$passwd">
487 <input type=hidden name="msgid" value="$msgid">
488 $stdcontainerend
489 </BODY>\n
490 _EOH
494 sub message_play()
496 my ($message, $msgid) = @_;
497 my $folder = param('folder');
498 my ($mbox, $context) = split(/\@/, param('mailbox'));
499 my $passwd = param('password');
500 my $format = param('format');
502 my $fields;
503 if (!$context) {
504 $context = param('context');
506 if (!$context) {
507 $context = "default";
510 my $folders = &folder_list('newfolder', $context, $mbox, $folder);
511 my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
512 if (!$format) {
513 $format = &getcookie('format');
515 if (!$format) {
516 &message_prefs("play", $msgid);
517 } else {
518 print header(-cookie => &makecookie($format));
519 $fields = &getfields($context, $mbox, $folder, $msgid);
520 if (!$fields) {
521 print "<BR>Bah!\n";
522 return;
524 my $duration = $fields->{'duration'};
525 if ($duration) {
526 $duration = sprintf "%d:%02d", $duration/60, $duration % 60;
527 } else {
528 $duration = "<i>Unknown</i>";
530 print <<_EOH;
532 <TITLE>Asterisk Web-Voicemail: $folder Message $msgid</TITLE>
533 <BODY BGCOLOR="white">
534 $stdcontainerstart
535 <FORM METHOD="post">
536 <table width=100% align=center>
537 <tr><td align=right colspan=3><font size=+1>$folder Message $msgid</font></td></tr>
538 _EOH
540 print <<_EOH;
541 <tr><td align=center colspan=3>
542 <table>
543 <tr><td colspan=2 align=center><font size=+1>$folder <b>$msgid</b></font></td></tr>
544 <tr><td><b>Message:</b></td><td>$msgid</td></tr>\n
545 <tr><td><b>Mailbox:</b></td><td>$mbox\@$context</td></tr>\n
546 <tr><td><b>Folder:</b></td><td>$folder</td></tr>\n
547 <tr><td><b>From:</b></td><td>$fields->{callerid}</td></tr>\n
548 <tr><td><b>Duration:</b></td><td>$duration</td></tr>\n
549 <tr><td><b>Original Date:</b></td><td>$fields->{origdate}</td></tr>\n
550 <tr><td><b>Original Mailbox:</b></td><td>$fields->{origmailbox}</td></tr>\n
551 <tr><td><b>Caller Channel:</b></td><td>$fields->{callerchan}</td></tr>\n
552 <tr><td align=center colspan=2>
553 <input name="action" type=submit value="index">&nbsp;
554 <input name="action" type=submit value="delete ">&nbsp;
555 <input name="action" type=submit value="forward to -> ">&nbsp;
556 $mailboxes&nbsp;
557 <input name="action" type=submit value="save to ->">
558 $folders&nbsp;
559 <input name="action" type=submit value="play ">
560 <input name="action" type=submit value="download">
561 </td></tr>
562 <tr><td colspan=2 align=center>
563 <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>
564 </td></tr></table>
565 </td></tr>
566 </table>
567 <input type=hidden name="folder" value="$folder">
568 <input type=hidden name="mailbox" value="$mbox">
569 <input type=hidden name="context" value="$context">
570 <input type=hidden name="password" value="$passwd">
571 <input type=hidden name="msgid" value="$msgid">
572 $stdcontainerend
573 </BODY>\n
574 _EOH
578 sub message_audio()
580 my ($forcedownload) = @_;
581 my $folder = &untaint(param('folder'));
582 my $msgid = &untaint(param('msgid'));
583 my $mailbox = &untaint(param('mailbox'));
584 my $context = &untaint(param('context'));
585 my $format = param('format');
586 if (!$format) {
587 $format = &getcookie('format');
589 &untaint($format);
591 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msgid}.$format";
593 $msgid =~ /^\d\d\d\d$/ || die("Msgid Liar ($msgid)!");
594 grep(/^${format}$/, keys %formats) || die("Format Liar ($format)!");
596 # Mailbox and folder are already verified
597 if (open(AUDIO, "<$path")) {
598 $size = -s $path;
599 $|=1;
600 if ($forcedownload) {
601 print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size, -attachment => "msg${msgid}.$format");
602 } else {
603 print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size);
606 while(($amt = sysread(AUDIO, $data, 4096)) > 0) {
607 syswrite(STDOUT, $data, $amt);
609 close(AUDIO);
610 } else {
611 die("Hrm, can't seem to open $path\n");
615 sub message_index()
617 my ($folder, $message) = @_;
618 my ($mbox, $context) = split(/\@/, param('mailbox'));
619 my $passwd = param('password');
620 my $message2;
621 my $msgcount;
622 my $hasmsg;
623 my ($newmessages, $oldmessages);
624 my $format = param('format');
625 if (!$format) {
626 $format = &getcookie('format');
628 if (!$context) {
629 $context = param('context');
631 if (!$context) {
632 $context = "default";
634 if ($folder) {
635 $msgcount = &msgcountstr($context, $mbox, $folder);
636 $message2 = "&nbsp;&nbsp;&nbsp;Folder '$folder' has " . &msgcountstr($context, $mbox, $folder);
637 } else {
638 $newmessages = &msgcount($context, $mbox, "INBOX");
639 $oldmessages = &msgcount($context, $mbox, "Old");
640 if (($newmessages > 0) || ($oldmessages < 1)) {
641 $folder = "INBOX";
642 } else {
643 $folder = "Old";
645 $message2 = "You have";
646 if ($newmessages > 0) {
647 $message2 .= " <b>$newmessages</b> NEW";
648 if ($oldmessages > 0) {
649 $message2 .= "and <b>$oldmessages</b> OLD";
650 if ($oldmessages != 1) {
651 $message2 .= " messages.";
652 } else {
653 $message2 .= "message.";
655 } else {
656 if ($newmessages != 1) {
657 $message2 .= " messages.";
658 } else {
659 $message2 .= " message.";
662 } else {
663 if ($oldmessages > 0) {
664 $message2 .= " <b>$oldmessages</b> OLD";
665 if ($oldmessages != 1) {
666 $message2 .= " messages.";
667 } else {
668 $message2 .= " message.";
670 } else {
671 $message2 .= " <b>no</b> messages.";
676 my $folders = &folder_list('newfolder', $context, $mbox, $folder);
677 my $cfolders = &folder_list('changefolder', $context, $mbox, $folder);
678 my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
679 print header(-cookie => &makecookie($format));
680 print <<_EOH;
682 <TITLE>Asterisk Web-Voicemail: $mbox\@$context $folder</TITLE>
683 <BODY BGCOLOR="white">
684 $stdcontainerstart
685 <FORM METHOD="post">
686 <table width=100% align=center>
687 <tr><td align=center colspan=2><font size=+2><I>$message</I></font></td></tr>
688 <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>
689 <tr><td align=left colspan=2><font size=+1>$message2</font></td></tr>
690 </table>
691 <table width=100% align=center cellpadding=0 cellspacing=0>
692 _EOH
694 print "<tr><td>&nbsp;Msg</td><td>&nbsp;From</td><td>&nbsp;Duration</td><td>&nbsp;Date</td><td>&nbsp;</td></tr>\n";
695 print "<tr><td><hr></td><td><hr></td><td><hr></td><td><hr></td><td></td></tr>\n";
696 foreach $msg (&messages($context, $mbox, $folder)) {
698 $fields = &getfields($context, $mbox, $folder, $msg);
699 $duration = $fields->{'duration'};
700 if ($duration) {
701 $duration = sprintf "%d:%02d", $duration / 60, $duration % 60;
702 } else {
703 $duration = "<i>Unknown</i>";
705 $hasmsg++;
706 print "<tr><td><input type=checkbox name=\"msgselect\" value=\"$msg\">&nbsp;<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";
709 if (!$hasmsg) {
710 print "<tr><td colspan=4 align=center><P><b><i>No messages</i></b><P></td></tr>";
713 print <<_EOH;
714 </table>
715 <table width=100% align=center>
716 <tr><td align=right colspan=2>
717 <input type="submit" name="action" value="refresh">&nbsp;
718 _EOH
720 if ($hasmsg) {
721 print <<_EOH;
722 <input type="submit" name="action" value="delete">&nbsp;
723 <input type="submit" name="action" value="save to ->">
724 $folders&nbsp;
725 <input type="submit" name="action" value="forward to ->">
726 $mailboxes
727 _EOH
730 print <<_EOH;
731 </td></tr>
732 <tr><td align=right colspan=2>
733 <input type="submit" name="action" value="preferences">
734 <input type="submit" name="action" value="logout">
735 </td></tr>
736 </table>
737 <input type=hidden name="folder" value="$folder">
738 <input type=hidden name="mailbox" value="$mbox">
739 <input type=hidden name="context" value="$context">
740 <input type=hidden name="password" value="$passwd">
741 </FORM>
742 $stdcontainerend
743 </BODY>\n
744 _EOH
747 sub validfolder()
749 my ($folder) = @_;
750 return grep(/^$folder$/, @validfolders);
753 sub folder_list()
755 my ($name, $context, $mbox, $selected) = @_;
756 my $f;
757 my $count;
758 my $tmp = "<SELECT name=\"$name\">\n";
759 foreach $f (@validfolders) {
760 $count = &msgcount($context, $mbox, $f);
761 if ($f eq $selected) {
762 $tmp .= "<OPTION SELECTED>$f ($count)</OPTION>\n";
763 } else {
764 $tmp .= "<OPTION>$f ($count)</OPTION>\n";
767 $tmp .= "</SELECT>";
770 sub message_rename()
772 my ($context, $mbox, $oldfolder, $old, $newfolder, $new) = @_;
773 my ($oldfile, $newfile);
774 return if ($old eq $new) && ($oldfolder eq $newfolder);
776 if ($context =~ /^(\w+)$/) {
777 $context = $1;
778 } else {
779 die("Invalid Context<BR>\n");
782 if ($mbox =~ /^(\w+)$/) {
783 $mbox = $1;
784 } else {
785 die ("Invalid mailbox<BR>\n");
788 if ($oldfolder =~ /^(\w+)$/) {
789 $oldfolder = $1;
790 } else {
791 die("Invalid old folder<BR>\n");
794 if ($newfolder =~ /^(\w+)$/) {
795 $newfolder = $1;
796 } else {
797 die("Invalid new folder ($newfolder)<BR>\n");
800 if ($old =~ /^(\d\d\d\d)$/) {
801 $old = $1;
802 } else {
803 die("Invalid old Message<BR>\n");
806 if ($new =~ /^(\d\d\d\d)$/) {
807 $new = $1;
808 } else {
809 die("Invalid old Message<BR>\n");
812 my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder";
813 $path =~ /^(.*)$/;
814 $path = $1;
815 mkdir $path, 0770;
816 $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
817 opendir(DIR, $path) || die("Unable to open directory\n");
818 my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
819 closedir(DIR);
820 foreach $oldfile (@files) {
821 my $tmp = $oldfile;
822 if ($tmp =~ /^(msg${old}.\w+)$/) {
823 $tmp = $1;
824 $oldfile = $path . "/$tmp";
825 $tmp =~ s/msg${old}/msg${new}/;
826 $newfile = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder/$tmp";
827 # print "Renaming $oldfile to $newfile<BR>\n";
828 rename($oldfile, $newfile);
833 sub file_copy()
835 my ($orig, $new) = @_;
836 my $res;
837 my $data;
838 $orig =~ /^(.*)$/;
839 $orig = $1;
840 $new =~ /^(.*)$/;
841 $new = $1;
842 open(IN, "<$orig") || die("Unable to open '$orig'\n");
843 open(OUT, ">$new") || DIE("Unable to open '$new'\n");
844 while(($res = sysread(IN, $data, 4096)) > 0) {
845 syswrite(OUT, $data, $res);
847 close(OUT);
848 close(IN);
851 sub message_copy()
853 my ($context, $mbox, $newmbox, $oldfolder, $old, $new) = @_;
854 my ($oldfile, $newfile);
855 return if ($mbox eq $newmbox);
857 if ($mbox =~ /^(\w+)$/) {
858 $mbox = $1;
859 } else {
860 die ("Invalid mailbox<BR>\n");
863 if ($newmbox =~ /^(\w+)$/) {
864 $newmbox = $1;
865 } else {
866 die ("Invalid new mailbox<BR>\n");
869 if ($oldfolder =~ /^(\w+)$/) {
870 $oldfolder = $1;
871 } else {
872 die("Invalid old folder<BR>\n");
875 if ($old =~ /^(\d\d\d\d)$/) {
876 $old = $1;
877 } else {
878 die("Invalid old Message<BR>\n");
881 if ($new =~ /^(\d\d\d\d)$/) {
882 $new = $1;
883 } else {
884 die("Invalid old Message<BR>\n");
887 my $path = "/var/spool/asterisk/voicemail/$context/$newmbox";
888 $path =~ /^(.*)$/;
889 $path = $1;
890 mkdir $path, 0770;
891 $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
892 $path =~ /^(.*)$/;
893 $path = $1;
894 mkdir $path, 0770;
895 $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
896 opendir(DIR, $path) || die("Unable to open directory\n");
897 my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
898 closedir(DIR);
899 foreach $oldfile (@files) {
900 my $tmp = $oldfile;
901 if ($tmp =~ /^(msg${old}.\w+)$/) {
902 $tmp = $1;
903 $oldfile = $path . "/$tmp";
904 $tmp =~ s/msg${old}/msg${new}/;
905 $newfile = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX/$tmp";
906 # print "Copying $oldfile to $newfile<BR>\n";
907 &file_copy($oldfile, $newfile);
912 sub message_delete()
914 my ($context, $mbox, $folder, $msg) = @_;
915 if ($mbox =~ /^(\w+)$/) {
916 $mbox = $1;
917 } else {
918 die ("Invalid mailbox<BR>\n");
920 if ($context =~ /^(\w+)$/) {
921 $context = $1;
922 } else {
923 die ("Invalid context<BR>\n");
925 if ($folder =~ /^(\w+)$/) {
926 $folder = $1;
927 } else {
928 die("Invalid folder<BR>\n");
930 if ($msg =~ /^(\d\d\d\d)$/) {
931 $msg = $1;
932 } else {
933 die("Invalid Message<BR>\n");
935 my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
936 opendir(DIR, $path) || die("Unable to open directory\n");
937 my @files = grep /^msg${msg}\.\w+$/, readdir(DIR);
938 closedir(DIR);
939 foreach $oldfile (@files) {
940 if ($oldfile =~ /^(msg${msg}.\w+)$/) {
941 $oldfile = $path . "/$1";
942 # print "Deleting $oldfile<BR>\n";
943 unlink($oldfile);
948 sub message_forward()
950 my ($toindex, @msgs) = @_;
951 my $folder = param('folder');
952 my ($mbox, $context) = split(/\@/, param('mailbox'));
953 my $newmbox = param('forwardto');
954 my $msg;
955 my $msgcount;
956 if (!$context) {
957 $context = param('context');
959 if (!$context) {
960 $context = "default";
962 $newmbox =~ s/(\w+)(\s+.*)?$/$1/;
963 if (!&validmailbox($context, $newmbox)) {
964 die("Bah! Not a valid mailbox '$newmbox'\n");
965 return "";
968 my $txt;
969 $context = &untaint($context);
970 $newmbox = &untaint($newmbox);
971 my $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
972 if ($msgs[0]) {
973 if (&lock_path($path) == 0) {
974 $msgcount = &msgcount($context, $newmbox, "INBOX");
976 if ($newmbox ne $mbox) {
977 # print header;
978 foreach $msg (@msgs) {
979 # print "Forwarding $msg from $mbox to $newmbox<BR>\n";
980 &message_copy($context, $mbox, $newmbox, $folder, $msg, sprintf "%04d", $msgcount);
981 $msgcount++;
983 $txt = "Forwarded messages " . join(', ', @msgs) . "to $newmbox";
984 } else {
985 $txt = "Can't forward messages to yourself!\n";
987 &unlock_path($path);
988 } else {
989 $txt = "Cannot forward messages: Unable to lock path.\n";
991 } else {
992 $txt = "Please Select Message(s) for this action.\n";
994 if ($toindex) {
995 &message_index($folder, $txt);
996 } else {
997 &message_play($txt, $msgs[0]);
1001 sub message_delete_or_move()
1003 my ($toindex, $del, @msgs) = @_;
1004 my $txt;
1005 my $path;
1006 my ($y, $x);
1007 my $folder = param('folder');
1008 my $newfolder = param('newfolder') unless $del;
1009 $newfolder =~ s/^(\w+)\s+.*$/$1/;
1010 my ($mbox, $context) = split(/\@/, param('mailbox'));
1011 if (!$context) {
1012 $context = param('context');
1014 if (!$context) {
1015 $context = "default";
1017 my $passwd = param('password');
1018 $context = &untaint($context);
1019 $mbox = &untaint($mbox);
1020 $folder = &untaint($folder);
1021 $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
1022 if ($msgs[0]) {
1023 if (&lock_path($path) == 0) {
1024 my $msgcount = &msgcount($context, $mbox, $folder);
1025 my $omsgcount = &msgcount($context, $mbox, $newfolder) if $newfolder;
1026 # print header;
1027 if ($newfolder ne $folder) {
1028 $y = 0;
1029 for ($x=0;$x<$msgcount;$x++) {
1030 my $msg = sprintf "%04d", $x;
1031 my $newmsg = sprintf "%04d", $y;
1032 if (grep(/^$msg$/, @msgs)) {
1033 if ($newfolder) {
1034 &message_rename($context, $mbox, $folder, $msg, $newfolder, sprintf "%04d", $omsgcount);
1035 $omsgcount++;
1036 } else {
1037 &message_delete($context, $mbox, $folder, $msg);
1039 } else {
1040 &message_rename($context, $mbox, $folder, $msg, $folder, $newmsg);
1041 $y++;
1044 if ($del) {
1045 $txt = "Deleted messages " . join (', ', @msgs);
1046 } else {
1047 $txt = "Moved messages " . join (', ', @msgs) . " to $newfolder";
1049 } else {
1050 $txt = "Can't move a message to the same folder they're in already";
1052 &unlock_path($path);
1053 } else {
1054 $txt = "Cannot move/delete messages: Unable to lock path.\n";
1056 } else {
1057 $txt = "Please Select Message(s) for this action.\n";
1059 # Not as many messages now
1060 $msgcount--;
1061 if ($toindex || ($msgs[0] >= $msgcount)) {
1062 &message_index($folder, $txt);
1063 } else {
1064 &message_play($txt, $msgs[0]);
1068 if (param()) {
1069 my $folder = param('folder');
1070 my $changefolder = param('changefolder');
1071 $changefolder =~ s/(\w+)\s+.*$/$1/;
1073 my $newfolder = param('newfolder');
1074 $newfolder =~ s/^(\w+)\s+.*$/$1/;
1075 if ($newfolder && !&validfolder($newfolder)) {
1076 print header;
1077 die("Bah! new folder '$newfolder' isn't a folder.");
1079 $action = param('action');
1080 $msgid = param('msgid');
1081 if (!$action) {
1082 my ($tmp) = grep /^play\d\d\d\d\.x$/, param;
1083 if ($tmp =~ /^play(\d\d\d\d)/) {
1084 $msgid = $1;
1085 $action = "play";
1086 } else {
1087 print header;
1088 print "No message?<BR>\n";
1089 return;
1092 @msgs = param('msgselect');
1093 @msgs = ($msgid) unless @msgs;
1095 ($mailbox) = &check_login();
1096 if (length($mailbox)) {
1097 if ($action eq 'login') {
1098 &message_index($folder, "Welcome, $mailbox");
1099 } elsif (($action eq 'refresh') || ($action eq 'index')) {
1100 &message_index($folder, "Welcome, $mailbox");
1101 } elsif ($action eq 'change to ->') {
1102 if (&validfolder($changefolder)) {
1103 $folder = $changefolder;
1104 &message_index($folder, "Welcome, $mailbox");
1105 } else {
1106 die("Bah! Not a valid change to folder '$changefolder'\n");
1108 } elsif ($action eq 'play') {
1109 &message_play("$mailbox $folder $msgid", $msgid);
1110 } elsif ($action eq 'preferences') {
1111 &message_prefs("refresh", $msgid);
1112 } elsif ($action eq 'download') {
1113 &message_audio(1);
1114 } elsif ($action eq 'play ') {
1115 &message_audio(0);
1116 } elsif ($action eq 'audio') {
1117 &message_audio(0);
1118 } elsif ($action eq 'delete') {
1119 &message_delete_or_move(1, 1, @msgs);
1120 } elsif ($action eq 'delete ') {
1121 &message_delete_or_move(0, 1, @msgs);
1122 } elsif ($action eq 'forward to ->') {
1123 &message_forward(1, @msgs);
1124 } elsif ($action eq 'forward to -> ') {
1125 &message_forward(0, @msgs);
1126 } elsif ($action eq 'save to ->') {
1127 &message_delete_or_move(1, 0, @msgs);
1128 } elsif ($action eq 'save to -> ') {
1129 &message_delete_or_move(0, 0, @msgs);
1130 } elsif ($action eq 'logout') {
1131 &login_screen("Logged out!\n");
1133 } else {
1134 sleep(1);
1135 &login_screen("Login Incorrect!\n");
1138 } else {
1139 &login_screen("\&nbsp;");