Fix a few things I missed to ensure zt_chan_conf structure is not modified in mkintf
[asterisk-bristuff.git] / contrib / scripts / vmail.cgi
blob95bb9bb7717646f7173934c1e87cc049806f6e6a
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 ("", $category);
199 sub validmailbox($$$$)
201 local ($context, $mbox, $filename, $startcat) = @_;
202 local $category = $startcat;
203 local @fields;
204 local (*VMAIL);
205 if (!$context) {
206 $context = param('context');
208 if (!$context) {
209 $context = "default";
211 if (!$filename) {
212 $filename = "/etc/asterisk/voicemail.conf";
214 if (!$category) {
215 $category = "general";
217 open(VMAIL, "<$filename") || die("Bleh, no $filename");
218 while (<VMAIL>) {
219 chomp;
220 if (/include\s\"([^\"]+)\"$/) {
221 ($tmp, $category) = &validmailbox($mbox, $context, "/etc/asterisk/$1");
222 if ($tmp) {
223 return ($tmp, $category);
225 } elsif (/\[(.*)\]/) {
226 $category = $1;
227 } elsif ($category eq "general") {
228 if (/([^\s]+)\s*\=\s*(.*)/) {
229 if ($1 eq "dbname") {
230 $dbname = $2;
231 } elsif ($1 eq "dbpass") {
232 $dbpass = $2;
233 } elsif ($1 eq "dbhost") {
234 $dbhost = $2;
235 } elsif ($1 eq "dbuser") {
236 $dbuser = $2;
239 if ($dbname and $dbpass and $dbhost and $dbuser) {
241 # db variables are present. Use db for authentication.
242 my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
243 my $sth = $dbh->prepare(qq{select fullname,context from voicemail where mailbox='$mbox' and password='$pass' and context='$context'});
244 $sth->execute();
245 if (($fullname, $context) = $sth->fetchrow_array()) {
246 return ($fullname ? $fullname : "unknown", $category);
249 } elsif (($category ne "general") && ($category ne "zonemessages") && ($category eq $context)) {
250 if (/([^\s]+)\s*\=\>?\s*(.*)/) {
251 @fields = split(/\,\s*/, $2);
252 if (($mbox eq $1) && ($context eq $category)) {
253 return ($fields[2] ? $fields[2] : "unknown", $category);
258 return ("", $category);
261 sub mailbox_options()
263 local($context, $current, $filename, $category) = @_;
264 local (*VMAIL);
265 local $tmp2;
266 local $tmp;
267 if (!$filename) {
268 $filename = "/etc/asterisk/voicemail.conf";
270 if (!$category) {
271 $category = "general";
273 # print header;
274 # print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
275 open(VMAIL, "<$filename") || die("Bleh, no voicemail.conf");
276 while(<VMAIL>) {
277 chomp;
278 s/\;.*$//;
279 if (/include\s\"([^\"]+)\"$/) {
280 ($tmp2, $category) = &mailbox_options($context, $current, "/etc/asterisk/$1", $category);
281 # print "Got '$tmp2'...\n";
282 $tmp .= $tmp2;
283 } elsif (/\[(.*)\]/) {
284 $category = $1;
285 } elsif ($category eq "general") {
286 if (/([^\s]+)\s*\=\s*(.*)/) {
287 if ($1 eq "dbname") {
288 $dbname = $2;
289 } elsif ($1 eq "dbpass") {
290 $dbpass = $2;
291 } elsif ($1 eq "dbhost") {
292 $dbhost = $2;
293 } elsif ($1 eq "dbuser") {
294 $dbuser = $2;
297 if ($dbname and $dbpass and $dbhost and $dbuser) {
299 # db variables are present. Use db for authentication.
300 my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
301 my $sth = $dbh->prepare(qq{select mailbox,fullname,context from voicemail where context='$context' order by mailbox});
302 $sth->execute();
303 while (($mailbox, $fullname, $category) = $sth->fetchrow_array()) {
304 $text = $mailbox;
305 if ($fullname) {
306 $text .= " (".$fullname.")";
308 if ($mailbox eq $current) {
309 $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
310 } else {
311 $tmp .= "<OPTION>$text</OPTION>\n";
314 return ($tmp, $category);
316 } elsif (($category ne "general") && ($category ne "zonemessages")) {
317 if (/([^\s]+)\s*\=\>?\s*(.*)/) {
318 @fields = split(/\,\s*/, $2);
319 $text = "$1";
320 if ($fields[1]) {
321 $text .= " ($fields[1])";
323 if ($1 eq $current) {
324 $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
325 } else {
326 $tmp .= "<OPTION>$text</OPTION>\n";
332 close(VMAIL);
333 return ($tmp, $category);
336 sub mailbox_list()
338 local ($name, $context, $current) = @_;
339 local $tmp;
340 local $text;
341 local $tmp;
342 local $opts;
343 if (!$context) {
344 $context = "default";
346 $tmp = "<SELECT name=\"$name\">\n";
347 ($opts) = &mailbox_options($context, $current);
348 $tmp .= $opts;
349 $tmp .= "</SELECT>\n";
353 sub msgcount()
355 my ($context, $mailbox, $folder) = @_;
356 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
357 if (opendir(DIR, $path)) {
358 my @msgs = grep(/^msg....\.txt$/, readdir(DIR));
359 closedir(DIR);
360 return sprintf "%d", $#msgs + 1;
362 return "0";
365 sub msgcountstr()
367 my ($context, $mailbox, $folder) = @_;
368 my $count = &msgcount($context, $mailbox, $folder);
369 if ($count > 1) {
370 "$count messages";
371 } elsif ($count > 0) {
372 "$count message";
373 } else {
374 "no messages";
377 sub messages()
379 my ($context, $mailbox, $folder) = @_;
380 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
381 if (opendir(DIR, $path)) {
382 my @msgs = sort grep(/^msg....\.txt$/, readdir(DIR));
383 closedir(DIR);
384 return map { s/^msg(....)\.txt$/$1/; $_ } @msgs;
386 return ();
389 sub getcookie()
391 my ($var) = @_;
392 return cookie($var);
395 sub makecookie()
397 my ($format) = @_;
398 cookie(-name => "format", -value =>["$format"], -expires=>"+1y");
401 sub getfields()
403 my ($context, $mailbox, $folder, $msg) = @_;
404 my $fields;
405 if (open(MSG, "</var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msg}.txt")) {
406 while(<MSG>) {
407 s/\#.*$//g;
408 if (/^(\w+)\s*\=\s*(.*)$/) {
409 $fields->{$1} = $2;
412 close(MSG);
413 $fields->{'msgid'} = $msg;
414 } else { print "<BR>Unable to open '$msg' in '$mailbox', '$folder'\n<B>"; }
415 $fields;
418 sub message_prefs()
420 my ($nextaction, $msgid) = @_;
421 my $folder = param('folder');
422 my $mbox = param('mailbox');
423 my $context = param('context');
424 my $passwd = param('password');
425 my $format = param('format');
426 if (!$format) {
427 $format = &getcookie('format');
429 print header;
430 print <<_EOH;
432 <TITLE>Asterisk Web-Voicemail: Preferences</TITLE>
433 <BODY BGCOLOR="white">
434 $stdcontainerstart
435 <FORM METHOD="post">
436 <table width=100% align=center>
437 <tr><td align=right colspan=3><font size=+2>Web Voicemail Preferences</font></td></tr>
438 <tr><td align=left><font size=+1>Preferred&nbsp;Audio&nbsp;Format:</font></td><td colspan=2></td></tr>
439 _EOH
441 foreach $fmt (sort { $formats{$a}->{'pref'} <=> $formats{$b}->{'pref'} } keys %formats) {
442 my $clicked = "checked" if $fmt eq $format;
443 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";
446 print <<_EOH;
447 <tr><td align=right colspan=3><input type=submit value="save settings..."></td></tr>
448 </table>
449 <input type=hidden name="action" value="$nextaction">
450 <input type=hidden name="folder" value="$folder">
451 <input type=hidden name="mailbox" value="$mbox">
452 <input type=hidden name="context" value="$context">
453 <input type=hidden name="password" value="$passwd">
454 <input type=hidden name="msgid" value="$msgid">
455 $stdcontainerend
456 </BODY>\n
457 _EOH
461 sub message_play()
463 my ($message, $msgid) = @_;
464 my $folder = param('folder');
465 my ($mbox, $context) = split(/\@/, param('mailbox'));
466 my $passwd = param('password');
467 my $format = param('format');
469 my $fields;
470 if (!$context) {
471 $context = param('context');
473 if (!$context) {
474 $context = "default";
477 my $folders = &folder_list('newfolder', $context, $mbox, $folder);
478 my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
479 if (!$format) {
480 $format = &getcookie('format');
482 if (!$format) {
483 &message_prefs("play", $msgid);
484 } else {
485 print header(-cookie => &makecookie($format));
486 $fields = &getfields($context, $mbox, $folder, $msgid);
487 if (!$fields) {
488 print "<BR>Bah!\n";
489 return;
491 my $duration = $fields->{'duration'};
492 if ($duration) {
493 $duration = sprintf "%d:%02d", $duration/60, $duration % 60;
494 } else {
495 $duration = "<i>Unknown</i>";
497 print <<_EOH;
499 <TITLE>Asterisk Web-Voicemail: $folder Message $msgid</TITLE>
500 <BODY BGCOLOR="white">
501 $stdcontainerstart
502 <FORM METHOD="post">
503 <table width=100% align=center>
504 <tr><td align=right colspan=3><font size=+1>$folder Message $msgid</font></td></tr>
505 _EOH
507 print <<_EOH;
508 <tr><td align=center colspan=3>
509 <table>
510 <tr><td colspan=2 align=center><font size=+1>$folder <b>$msgid</b></font></td></tr>
511 <tr><td><b>Message:</b></td><td>$msgid</td></tr>\n
512 <tr><td><b>Mailbox:</b></td><td>$mbox\@$context</td></tr>\n
513 <tr><td><b>Folder:</b></td><td>$folder</td></tr>\n
514 <tr><td><b>From:</b></td><td>$fields->{callerid}</td></tr>\n
515 <tr><td><b>Duration:</b></td><td>$duration</td></tr>\n
516 <tr><td><b>Original Date:</b></td><td>$fields->{origdate}</td></tr>\n
517 <tr><td><b>Original Mailbox:</b></td><td>$fields->{origmailbox}</td></tr>\n
518 <tr><td><b>Caller Channel:</b></td><td>$fields->{callerchan}</td></tr>\n
519 <tr><td align=center colspan=2>
520 <input name="action" type=submit value="index">&nbsp;
521 <input name="action" type=submit value="delete ">&nbsp;
522 <input name="action" type=submit value="forward to -> ">&nbsp;
523 $mailboxes&nbsp;
524 <input name="action" type=submit value="save to ->">
525 $folders&nbsp;
526 <input name="action" type=submit value="play ">
527 <input name="action" type=submit value="download">
528 </td></tr>
529 <tr><td colspan=2 align=center>
530 <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>
531 </td></tr></table>
532 </td></tr>
533 </table>
534 <input type=hidden name="folder" value="$folder">
535 <input type=hidden name="mailbox" value="$mbox">
536 <input type=hidden name="context" value="$context">
537 <input type=hidden name="password" value="$passwd">
538 <input type=hidden name="msgid" value="$msgid">
539 $stdcontainerend
540 </BODY>\n
541 _EOH
545 sub message_audio()
547 my ($forcedownload) = @_;
548 my $folder = &untaint(param('folder'));
549 my $msgid = &untaint(param('msgid'));
550 my $mailbox = &untaint(param('mailbox'));
551 my $context = &untaint(param('context'));
552 my $format = param('format');
553 if (!$format) {
554 $format = &getcookie('format');
556 &untaint($format);
558 my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msgid}.$format";
560 $msgid =~ /^\d\d\d\d$/ || die("Msgid Liar ($msgid)!");
561 grep(/^${format}$/, keys %formats) || die("Format Liar ($format)!");
563 # Mailbox and folder are already verified
564 if (open(AUDIO, "<$path")) {
565 $size = -s $path;
566 $|=1;
567 if ($forcedownload) {
568 print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size, -attachment => "msg${msgid}.$format");
569 } else {
570 print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size);
573 while(($amt = sysread(AUDIO, $data, 4096)) > 0) {
574 syswrite(STDOUT, $data, $amt);
576 close(AUDIO);
577 } else {
578 die("Hrm, can't seem to open $path\n");
582 sub message_index()
584 my ($folder, $message) = @_;
585 my ($mbox, $context) = split(/\@/, param('mailbox'));
586 my $passwd = param('password');
587 my $message2;
588 my $msgcount;
589 my $hasmsg;
590 my ($newmessages, $oldmessages);
591 my $format = param('format');
592 if (!$format) {
593 $format = &getcookie('format');
595 if (!$context) {
596 $context = param('context');
598 if (!$context) {
599 $context = "default";
601 if ($folder) {
602 $msgcount = &msgcountstr($context, $mbox, $folder);
603 $message2 = "&nbsp;&nbsp;&nbsp;Folder '$folder' has " . &msgcountstr($context, $mbox, $folder);
604 } else {
605 $newmessages = &msgcount($context, $mbox, "INBOX");
606 $oldmessages = &msgcount($context, $mbox, "Old");
607 if (($newmessages > 0) || ($oldmessages < 1)) {
608 $folder = "INBOX";
609 } else {
610 $folder = "Old";
612 $message2 = "You have";
613 if ($newmessages > 0) {
614 $message2 .= " <b>$newmessages</b> NEW";
615 if ($oldmessages > 0) {
616 $message2 .= "and <b>$oldmessages</b> OLD";
617 if ($oldmessages != 1) {
618 $message2 .= " messages.";
619 } else {
620 $message2 .= "message.";
622 } else {
623 if ($newmessages != 1) {
624 $message2 .= " messages.";
625 } else {
626 $message2 .= " message.";
629 } else {
630 if ($oldmessages > 0) {
631 $message2 .= " <b>$oldmessages</b> OLD";
632 if ($oldmessages != 1) {
633 $message2 .= " messages.";
634 } else {
635 $message2 .= " message.";
637 } else {
638 $message2 .= " <b>no</b> messages.";
643 my $folders = &folder_list('newfolder', $context, $mbox, $folder);
644 my $cfolders = &folder_list('changefolder', $context, $mbox, $folder);
645 my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
646 print header(-cookie => &makecookie($format));
647 print <<_EOH;
649 <TITLE>Asterisk Web-Voicemail: $mbox\@$context $folder</TITLE>
650 <BODY BGCOLOR="white">
651 $stdcontainerstart
652 <FORM METHOD="post">
653 <table width=100% align=center>
654 <tr><td align=center colspan=2><font size=+2><I>$message</I></font></td></tr>
655 <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>
656 <tr><td align=left colspan=2><font size=+1>$message2</font></td></tr>
657 </table>
658 <table width=100% align=center cellpadding=0 cellspacing=0>
659 _EOH
661 print "<tr><td>&nbsp;Msg</td><td>&nbsp;From</td><td>&nbsp;Duration</td><td>&nbsp;Date</td><td>&nbsp;</td></tr>\n";
662 print "<tr><td><hr></td><td><hr></td><td><hr></td><td><hr></td><td></td></tr>\n";
663 foreach $msg (&messages($context, $mbox, $folder)) {
665 $fields = &getfields($context, $mbox, $folder, $msg);
666 $duration = $fields->{'duration'};
667 if ($duration) {
668 $duration = sprintf "%d:%02d", $duration / 60, $duration % 60;
669 } else {
670 $duration = "<i>Unknown</i>";
672 $hasmsg++;
673 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";
676 if (!$hasmsg) {
677 print "<tr><td colspan=4 align=center><P><b><i>No messages</i></b><P></td></tr>";
680 print <<_EOH;
681 </table>
682 <table width=100% align=center>
683 <tr><td align=right colspan=2>
684 <input type="submit" name="action" value="refresh">&nbsp;
685 _EOH
687 if ($hasmsg) {
688 print <<_EOH;
689 <input type="submit" name="action" value="delete">&nbsp;
690 <input type="submit" name="action" value="save to ->">
691 $folders&nbsp;
692 <input type="submit" name="action" value="forward to ->">
693 $mailboxes
694 _EOH
697 print <<_EOH;
698 </td></tr>
699 <tr><td align=right colspan=2>
700 <input type="submit" name="action" value="preferences">
701 <input type="submit" name="action" value="logout">
702 </td></tr>
703 </table>
704 <input type=hidden name="folder" value="$folder">
705 <input type=hidden name="mailbox" value="$mbox">
706 <input type=hidden name="context" value="$context">
707 <input type=hidden name="password" value="$passwd">
708 </FORM>
709 $stdcontainerend
710 </BODY>\n
711 _EOH
714 sub validfolder()
716 my ($folder) = @_;
717 return grep(/^$folder$/, @validfolders);
720 sub folder_list()
722 my ($name, $context, $mbox, $selected) = @_;
723 my $f;
724 my $count;
725 my $tmp = "<SELECT name=\"$name\">\n";
726 foreach $f (@validfolders) {
727 $count = &msgcount($context, $mbox, $f);
728 if ($f eq $selected) {
729 $tmp .= "<OPTION SELECTED>$f ($count)</OPTION>\n";
730 } else {
731 $tmp .= "<OPTION>$f ($count)</OPTION>\n";
734 $tmp .= "</SELECT>";
737 sub message_rename()
739 my ($context, $mbox, $oldfolder, $old, $newfolder, $new) = @_;
740 my ($oldfile, $newfile);
741 return if ($old eq $new) && ($oldfolder eq $newfolder);
743 if ($context =~ /^(\w+)$/) {
744 $context = $1;
745 } else {
746 die("Invalid Context<BR>\n");
749 if ($mbox =~ /^(\w+)$/) {
750 $mbox = $1;
751 } else {
752 die ("Invalid mailbox<BR>\n");
755 if ($oldfolder =~ /^(\w+)$/) {
756 $oldfolder = $1;
757 } else {
758 die("Invalid old folder<BR>\n");
761 if ($newfolder =~ /^(\w+)$/) {
762 $newfolder = $1;
763 } else {
764 die("Invalid new folder ($newfolder)<BR>\n");
767 if ($old =~ /^(\d\d\d\d)$/) {
768 $old = $1;
769 } else {
770 die("Invalid old Message<BR>\n");
773 if ($new =~ /^(\d\d\d\d)$/) {
774 $new = $1;
775 } else {
776 die("Invalid old Message<BR>\n");
779 my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder";
780 $path =~ /^(.*)$/;
781 $path = $1;
782 mkdir $path, 0770;
783 $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
784 opendir(DIR, $path) || die("Unable to open directory\n");
785 my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
786 closedir(DIR);
787 foreach $oldfile (@files) {
788 my $tmp = $oldfile;
789 if ($tmp =~ /^(msg${old}.\w+)$/) {
790 $tmp = $1;
791 $oldfile = $path . "/$tmp";
792 $tmp =~ s/msg${old}/msg${new}/;
793 $newfile = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder/$tmp";
794 # print "Renaming $oldfile to $newfile<BR>\n";
795 rename($oldfile, $newfile);
800 sub file_copy()
802 my ($orig, $new) = @_;
803 my $res;
804 my $data;
805 $orig =~ /^(.*)$/;
806 $orig = $1;
807 $new =~ /^(.*)$/;
808 $new = $1;
809 open(IN, "<$orig") || die("Unable to open '$orig'\n");
810 open(OUT, ">$new") || DIE("Unable to open '$new'\n");
811 while(($res = sysread(IN, $data, 4096)) > 0) {
812 syswrite(OUT, $data, $res);
814 close(OUT);
815 close(IN);
818 sub message_copy()
820 my ($context, $mbox, $newmbox, $oldfolder, $old, $new) = @_;
821 my ($oldfile, $newfile);
822 return if ($mbox eq $newmbox);
824 if ($mbox =~ /^(\w+)$/) {
825 $mbox = $1;
826 } else {
827 die ("Invalid mailbox<BR>\n");
830 if ($newmbox =~ /^(\w+)$/) {
831 $newmbox = $1;
832 } else {
833 die ("Invalid new mailbox<BR>\n");
836 if ($oldfolder =~ /^(\w+)$/) {
837 $oldfolder = $1;
838 } else {
839 die("Invalid old folder<BR>\n");
842 if ($old =~ /^(\d\d\d\d)$/) {
843 $old = $1;
844 } else {
845 die("Invalid old Message<BR>\n");
848 if ($new =~ /^(\d\d\d\d)$/) {
849 $new = $1;
850 } else {
851 die("Invalid old Message<BR>\n");
854 my $path = "/var/spool/asterisk/voicemail/$context/$newmbox";
855 $path =~ /^(.*)$/;
856 $path = $1;
857 mkdir $path, 0770;
858 $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
859 $path =~ /^(.*)$/;
860 $path = $1;
861 mkdir $path, 0770;
862 $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
863 opendir(DIR, $path) || die("Unable to open directory\n");
864 my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
865 closedir(DIR);
866 foreach $oldfile (@files) {
867 my $tmp = $oldfile;
868 if ($tmp =~ /^(msg${old}.\w+)$/) {
869 $tmp = $1;
870 $oldfile = $path . "/$tmp";
871 $tmp =~ s/msg${old}/msg${new}/;
872 $newfile = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX/$tmp";
873 # print "Copying $oldfile to $newfile<BR>\n";
874 &file_copy($oldfile, $newfile);
879 sub message_delete()
881 my ($context, $mbox, $folder, $msg) = @_;
882 if ($mbox =~ /^(\w+)$/) {
883 $mbox = $1;
884 } else {
885 die ("Invalid mailbox<BR>\n");
887 if ($context =~ /^(\w+)$/) {
888 $context = $1;
889 } else {
890 die ("Invalid context<BR>\n");
892 if ($folder =~ /^(\w+)$/) {
893 $folder = $1;
894 } else {
895 die("Invalid folder<BR>\n");
897 if ($msg =~ /^(\d\d\d\d)$/) {
898 $msg = $1;
899 } else {
900 die("Invalid Message<BR>\n");
902 my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
903 opendir(DIR, $path) || die("Unable to open directory\n");
904 my @files = grep /^msg${msg}\.\w+$/, readdir(DIR);
905 closedir(DIR);
906 foreach $oldfile (@files) {
907 if ($oldfile =~ /^(msg${msg}.\w+)$/) {
908 $oldfile = $path . "/$1";
909 # print "Deleting $oldfile<BR>\n";
910 unlink($oldfile);
915 sub message_forward()
917 my ($toindex, @msgs) = @_;
918 my $folder = param('folder');
919 my ($mbox, $context) = split(/\@/, param('mailbox'));
920 my $newmbox = param('forwardto');
921 my $msg;
922 my $msgcount;
923 if (!$context) {
924 $context = param('context');
926 if (!$context) {
927 $context = "default";
929 $newmbox =~ s/(\w+)(\s+.*)?$/$1/;
930 if (!&validmailbox($context, $newmbox)) {
931 die("Bah! Not a valid mailbox '$newmbox'\n");
932 return "";
935 my $txt;
936 $context = &untaint($context);
937 $newmbox = &untaint($newmbox);
938 my $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
939 if ($msgs[0]) {
940 if (&lock_path($path) == 0) {
941 $msgcount = &msgcount($context, $newmbox, "INBOX");
943 if ($newmbox ne $mbox) {
944 # print header;
945 foreach $msg (@msgs) {
946 # print "Forwarding $msg from $mbox to $newmbox<BR>\n";
947 &message_copy($context, $mbox, $newmbox, $folder, $msg, sprintf "%04d", $msgcount);
948 $msgcount++;
950 $txt = "Forwarded messages " . join(', ', @msgs) . "to $newmbox";
951 } else {
952 $txt = "Can't forward messages to yourself!\n";
954 &unlock_path($path);
955 } else {
956 $txt = "Cannot forward messages: Unable to lock path.\n";
958 } else {
959 $txt = "Please Select Message(s) for this action.\n";
961 if ($toindex) {
962 &message_index($folder, $txt);
963 } else {
964 &message_play($txt, $msgs[0]);
968 sub message_delete_or_move()
970 my ($toindex, $del, @msgs) = @_;
971 my $txt;
972 my $path;
973 my ($y, $x);
974 my $folder = param('folder');
975 my $newfolder = param('newfolder') unless $del;
976 $newfolder =~ s/^(\w+)\s+.*$/$1/;
977 my ($mbox, $context) = split(/\@/, param('mailbox'));
978 if (!$context) {
979 $context = param('context');
981 if (!$context) {
982 $context = "default";
984 my $passwd = param('password');
985 $context = &untaint($context);
986 $mbox = &untaint($mbox);
987 $folder = &untaint($folder);
988 $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
989 if ($msgs[0]) {
990 if (&lock_path($path) == 0) {
991 my $msgcount = &msgcount($context, $mbox, $folder);
992 my $omsgcount = &msgcount($context, $mbox, $newfolder) if $newfolder;
993 # print header;
994 if ($newfolder ne $folder) {
995 $y = 0;
996 for ($x=0;$x<$msgcount;$x++) {
997 my $msg = sprintf "%04d", $x;
998 my $newmsg = sprintf "%04d", $y;
999 if (grep(/^$msg$/, @msgs)) {
1000 if ($newfolder) {
1001 &message_rename($context, $mbox, $folder, $msg, $newfolder, sprintf "%04d", $omsgcount);
1002 $omsgcount++;
1003 } else {
1004 &message_delete($context, $mbox, $folder, $msg);
1006 } else {
1007 &message_rename($context, $mbox, $folder, $msg, $folder, $newmsg);
1008 $y++;
1011 if ($del) {
1012 $txt = "Deleted messages " . join (', ', @msgs);
1013 } else {
1014 $txt = "Moved messages " . join (', ', @msgs) . " to $newfolder";
1016 } else {
1017 $txt = "Can't move a message to the same folder they're in already";
1019 &unlock_path($path);
1020 } else {
1021 $txt = "Cannot move/delete messages: Unable to lock path.\n";
1023 } else {
1024 $txt = "Please Select Message(s) for this action.\n";
1026 # Not as many messages now
1027 $msgcount--;
1028 if ($toindex || ($msgs[0] >= $msgcount)) {
1029 &message_index($folder, $txt);
1030 } else {
1031 &message_play($txt, $msgs[0]);
1035 if (param()) {
1036 my $folder = param('folder');
1037 my $changefolder = param('changefolder');
1038 $changefolder =~ s/(\w+)\s+.*$/$1/;
1040 my $newfolder = param('newfolder');
1041 $newfolder =~ s/^(\w+)\s+.*$/$1/;
1042 if ($newfolder && !&validfolder($newfolder)) {
1043 print header;
1044 die("Bah! new folder '$newfolder' isn't a folder.");
1046 $action = param('action');
1047 $msgid = param('msgid');
1048 if (!$action) {
1049 my ($tmp) = grep /^play\d\d\d\d\.x$/, param;
1050 if ($tmp =~ /^play(\d\d\d\d)/) {
1051 $msgid = $1;
1052 $action = "play";
1053 } else {
1054 print header;
1055 print "No message?<BR>\n";
1056 return;
1059 @msgs = param('msgselect');
1060 @msgs = ($msgid) unless @msgs;
1062 ($mailbox) = &check_login();
1063 if (length($mailbox)) {
1064 if ($action eq 'login') {
1065 &message_index($folder, "Welcome, $mailbox");
1066 } elsif (($action eq 'refresh') || ($action eq 'index')) {
1067 &message_index($folder, "Welcome, $mailbox");
1068 } elsif ($action eq 'change to ->') {
1069 if (&validfolder($changefolder)) {
1070 $folder = $changefolder;
1071 &message_index($folder, "Welcome, $mailbox");
1072 } else {
1073 die("Bah! Not a valid change to folder '$changefolder'\n");
1075 } elsif ($action eq 'play') {
1076 &message_play("$mailbox $folder $msgid", $msgid);
1077 } elsif ($action eq 'preferences') {
1078 &message_prefs("refresh", $msgid);
1079 } elsif ($action eq 'download') {
1080 &message_audio(1);
1081 } elsif ($action eq 'play ') {
1082 &message_audio(0);
1083 } elsif ($action eq 'audio') {
1084 &message_audio(0);
1085 } elsif ($action eq 'delete') {
1086 &message_delete_or_move(1, 1, @msgs);
1087 } elsif ($action eq 'delete ') {
1088 &message_delete_or_move(0, 1, @msgs);
1089 } elsif ($action eq 'forward to ->') {
1090 &message_forward(1, @msgs);
1091 } elsif ($action eq 'forward to -> ') {
1092 &message_forward(0, @msgs);
1093 } elsif ($action eq 'save to ->') {
1094 &message_delete_or_move(1, 0, @msgs);
1095 } elsif ($action eq 'save to -> ') {
1096 &message_delete_or_move(0, 0, @msgs);
1097 } elsif ($action eq 'logout') {
1098 &login_screen("Logged out!\n");
1100 } else {
1101 sleep(1);
1102 &login_screen("Login Incorrect!\n");
1105 } else {
1106 &login_screen("\&nbsp;");