451 lines
11 KiB
PHP
451 lines
11 KiB
PHP
<?php
|
|
#
|
|
# WVMail - Web based Voicemail for Asterisk (http://asterisk.org)
|
|
# (C) 2002 Siggi Langauf
|
|
#
|
|
# Backend access functions
|
|
#
|
|
###########################################################################
|
|
|
|
/**
|
|
* Get MySQL config from voicemail.conf
|
|
*
|
|
* @return array('user'=>'username', 'pass'=>'password', 'host'=>'hostname', 'name'=>'database name')
|
|
*
|
|
*/
|
|
function get_mysql_config() {
|
|
|
|
global $voicemailconf;
|
|
|
|
$lines = @file($voicemailconf);
|
|
$section = NULL;
|
|
foreach ($lines as $line){
|
|
$line = rtrim($line);
|
|
if (preg_match("/^\s*\[([a-z]*)\]\s*$/i", $line, $m)){
|
|
$section = $m[1];
|
|
continue;
|
|
}
|
|
if ($section == "general"
|
|
&& preg_match("/^(db[a-z]*)\s*=\s*([\w\W]*)$/",$line, $m)) {
|
|
if ($m[1] == "dbuser" ) {
|
|
$db['user'] = $m[2];
|
|
}
|
|
if ($m[1] == "dbpass" ) {
|
|
$db['pass'] = $m[2];
|
|
}
|
|
if ($m[1] == "dbhost" ) {
|
|
$db['host'] = $m[2];
|
|
}
|
|
if ($m[1] == "dbname" ) {
|
|
$db['name'] = $m[2];
|
|
}
|
|
}
|
|
if (isset($db) && count($db) == 4) {
|
|
break;
|
|
}
|
|
}
|
|
return $db;
|
|
}
|
|
|
|
/**
|
|
* Authenticate user
|
|
*
|
|
* @param $user is the user ID
|
|
* @param $password is the password given by user
|
|
*
|
|
* @return false if the password is wrong, otherwise:
|
|
* This users config string (typically: Realname, email)
|
|
*/
|
|
function verify_user($user, $password){
|
|
|
|
global $context, $voicemailconf, $backendtype;
|
|
|
|
if($backendtype == "mysql") {
|
|
$db=get_mysql_config();
|
|
$link = mysql_connect($db["host"], $db["user"], $db["pass"]) or die("DB connection failed ".mysql_error());
|
|
mysql_select_db($db["name"]) or die("DB selection failed ".mysql_error());
|
|
|
|
$query = "SELECT context,mailbox,PASSWORD
|
|
FROM users
|
|
WHERE context='".$context."'
|
|
AND mailbox='".$user."'
|
|
AND PASSWORD='".$password."'";
|
|
$result = mysql_query($query) or die("Query failed : " . mysql_error());
|
|
if(mysql_num_rows($result) != '1') {
|
|
return false;
|
|
} else {
|
|
mysql_free_result($result);
|
|
mysql_close($link);
|
|
return true;
|
|
}
|
|
} else {
|
|
$lines = @file($voicemailconf);
|
|
$section = NULL;
|
|
foreach ($lines as $line){
|
|
$line = rtrim($line);
|
|
if (preg_match("/^\s*\[([a-z]*)\]\s*$/i", $line, $m)){
|
|
$section = $m[1];
|
|
}
|
|
if ($section == $context
|
|
&& preg_match("/^([0-9]*)\s*=>?\s*([0-9]*)\s*,(.*)$/",$line, $m)) {
|
|
if ($m[1] == $user && $m[2] == $password){
|
|
return $m[3];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* get list of mailboxes for given user
|
|
*/
|
|
function get_mailboxes($user){
|
|
|
|
global $boxbase, $dirMode;
|
|
|
|
$boxes = array();
|
|
|
|
$dir = "$boxbase/$user";
|
|
|
|
/* handle case where user exists but mailbox doesn't
|
|
app_voicemail creates them on 1st access, so should we */
|
|
if (!file_exists($dir)) {
|
|
umask("0000");
|
|
if(mkdir($dir, "2770")) {
|
|
if(mkdir("$dir/INBOX", "2770")) {
|
|
$boxes[] = "INBOX";
|
|
}
|
|
}
|
|
/* exit early, there won't be any other dir's */
|
|
return $boxes;
|
|
}
|
|
|
|
if ($handle = @opendir($dir)) {
|
|
while (false !== ($file = @readdir($handle))) {
|
|
if ($file{0}!= '.' && @is_dir("$boxbase/$user/$file")){
|
|
$boxes[] = $file;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $boxes;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* get message info for all messages in a given mailbox
|
|
*
|
|
* @param $user the user id
|
|
* @param $mailbox the mailbox
|
|
* @return an array of message info arrays
|
|
*/
|
|
function get_messages($user, $mailbox){
|
|
|
|
global $boxbase, $dirMode;
|
|
|
|
$messages = array();
|
|
|
|
$dir = "$boxbase/$user/$mailbox";
|
|
|
|
if ($handle = @opendir($dir)) {
|
|
/* This is the correct way to loop over the directory. */
|
|
while (false !== ($file = @readdir($handle))) {
|
|
if (preg_match("/^(msg(.*))\.txt$/",$file, $m)){
|
|
$info = array();
|
|
$info['txtfile'] = "$dir/$file";
|
|
$info['playname'] = "$dir/".$m[1];
|
|
$info['id'] = $m[2];
|
|
$info['folder'] = $mailbox;
|
|
if ($lines = @file($info['txtfile'])){
|
|
foreach ($lines as $line){
|
|
if (preg_match("/^([a-z]*)=(.*)$/", rtrim($line), $m)){
|
|
# this should give us the following info parameters:
|
|
# origmailbox, context, exten, priority, callerchan, callerid,
|
|
# origdate, origtime, duration
|
|
$info[$m[1]] = $m[2];
|
|
}
|
|
}
|
|
$messages[] = $info;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $messages;
|
|
}
|
|
|
|
/**
|
|
* delete a given message
|
|
*
|
|
* @param $user the user id
|
|
* @param $mailbox the mailbox
|
|
* @param $message id of the message you want to delete
|
|
*
|
|
* @return true if deleted, false on errors
|
|
*/
|
|
function delete_message($user, $mailbox, $message){
|
|
|
|
global $boxbase;
|
|
|
|
$dir = "$boxbase/$user/$mailbox";
|
|
$deleted = false;
|
|
if ($handle = @opendir($dir)) {
|
|
while (false !== ($file = @readdir($handle))) {
|
|
if (preg_match("/^msg$message/",$file, $m)){
|
|
if(@unlink("$dir/$file")){
|
|
$deleted = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if($mailbox == "INBOX") {
|
|
update_mwi($user);
|
|
}
|
|
return $deleted;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* play a file to given phone via the vmailbridge.agi script
|
|
*
|
|
* @param $extension is the extension to play to
|
|
* @param $file is the file to play (extension omitted, * playfile convention)
|
|
* @param $initiate if true (default), the voice connection is initiated
|
|
* (ie. the phone called) if it is not already open
|
|
* if set to false, the file is just enqueued while the call will have
|
|
* to be initiated manually.
|
|
* @return false if there is no voice connection, true otherwise
|
|
*/
|
|
function send_file($extension, $file, $initiate=true){
|
|
|
|
|
|
global $callspooldir, $vmbridgedir, $vmbridge_channel, $vmbridge_extension;
|
|
|
|
$status_file = $vmbridgedir."/$extension.current";
|
|
$request_file = $vmbridgedir."/$extension";
|
|
|
|
$talking = true; //assume connected phone
|
|
if (! @file_exists($status_file)){ //no phone connected, yet
|
|
if (!$initiate){
|
|
$talking = false;
|
|
}
|
|
else {//initiate call
|
|
list($usec, $sec) = explode(' ', microtime());
|
|
$t = (float)$sec + (float)$usec;
|
|
$callspool_file = "$callspooldir/$extension.$t.call";
|
|
$callrequest = 'Channel: ';
|
|
$callrequest.= str_replace('@extension@', $extension, $vmbridge_channel);
|
|
$callrequest.= "\nCallerid: $extension\n"
|
|
. "Context: default\n"
|
|
. "Extension: $vmbridge_extension\n"
|
|
. "Priority: 1\n";
|
|
umask("0000");
|
|
if (!$handle = @fopen($callspool_file, 'w')){
|
|
print("unable to open file $callspool_file");
|
|
exit;
|
|
}
|
|
fwrite($handle, $callrequest);
|
|
fclose($handle);
|
|
}
|
|
}
|
|
// write request to the request file read by vmbridge.agi
|
|
if (!$handle = @fopen($request_file, 'w')){
|
|
print("unable to open file $request_file");
|
|
exit(1);
|
|
}
|
|
fwrite($handle, $file);
|
|
fclose($handle);
|
|
|
|
return $talking;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* close the vmailbridge (if any) to this extension
|
|
*
|
|
* @param $extension is the extension to close
|
|
*/
|
|
function close_bridge($extension){
|
|
|
|
global $vmbridgedir;
|
|
|
|
$status_file = $vmbridgedir."/$extension.current";
|
|
$request_file = $vmbridgedir."/$extension";
|
|
|
|
if (@file_exists($status_file)){ //bridge is open
|
|
// write request to the request file read by vmbridge.agi
|
|
if (!$handle = @fopen($request_file, 'w')){
|
|
print("unable to open $request_file");
|
|
exit(1);
|
|
}
|
|
fwrite($handle, "vm-goodbye");
|
|
fclose($handle);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* update MWI
|
|
*
|
|
* @param $user
|
|
*/
|
|
function update_mwi($user) {
|
|
|
|
global $context, $updateMWI;
|
|
|
|
if(!$updateMWI) {
|
|
return true;
|
|
}
|
|
|
|
$call_context = "voicemail"; //not actually used
|
|
|
|
@system("../bin/ccm-mwi ".$call_context." ".$user."@".$context." ".count(get_messages($user, "INBOX")), $result);
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* save to folder
|
|
*
|
|
* @param $user
|
|
* @param $message
|
|
* @param $srcFolder
|
|
* @param $dstFolder
|
|
*/
|
|
function save_to_folder($user, $message, $srcFolder, $dstFolder) {
|
|
|
|
global $MAXMSG, $boxbase, $dirMode;
|
|
|
|
$srcPath = $boxbase.'/'.$user.'/'.$srcFolder;
|
|
$dstPath = $boxbase.'/'.$user.'/'.$dstFolder;
|
|
|
|
umask("0000");
|
|
if(!@file_exists($dstPath)){
|
|
if(!@mkdir($dstPath, $dirMode)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for($i=0; $i <= $MAXMSG; $i++) {
|
|
$dstMessage = sprintf("msg%04d", $i);
|
|
if(!@file_exists($dstPath.'/'.$dstMessage.'.txt') ) {
|
|
break;
|
|
}
|
|
}
|
|
if($i >= $MAXMSG) {
|
|
return false; // folder is full
|
|
}
|
|
|
|
// copy files
|
|
foreach(array("wav","WAV","gsm","txt") as $extension) {
|
|
$src = $srcPath.'/msg'.$message.".".$extension;
|
|
$dst = $dstPath.'/'.$dstMessage.".".$extension;
|
|
if(@file_exists($src))if(!@copy($src, $dst)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* move to folder
|
|
*
|
|
* @param $user
|
|
* @param $message
|
|
* @param $srcFolder
|
|
* @param $dstFolder
|
|
*/
|
|
|
|
function move_to_folder($user, $message, $srcFolder, $dstFolder)
|
|
{
|
|
global $MAXMSG, $boxbase, $dirMode;
|
|
|
|
$srcPath = $boxbase.'/'.$user.'/'.$srcFolder;
|
|
$dstPath = $boxbase.'/'.$user.'/'.$dstFolder;
|
|
|
|
umask("0000");
|
|
if(!@file_exists($dstPath))
|
|
{
|
|
if(!@mkdir($dstPath, $dirMode)) return false;
|
|
}
|
|
|
|
for($i=0; $i <= $MAXMSG; $i++)
|
|
{
|
|
$dstMessage = sprintf("msg%04d", $i);
|
|
if(!@file_exists($dstPath.'/'.$dstMessage.'.txt') ) break;
|
|
|
|
// folder is full
|
|
if($i >= $MAXMSG) return false;
|
|
}
|
|
|
|
// move files
|
|
foreach(array("wav","WAV","gsm","txt") as $extension)
|
|
{
|
|
$src = $srcPath.'/msg'.$message.".".$extension;
|
|
$dst = $dstPath.'/'.$dstMessage.".".$extension;
|
|
if(@file_exists($src))
|
|
{
|
|
if(!@copy($src, $dst)) return false;
|
|
else @unlink($src);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* mark as read
|
|
*
|
|
* @param $user
|
|
* @param $message
|
|
* @param $srcFolder
|
|
* @param $dstFolder
|
|
*/
|
|
|
|
function mark_as_read($user, $message, $srcFolder, $dstFolder)
|
|
{
|
|
global $MAXMSG, $boxbase, $dirMode;
|
|
|
|
$srcPath = $boxbase.'/'.$user.'/'.$srcFolder;
|
|
$dstPath = $boxbase.'/'.$user.'/'.$dstFolder;
|
|
|
|
umask("0000");
|
|
if(!@file_exists($dstPath))
|
|
{
|
|
if(!@mkdir($dstPath, $dirMode)) return ("");
|
|
}
|
|
|
|
for($i=0; $i <= $MAXMSG; $i++)
|
|
{
|
|
$dstMessage = sprintf("msg%04d", $i);
|
|
$msg_id = sprintf("%04d", $i);
|
|
if(!@file_exists($dstPath.'/'.$dstMessage.'.txt') ) break;
|
|
|
|
// folder is full
|
|
if($i >= $MAXMSG) return ("");
|
|
}
|
|
|
|
// move files
|
|
foreach(array("wav","WAV","gsm","txt") as $extension)
|
|
{
|
|
$src = $srcPath.'/msg'.$message.".".$extension;
|
|
$dst = $dstPath.'/'.$dstMessage.".".$extension;
|
|
|
|
if(@file_exists($src))
|
|
{
|
|
if(!@copy($src, $dst)) return ("");
|
|
else @unlink($src);
|
|
}
|
|
}
|
|
|
|
return $msg_id;
|
|
}
|
|
|
|
|
|
|
|
?>
|