Skip to content
Snippets Groups Projects
vmail.cgi 29.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • Mark Spencer's avatar
    Mark Spencer committed
    #!/usr/bin/perl
    #
    # Web based Voicemail for Asterisk
    #
    # Copyright (C) 2002, Linux Support Services, Inc.
    #
    # Distributed under the terms of the GNU General Public License
    #
    # Written by Mark Spencer <markster@linux-support.net>
    #
    # (icky, I know....  if you know better perl please help!)
    #
    #
    
    # Synchronization added by GDS Partners (www.gdspartners.com)
    #			 Stojan Sljivic (stojan.sljivic@gdspartners.com)
    #
    
    Mark Spencer's avatar
    Mark Spencer committed
    use CGI qw/:standard/;
    
    Mark Spencer's avatar
    Mark Spencer committed
    use CGI::Carp qw(fatalsToBrowser);
    
    use Fcntl qw ( O_WRONLY O_CREAT O_EXCL );
    use Time::HiRes qw ( usleep );
    
    $context=""; # Define here your by default context (so you dont need to put voicemail@context in the login)
    
    Mark Spencer's avatar
    Mark Spencer committed
    @validfolders = ( "INBOX", "Old", "Work", "Family", "Friends", "Cust1", "Cust2", "Cust3", "Cust4", "Cust5" );
    
    %formats = (
    	"wav" => {
    		name => "Uncompressed WAV",
    		mime => "audio/x-wav",
    		pref => 1
    	},
    	"WAV" => {
    		name => "GSM Compressed WAV",
    		mime => "audio/x-wav",
    		pref => 2
    	},
    	"gsm" => {
    		name => "Raw GSM Audio",
    		mime => "audio/x-gsm",
    		pref => 3
    	}
    );
    
    $astpath = "/_asterisk";
    
    $stdcontainerstart = "<table align=center width=600><tr><td>\n";
    
    $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>";
    
    Mark Spencer's avatar
    Mark Spencer committed
    $stdcontainerend = "</td></tr><tr><td align=right>$footer</td></tr></table>\n";
    
    
    sub lock_path($) {
    
    
    	my($path) = @_;
    	my $rand;
    	my $rfile;
    	my $start;
    	my $res;
    	
    	$rand = rand 99999999;	
    	$rfile = "$path/.lock-$rand";
    	
    	sysopen(RFILE, $rfile, O_WRONLY | O_CREAT | O_EXCL, 0666) or return -1;
    	close(RFILE);
    	
    	$res = link($rfile, "$path/.lock");
    	$start = time;
    	if ($res == 0) {
    	while (($res == 0) && (time - $start <= 5)) {
    		$res = link($rfile, "$path/.lock");
    		usleep(1);
    	}
    	}
    	unlink($rfile);
    	
    	if ($res == 0) {
    		return -1;
    	} else {
    		return 0;
    	}
    }
    
    
    sub unlock_path($) {
    
    
    	my($path) = @_;
    	
    	unlink("$path/.lock");
    }
    
    
    sub untaint($) {
    
    
    	my($data) = @_;
    	
    	if ($data =~ /^([-\@\w.]+)$/) {
    		$data = $1;
    	} else {
    		die "Security violation.";
    	}
    	
    	return $data;
    }
    
    
    sub login_screen($) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	print header;
    	my ($message) = @_;
    	print <<_EOH;
    
    <TITLE>Asterisk Web-Voicemail</TITLE>
    <BODY BGCOLOR="white">
    $stdcontainerstart
    <FORM METHOD="post">
    
    Mark Spencer's avatar
    Mark Spencer committed
    <input type=hidden name="action" value="login">
    
    Mark Spencer's avatar
    Mark Spencer committed
    <table align=center>
    <tr><td valign=top align=center rowspan=6><img align=center src="$astpath/animlogo.gif"></td></tr>
    
    <tr><td align=center colspan=2><font size=+2>Comedian Mail Login</font></td></tr>
    
    Mark Spencer's avatar
    Mark Spencer committed
    <tr><td align=center colspan=2><font size=+1>$message</font></td></tr>
    <tr><td>Mailbox:</td><td><input type=text name="mailbox"></td></tr>
    <tr><td>Password:</td><td><input type=password name="password"></td></tr>
    
    Mark Spencer's avatar
    Mark Spencer committed
    <tr><td align=right colspan=2><input value="Login" type=submit></td></tr>
    
    <input type=hidden name="context" value="$context">
    
    Mark Spencer's avatar
    Mark Spencer committed
    </table>
    </FORM>
    $stdcontainerend
    </BODY>\n
    _EOH
    
    }
    
    
    sub check_login($$)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	local ($filename, $startcat) = @_;
    	local ($mbox, $context) = split(/\@/, param('mailbox'));
    	local $pass = param('password');
    	local $category = $startcat;
    	local @fields;
    	local $tmp;
    	local (*VMAIL);
    	if (!$category) {
    		$category = "general";
    	}
    
    	if (!$context) {
    		$context = param('context');
    	}
    	if (!$context) {
    		$context = "default";
    	}
    
    	if (!$filename) {
    		$filename = "/etc/asterisk/voicemail.conf";
    	}
    #	print header;
    #	print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
    	open(VMAIL, "<$filename") || die("Bleh, no $filename");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	while(<VMAIL>) {
    		chomp;
    
    		if (/include\s\"([^\"]+)\"$/) {
    			($tmp, $category) = &check_login("/etc/asterisk/$1", $category);
    			if (length($tmp)) {
    #				print "Got '$tmp'\n";
    				return ($tmp, $category);
    			}
    		} elsif (/\[(.*)\]/) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			$category = $1;
    
    		} elsif ($category eq "general") {
    			if (/([^\s]+)\s*\=\s*(.*)/) {
    				if ($1 eq "dbname") {
    					$dbname = $2;
    				} elsif ($1 eq "dbpass") {
    					$dbpass = $2;
    				} elsif ($1 eq "dbhost") {
    					$dbhost = $2;
    				} elsif ($1 eq "dbuser") {
    					$dbuser = $2;
    				}
    			}
    			if ($dbname and $dbpass and $dbhost and $dbuser) {
    
    				# db variables are present.  Use db for authentication.
    				my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
    				my $sth = $dbh->prepare(qq{select fullname,context from voicemail where mailbox='$mbox' and password='$pass' and context='$context'});
    				$sth->execute();
    				if (($fullname, $category) = $sth->fetchrow_array()) {
    					return ($fullname ? $fullname : "Extension $mbox in $context",$category);
    				}
    			}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} elsif (($category ne "general") && ($category ne "zonemessages")) { 
    
    Mark Spencer's avatar
    Mark Spencer committed
    			if (/([^\s]+)\s*\=\>?\s*(.*)/) {
    				@fields = split(/\,\s*/, $2);
    
    				if (($mbox eq $1) && (($pass eq $fields[0]) || ("-${pass}" eq $fields[0])) && ($context eq $category)) {
    
    					return ($fields[1] ? $fields[1] : "Extension $mbox in $context", $category);
    
    	return check_login_users();
    }
    
    sub check_login_users {
    	my ($mbox, $context) = split(/\@/, param('mailbox'));
    	my $pass = param('password');
    	my ($found, $fullname) = (0, "");
    	open VMAIL, "</etc/asterisk/users.conf";
    	while (<VMAIL>) {
    		chomp;
    		if (m/\[(.*)\]/) {
    			if ($1 eq $mbox) {
    				$found = 1;
    			} elsif ($found == 2) {
    				close VMAIL;
    				return (($fullname ? $fullname : "Extension $mbox in $context"), $context);
    			} else {
    				$found = 0;
    			}
    		} elsif ($found) {
    			my ($var, $value) = split /\s*=\s*/, $_, 2;
    			if ($var eq 'vmsecret' and $value eq $pass) {
    				$found = 2;
    			} elsif ($var eq 'fullname') {
    				$fullname = $value;
    				if ($found == 2) {
    					close VMAIL;
    					return ($fullname, $context);
    				}
    			}
    		}
    	}
    	close VMAIL;
    	return ("", "");
    
    sub validmailbox($$$$)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	local ($context, $mbox, $filename, $startcat) = @_;
    	local $category = $startcat;
    	local @fields;
    	local (*VMAIL);
    	if (!$context) {
    		$context = param('context');
    	}
    	if (!$context) {
    		$context = "default";
    	}
    	if (!$filename) {
    		$filename = "/etc/asterisk/voicemail.conf";
    	}
    	if (!$category) {
    		$category = "general";
    	}
    	open(VMAIL, "<$filename") || die("Bleh, no $filename");
    
    	while (<VMAIL>) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		chomp;
    
    		if (/include\s\"([^\"]+)\"$/) {
    			($tmp, $category) = &validmailbox($mbox, $context, "/etc/asterisk/$1");
    			if ($tmp) {
    				return ($tmp, $category);
    			}
    		} elsif (/\[(.*)\]/) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			$category = $1;
    
    		} elsif ($category eq "general") {
    			if (/([^\s]+)\s*\=\s*(.*)/) {
    				if ($1 eq "dbname") {
    					$dbname = $2;
    				} elsif ($1 eq "dbpass") {
    					$dbpass = $2;
    				} elsif ($1 eq "dbhost") {
    					$dbhost = $2;
    				} elsif ($1 eq "dbuser") {
    					$dbuser = $2;
    				}
    			}
    			if ($dbname and $dbpass and $dbhost and $dbuser) {
    
    				# db variables are present.  Use db for authentication.
    				my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
    				my $sth = $dbh->prepare(qq{select fullname,context from voicemail where mailbox='$mbox' and password='$pass' and context='$context'});
    				$sth->execute();
    				if (($fullname, $context) = $sth->fetchrow_array()) {
    					return ($fullname ? $fullname : "unknown", $category);
    				}
    			}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} elsif (($category ne "general") && ($category ne "zonemessages") && ($category eq $context)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			if (/([^\s]+)\s*\=\>?\s*(.*)/) {
    				@fields = split(/\,\s*/, $2);
    
    				if (($mbox eq $1) && ($context eq $category)) {
    					return ($fields[2] ? $fields[2] : "unknown", $category);
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	local($context, $current, $filename, $category) = @_;
    	local (*VMAIL);
    	local $tmp2;
    	local $tmp;
    	if (!$filename) {
    		$filename = "/etc/asterisk/voicemail.conf";
    	}
    	if (!$category) {
    		$category = "general";
    	}
    #	print header;
    #	print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
    	open(VMAIL, "<$filename") || die("Bleh, no voicemail.conf");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	while(<VMAIL>) {
    		chomp;
    		s/\;.*$//;
    
    		if (/include\s\"([^\"]+)\"$/) {
    			($tmp2, $category) = &mailbox_options($context, $current, "/etc/asterisk/$1", $category);
    #			print "Got '$tmp2'...\n";
    			$tmp .= $tmp2;
    		} elsif (/\[(.*)\]/) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			$category = $1;
    
    		} elsif ($category eq "general") {
    			if (/([^\s]+)\s*\=\s*(.*)/) {
    				if ($1 eq "dbname") {
    					$dbname = $2;
    				} elsif ($1 eq "dbpass") {
    					$dbpass = $2;
    				} elsif ($1 eq "dbhost") {
    					$dbhost = $2;
    				} elsif ($1 eq "dbuser") {
    					$dbuser = $2;
    				}
    			}
    			if ($dbname and $dbpass and $dbhost and $dbuser) {
    
    				# db variables are present.  Use db for authentication.
    				my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
    				my $sth = $dbh->prepare(qq{select mailbox,fullname,context from voicemail where context='$context' order by mailbox});
    				$sth->execute();
    				while (($mailbox, $fullname, $category) = $sth->fetchrow_array()) {
    					$text = $mailbox;
    					if ($fullname) {
    						$text .= " (".$fullname.")";
    					}
    					if ($mailbox eq $current) {
    						$tmp .= "<OPTION SELECTED>$text</OPTION>\n";
    					} else {
    						$tmp .= "<OPTION>$text</OPTION>\n";
    					}
    				}
    				return ($tmp, $category);
    			}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} elsif (($category ne "general") && ($category ne "zonemessages")) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			if (/([^\s]+)\s*\=\>?\s*(.*)/) {
    				@fields = split(/\,\s*/, $2);
    				$text = "$1";
    
    Mark Spencer's avatar
    Mark Spencer committed
    				if ($fields[1]) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    					$text .= " ($fields[1])";
    				}
    				if ($1 eq $current) {
    					$tmp .= "<OPTION SELECTED>$text</OPTION>\n";
    				} else {
    					$tmp .= "<OPTION>$text</OPTION>\n";
    				}
    				
    			}
    		}
    	}
    
    	close(VMAIL);
    	return ($tmp, $category);
    }
    
    sub mailbox_list()
    {
    	local ($name, $context, $current) = @_;
    	local $tmp;
    	local $text;
    	local $tmp;
    	local $opts;
    	if (!$context) {
    		$context = "default";
    	}
    	$tmp = "<SELECT name=\"$name\">\n";
    	($opts) = &mailbox_options($context, $current);
    	$tmp .= $opts;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	$tmp .= "</SELECT>\n";
    	
    }
    
    sub msgcount() 
    {
    
    	my ($context, $mailbox, $folder) = @_;
    	my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (opendir(DIR, $path)) {
    		my @msgs = grep(/^msg....\.txt$/, readdir(DIR));
    		closedir(DIR);
    		return sprintf "%d", $#msgs + 1;
    	}
    	return "0";
    }
    
    sub msgcountstr()
    {
    
    	my ($context, $mailbox, $folder) = @_;
    	my $count = &msgcount($context, $mailbox, $folder);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if ($count > 1) {
    		"$count messages";
    	} elsif ($count > 0) {
    		"$count message";
    	} else {
    		"no messages";
    	}
    }
    sub messages()
    {
    
    	my ($context, $mailbox, $folder) = @_;
    	my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (opendir(DIR, $path)) {
    		my @msgs = sort grep(/^msg....\.txt$/, readdir(DIR));
    		closedir(DIR);
    		return map { s/^msg(....)\.txt$/$1/; $_ } @msgs;
    	}
    	return ();
    }
    
    sub getcookie()
    {
    	my ($var) = @_;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return cookie($var);
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    sub makecookie()
    {
    	my ($format) = @_;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	cookie(-name => "format", -value =>["$format"], -expires=>"+1y");
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    sub getfields()
    {
    
    	my ($context, $mailbox, $folder, $msg) = @_;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $fields;
    
    	if (open(MSG, "</var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msg}.txt")) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		while(<MSG>) {
    			s/\#.*$//g;
    			if (/^(\w+)\s*\=\s*(.*)$/) {
    				$fields->{$1} = $2;
    			}
    		}
    		close(MSG);
    		$fields->{'msgid'} = $msg;
    	} else { print "<BR>Unable to open '$msg' in '$mailbox', '$folder'\n<B>"; }
    	$fields;
    }
    
    sub message_prefs()
    {
    	my ($nextaction, $msgid) = @_;
    	my $folder = param('folder');
    	my $mbox = param('mailbox');
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $context = param('context');
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $passwd = param('password');
    	my $format = param('format');
    	if (!$format) {
    		$format = &getcookie('format');
    	}
    	print header;
    	print <<_EOH;
    
    <TITLE>Asterisk Web-Voicemail: Preferences</TITLE>
    <BODY BGCOLOR="white">
    $stdcontainerstart
    <FORM METHOD="post">
    <table width=100% align=center>
    <tr><td align=right colspan=3><font size=+2>Web Voicemail Preferences</font></td></tr>
    <tr><td align=left><font size=+1>Preferred&nbsp;Audio&nbsp;Format:</font></td><td colspan=2></td></tr>
    _EOH
    
    foreach $fmt (sort { $formats{$a}->{'pref'} <=> $formats{$b}->{'pref'} } keys %formats) {
    	my $clicked = "checked" if $fmt eq $format;
    	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";
    }
    
    print <<_EOH;
    <tr><td align=right colspan=3><input type=submit value="save settings..."></td></tr>
    </table>
    <input type=hidden name="action" value="$nextaction">
    <input type=hidden name="folder" value="$folder">
    <input type=hidden name="mailbox" value="$mbox">
    
    <input type=hidden name="context" value="$context">
    
    Mark Spencer's avatar
    Mark Spencer committed
    <input type=hidden name="password" value="$passwd">
    <input type=hidden name="msgid" value="$msgid">
    $stdcontainerend
    </BODY>\n
    _EOH
    
    }
    
    sub message_play()
    {
    	my ($message, $msgid) = @_;
    	my $folder = param('folder');
    
    	my ($mbox, $context) = split(/\@/, param('mailbox'));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $passwd = param('password');
    	my $format = param('format');
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $fields;
    
    	if (!$context) {
    		$context = param('context');
    	}
    	if (!$context) {
    		$context = "default";
    	}
    	
    	my $folders = &folder_list('newfolder', $context, $mbox, $folder);
    	my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (!$format) {
    		$format = &getcookie('format');
    	}
    	if (!$format) {
    		&message_prefs("play", $msgid);
    	} else {
    		print header(-cookie => &makecookie($format));
    
    		$fields = &getfields($context, $mbox, $folder, $msgid);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (!$fields) {
    			print "<BR>Bah!\n";
    			return;
    		}
    		my $duration = $fields->{'duration'};
    		if ($duration) {
    			$duration = sprintf "%d:%02d", $duration/60, $duration % 60; 
    		} else {
    			$duration = "<i>Unknown</i>";
    		}
    		print <<_EOH;
    	
    <TITLE>Asterisk Web-Voicemail: $folder Message $msgid</TITLE>
    <BODY BGCOLOR="white">
    $stdcontainerstart
    <FORM METHOD="post">
    <table width=100% align=center>
    <tr><td align=right colspan=3><font size=+1>$folder Message $msgid</font></td></tr>
    _EOH
    
    		print <<_EOH;
    <tr><td align=center colspan=3>
    <table>
    	<tr><td colspan=2 align=center><font size=+1>$folder <b>$msgid</b></font></td></tr>
    	<tr><td><b>Message:</b></td><td>$msgid</td></tr>\n
    
    Mark Spencer's avatar
    Mark Spencer committed
    	<tr><td><b>Mailbox:</b></td><td>$mbox\@$context</td></tr>\n
    
    Mark Spencer's avatar
    Mark Spencer committed
    	<tr><td><b>Folder:</b></td><td>$folder</td></tr>\n
    	<tr><td><b>From:</b></td><td>$fields->{callerid}</td></tr>\n
    	<tr><td><b>Duration:</b></td><td>$duration</td></tr>\n
    	<tr><td><b>Original Date:</b></td><td>$fields->{origdate}</td></tr>\n
    	<tr><td><b>Original Mailbox:</b></td><td>$fields->{origmailbox}</td></tr>\n
    	<tr><td><b>Caller Channel:</b></td><td>$fields->{callerchan}</td></tr>\n
    	<tr><td align=center colspan=2>
    	<input name="action" type=submit value="index">&nbsp;
    	<input name="action" type=submit value="delete ">&nbsp;
    	<input name="action" type=submit value="forward to -> ">&nbsp;
    	$mailboxes&nbsp;
    	<input name="action" type=submit value="save to ->">
    	$folders&nbsp;
    	<input name="action" type=submit value="play ">
    	<input name="action" type=submit value="download">
    </td></tr>
    <tr><td colspan=2 align=center>
    
    Mark Spencer's avatar
    Mark Spencer committed
    <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>
    
    Mark Spencer's avatar
    Mark Spencer committed
    </td></tr></table>
    </td></tr>
    </table>
    <input type=hidden name="folder" value="$folder">
    <input type=hidden name="mailbox" value="$mbox">
    
    <input type=hidden name="context" value="$context">
    
    Mark Spencer's avatar
    Mark Spencer committed
    <input type=hidden name="password" value="$passwd">
    <input type=hidden name="msgid" value="$msgid">
    $stdcontainerend
    </BODY>\n
    _EOH
    	}
    }
    
    sub message_audio()
    {
    	my ($forcedownload) = @_;
    
    	my $folder = &untaint(param('folder'));
    	my $msgid = &untaint(param('msgid'));
    	my $mailbox = &untaint(param('mailbox'));
    	my $context = &untaint(param('context'));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $format = param('format');
    	if (!$format) {
    		$format = &getcookie('format');
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msgid}.$format";
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	$msgid =~ /^\d\d\d\d$/ || die("Msgid Liar ($msgid)!");
    	grep(/^${format}$/, keys %formats) || die("Format Liar ($format)!");
    
    	# Mailbox and folder are already verified
    	if (open(AUDIO, "<$path")) {
    
    		$size = -s $path;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		$|=1;
    		if ($forcedownload) {
    
    			print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size, -attachment => "msg${msgid}.$format");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} else {		
    
    			print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    		
    		while(($amt = sysread(AUDIO, $data, 4096)) > 0) {
    			syswrite(STDOUT, $data, $amt);
    		}
    		close(AUDIO);
    	} else {
    		die("Hrm, can't seem to open $path\n");
    	}
    }
    
    sub message_index() 
    {
    	my ($folder, $message) = @_;
    
    	my ($mbox, $context) = split(/\@/, param('mailbox'));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $passwd = param('password');
    	my $message2;
    	my $msgcount;	
    	my $hasmsg;
    
    	my ($newmessages, $oldmessages);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $format = param('format');
    	if (!$format) {
    		$format = &getcookie('format');
    	}
    
    	if (!$context) {
    		$context = param('context');
    	}
    	if (!$context) {
    		$context = "default";
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if ($folder) {
    
    		$msgcount = &msgcountstr($context, $mbox, $folder);
    		$message2 = "&nbsp;&nbsp;&nbsp;Folder '$folder' has " . &msgcountstr($context, $mbox, $folder);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	} else {
    
    		$newmessages = &msgcount($context, $mbox, "INBOX");
    		$oldmessages = &msgcount($context, $mbox, "Old");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (($newmessages > 0) || ($oldmessages < 1)) {
    			$folder = "INBOX";
    		} else {
    			$folder = "Old";
    		}
    		$message2 = "You have";
    		if ($newmessages > 0) {
    			$message2 .= " <b>$newmessages</b> NEW";
    			if ($oldmessages > 0) {
    				$message2 .= "and <b>$oldmessages</b> OLD";
    				if ($oldmessages != 1) {
    					$message2 .= " messages.";
    				} else {
    					$message2 .= "message.";
    				}
    			} else {
    				if ($newmessages != 1) {
    					$message2 .= " messages.";
    				} else {
    					$message2 .= " message.";
    				}
    			}
    		} else {
    			if ($oldmessages > 0) {
    				$message2 .= " <b>$oldmessages</b> OLD";
    				if ($oldmessages != 1) {
    					$message2 .= " messages.";
    				} else {
    					$message2 .= " message.";
    				}
    			} else {
    				$message2 .= " <b>no</b> messages.";
    			}
    		}
    	}
    	
    
    	my $folders = &folder_list('newfolder', $context, $mbox, $folder);
    	my $cfolders = &folder_list('changefolder', $context, $mbox, $folder);
    	my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	print header(-cookie => &makecookie($format));
    	print <<_EOH;
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    <TITLE>Asterisk Web-Voicemail: $mbox\@$context $folder</TITLE>
    
    Mark Spencer's avatar
    Mark Spencer committed
    <BODY BGCOLOR="white">
    $stdcontainerstart
    <FORM METHOD="post">
    <table width=100% align=center>
    <tr><td align=center colspan=2><font size=+2><I>$message</I></font></td></tr>
    <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>
    <tr><td align=left colspan=2><font size=+1>$message2</font></td></tr>
    </table>
    <table width=100% align=center cellpadding=0 cellspacing=0>
    _EOH
    
    print "<tr><td>&nbsp;Msg</td><td>&nbsp;From</td><td>&nbsp;Duration</td><td>&nbsp;Date</td><td>&nbsp;</td></tr>\n";
    print "<tr><td><hr></td><td><hr></td><td><hr></td><td><hr></td><td></td></tr>\n";
    
    foreach $msg (&messages($context, $mbox, $folder)) {
    
    	$fields = &getfields($context, $mbox, $folder, $msg);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	$duration = $fields->{'duration'};
    	if ($duration) {
    		$duration = sprintf "%d:%02d", $duration / 60, $duration % 60;
    	} else {
    		$duration = "<i>Unknown</i>";
    	}
    	$hasmsg++;
    	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";
    
    }
    if (!$hasmsg) {
    	print "<tr><td colspan=4 align=center><P><b><i>No messages</i></b><P></td></tr>";
    }
    
    print <<_EOH;
    </table>
    <table width=100% align=center>
    <tr><td align=right colspan=2>
    	<input type="submit" name="action" value="refresh">&nbsp;
    _EOH
    
    if ($hasmsg) {
    print <<_EOH;
    	<input type="submit" name="action" value="delete">&nbsp;
    	<input type="submit" name="action" value="save to ->">
    	$folders&nbsp;
    	<input type="submit" name="action" value="forward to ->">
    	$mailboxes
    _EOH
    }
    
    print <<_EOH;
    </td></tr>
    <tr><td align=right colspan=2>
    	<input type="submit" name="action" value="preferences">
    	<input type="submit" name="action" value="logout">
    </td></tr>
    </table>
    <input type=hidden name="folder" value="$folder">
    <input type=hidden name="mailbox" value="$mbox">
    
    <input type=hidden name="context" value="$context">
    
    Mark Spencer's avatar
    Mark Spencer committed
    <input type=hidden name="password" value="$passwd">
    </FORM>
    $stdcontainerend
    </BODY>\n
    _EOH
    }
    
    sub validfolder()
    {
    	my ($folder) = @_;
    	return grep(/^$folder$/, @validfolders);
    }
    
    sub folder_list()
    {
    
    	my ($name, $context, $mbox, $selected) = @_;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $f;
    	my $count;
    	my $tmp = "<SELECT name=\"$name\">\n";
    	foreach $f (@validfolders) {
    
    		$count =  &msgcount($context, $mbox, $f);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if ($f eq $selected) {
    			$tmp .= "<OPTION SELECTED>$f ($count)</OPTION>\n";
    		} else {
    			$tmp .= "<OPTION>$f ($count)</OPTION>\n";
    		}
    	}
    	$tmp .= "</SELECT>";
    }
    
    sub message_rename()
    {
    
    	my ($context, $mbox, $oldfolder, $old, $newfolder, $new) = @_;
    
    	my ($oldfile, $newfile);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return if ($old eq $new) && ($oldfolder eq $newfolder);
    
    	if ($context =~ /^(\w+)$/) {
    		$context = $1;
    	} else {
    		die("Invalid Context<BR>\n");
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	
    	if ($mbox =~ /^(\w+)$/) {
    		$mbox = $1;
    	} else {
    		die ("Invalid mailbox<BR>\n");
    	}
    	
    	if ($oldfolder =~ /^(\w+)$/) {
    		$oldfolder = $1;
    	} else {
    		die("Invalid old folder<BR>\n");
    	}
    	
    	if ($newfolder =~ /^(\w+)$/) {
    		$newfolder = $1;
    	} else {
    		die("Invalid new folder ($newfolder)<BR>\n");
    	}
    	
    	if ($old =~ /^(\d\d\d\d)$/) {
    		$old = $1;
    	} else {
    		die("Invalid old Message<BR>\n");
    	}
    	
    	if ($new =~ /^(\d\d\d\d)$/) {
    		$new = $1;
    	} else {
    		die("Invalid old Message<BR>\n");
    	}
    	
    
    	my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder";
    
    	$path =~ /^(.*)$/;
    	$path = $1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	mkdir $path, 0770;
    
    	$path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	opendir(DIR, $path) || die("Unable to open directory\n");
    	my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
    	closedir(DIR);
    	foreach $oldfile (@files) {
    		my $tmp = $oldfile;
    		if ($tmp =~ /^(msg${old}.\w+)$/) {
    			$tmp = $1;
    			$oldfile = $path . "/$tmp";
    			$tmp =~ s/msg${old}/msg${new}/;
    
    			$newfile = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder/$tmp";
    
    Mark Spencer's avatar
    Mark Spencer committed
    #			print "Renaming $oldfile to $newfile<BR>\n";
    			rename($oldfile, $newfile);
    		}
    	}
    }
    
    sub file_copy()
    {
    	my ($orig, $new) = @_;
    	my $res;
    	my $data;
    
    	$orig =~ /^(.*)$/;
    	$orig = $1;
    	$new =~ /^(.*)$/;
    	$new = $1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	open(IN, "<$orig") || die("Unable to open '$orig'\n");
    	open(OUT, ">$new") || DIE("Unable to open '$new'\n");
    	while(($res = sysread(IN, $data, 4096)) > 0) {
    		syswrite(OUT, $data, $res);
    	}
    	close(OUT);
    	close(IN);
    }
    
    sub message_copy()
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my ($context, $mbox, $newmbox, $oldfolder, $old, $new) = @_;
    
    	my ($oldfile, $newfile);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return if ($mbox eq $newmbox);
    	
    	if ($mbox =~ /^(\w+)$/) {
    		$mbox = $1;
    	} else {
    		die ("Invalid mailbox<BR>\n");
    	}
    
    	if ($newmbox =~ /^(\w+)$/) {
    		$newmbox = $1;
    	} else {
    		die ("Invalid new mailbox<BR>\n");
    	}
    	
    	if ($oldfolder =~ /^(\w+)$/) {
    		$oldfolder = $1;
    	} else {
    		die("Invalid old folder<BR>\n");
    	}
    	
    	if ($old =~ /^(\d\d\d\d)$/) {
    		$old = $1;
    	} else {
    		die("Invalid old Message<BR>\n");
    	}
    	
    	if ($new =~ /^(\d\d\d\d)$/) {
    		$new = $1;
    	} else {
    		die("Invalid old Message<BR>\n");
    	}
    	
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $path = "/var/spool/asterisk/voicemail/$context/$newmbox";
    
    	$path =~ /^(.*)$/;
    	$path = $1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	mkdir $path, 0770;
    
    	$path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
    
    	$path =~ /^(.*)$/;
    	$path = $1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	mkdir $path, 0770;
    
    	$path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	opendir(DIR, $path) || die("Unable to open directory\n");
    	my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
    	closedir(DIR);
    	foreach $oldfile (@files) {
    		my $tmp = $oldfile;
    		if ($tmp =~ /^(msg${old}.\w+)$/) {
    			$tmp = $1;
    			$oldfile = $path . "/$tmp";
    			$tmp =~ s/msg${old}/msg${new}/;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			$newfile = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX/$tmp";
    
    Mark Spencer's avatar
    Mark Spencer committed
    #			print "Copying $oldfile to $newfile<BR>\n";
    			&file_copy($oldfile, $newfile);
    		}
    	}
    }
    
    sub message_delete()
    {
    
    	my ($context, $mbox, $folder, $msg) = @_;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if ($mbox =~ /^(\w+)$/) {
    		$mbox = $1;
    	} else {
    		die ("Invalid mailbox<BR>\n");
    	}
    
    	if ($context =~ /^(\w+)$/) {
    		$context = $1;
    	} else {
    		die ("Invalid context<BR>\n");
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if ($folder =~ /^(\w+)$/) {
    		$folder = $1;
    	} else {
    		die("Invalid folder<BR>\n");
    	}
    	if ($msg =~ /^(\d\d\d\d)$/) {
    		$msg = $1;
    	} else {
    		die("Invalid Message<BR>\n");
    	}
    
    	my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	opendir(DIR, $path) || die("Unable to open directory\n");
    	my @files = grep /^msg${msg}\.\w+$/, readdir(DIR);
    	closedir(DIR);
    	foreach $oldfile (@files) {
    		if ($oldfile =~ /^(msg${msg}.\w+)$/) {
    			$oldfile = $path . "/$1";
    #			print "Deleting $oldfile<BR>\n";
    			unlink($oldfile);
    		}
    	}
    }
    
    sub message_forward()
    {
    	my ($toindex, @msgs) = @_;
    	my $folder = param('folder');
    
    	my ($mbox, $context) = split(/\@/, param('mailbox'));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $newmbox = param('forwardto');
    	my $msg;
    	my $msgcount;
    
    	if (!$context) {
    		$context = param('context');
    	}
    	if (!$context) {
    		$context = "default";
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	$newmbox =~ s/(\w+)(\s+.*)?$/$1/;
    
    	if (!&validmailbox($context, $newmbox)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		die("Bah! Not a valid mailbox '$newmbox'\n");
    		return "";
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	my $txt;
    
    	$context = &untaint($context);
    	$newmbox = &untaint($newmbox);
    	my $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
    
    	if ($msgs[0]) {
    		if (&lock_path($path) == 0) {
    			$msgcount = &msgcount($context, $newmbox, "INBOX");
    			
    			if ($newmbox ne $mbox) {
    	#			print header;
    				foreach $msg (@msgs) {
    	#				print "Forwarding $msg from $mbox to $newmbox<BR>\n";
    					&message_copy($context, $mbox, $newmbox, $folder, $msg, sprintf "%04d", $msgcount);
    					$msgcount++;
    				}
    				$txt = "Forwarded messages " . join(', ', @msgs) . "to $newmbox";
    			} else {
    				$txt = "Can't forward messages to yourself!\n";
    
    			&unlock_path($path); 
    
    			$txt = "Cannot forward messages: Unable to lock path.\n";
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    	} else {
    
    		$txt = "Please Select Message(s) for this action.\n";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if ($toindex) {
    		&message_index($folder, $txt);
    	} else {
    		&message_play($txt, $msgs[0]);
    	}
    }