fix voicemail path locking problems (bug #4245)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6091 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kevin P. Fleming
2005-07-12 01:04:54 +00:00
parent 58d1d59cab
commit 16c5ee5d56

View File

@@ -13,6 +13,9 @@
* 12-16 - 2005 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr) * 12-16 - 2005 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr)
* George Konstantoulakis <gkon@inaccessnetworks.com> * George Konstantoulakis <gkon@inaccessnetworks.com>
* 05-10 - 2005 : Support for Swedish and Norwegian added by Daniel Nylander, http://www.danielnylander.se/ * 05-10 - 2005 : Support for Swedish and Norwegian added by Daniel Nylander, http://www.danielnylander.se/
*
* 07-11 - 2005 : An issue with voicemail synchronization has been fixed by GDS Partners (www.gdspartners.com)
* Stojan Sljivic <stojan.sljivic@gdspartners.com>
*/ */
#include <stdlib.h> #include <stdlib.h>
@@ -88,6 +91,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define VM_DELETE (1 << 12) #define VM_DELETE (1 << 12)
#define VM_ALLOCED (1 << 13) #define VM_ALLOCED (1 << 13)
#define ERROR_LOCK_PATH -100
static int load_config(void); static int load_config(void);
/* Syntaxes supported, not really language codes. /* Syntaxes supported, not really language codes.
@@ -252,6 +257,8 @@ static char *descrip_vm =
"extension 'a' in the current context.\n" "extension 'a' in the current context.\n"
"If the requested mailbox does not exist, and there exists a priority\n" "If the requested mailbox does not exist, and there exists a priority\n"
"n + 101, then that priority will be taken next.\n" "n + 101, then that priority will be taken next.\n"
"If an error occur in the voicemail application resulting in that the message cannot be left,\n"
"and there exists a priority n + 101, then that priority will be taken next.\n"
"When multiple mailboxes are specified, the unavailable or busy message\n" "When multiple mailboxes are specified, the unavailable or busy message\n"
"will be taken from the first mailbox specified.\n" "will be taken from the first mailbox specified.\n"
"Returns -1 on error or mailbox not found, or if the user hangs up.\n" "Returns -1 on error or mailbox not found, or if the user hangs up.\n"
@@ -953,11 +960,17 @@ yuck:
return x; return x;
} }
/*
* A negative return value indicates an error.
*/
static int count_messages(char *dir) static int count_messages(char *dir)
{ {
return last_message_index(dir) + 1; int res = 0;
res = last_message_index(dir);
return res >= 0 ? res + 1 : res;
} }
static void delete_file(char *sdir, int smsg) static void delete_file(char *sdir, int smsg)
{ {
int res; int res;
@@ -1229,18 +1242,23 @@ static int count_messages(char *dir)
DIR *vmdir = NULL; DIR *vmdir = NULL;
struct dirent *vment = NULL; struct dirent *vment = NULL;
if ((vmdir = opendir(dir))) { if (!ast_lock_path(dir)) {
while ((vment = readdir(vmdir))) if ((vmdir = opendir(dir))) {
{ while ((vment = readdir(vmdir)))
if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,".txt",4))
{ {
vmcount++; if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,".txt",4))
{
vmcount++;
}
} }
closedir(vmdir);
} }
closedir(vmdir); ast_unlock_path(dir);
}
return vmcount; return vmcount;
} else {
return ERROR_LOCK_PATH;
}
} }
static void rename_file(char *sfn, char *dfn) static void rename_file(char *sfn, char *dfn)
@@ -1312,18 +1330,24 @@ static void copy_file(char *frompath, char *topath)
copy(frompath2, topath2); copy(frompath2, topath2);
} }
/*
* A negative return value indicates an error.
*/
static int last_message_index(char *dir) static int last_message_index(char *dir)
{ {
int x; int x;
char fn[256]; char fn[256];
ast_lock_path(dir); if (!ast_lock_path(dir)) {
for (x=0;x<MAXMSG;x++) { for (x=0;x<MAXMSG;x++) {
make_file(fn, sizeof(fn), dir, x); make_file(fn, sizeof(fn), dir, x);
if (ast_fileexists(fn, NULL, NULL) < 1) if (ast_fileexists(fn, NULL, NULL) < 1)
break; break;
}
ast_unlock_path(dir);
return x-1;
} else {
return ERROR_LOCK_PATH;
} }
ast_unlock_path(dir);
return x-1;
} }
static int vm_delete(char *file) static int vm_delete(char *file)
@@ -1934,7 +1958,7 @@ static int messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname); static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname);
static void copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt) static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt)
{ {
char fromdir[256], todir[256], frompath[256], topath[256]; char fromdir[256], todir[256], frompath[256], topath[256];
char *frombox = mbox(imbox); char *frombox = mbox(imbox);
@@ -1956,21 +1980,26 @@ static void copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int
make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox); make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
make_file(frompath, sizeof(frompath), fromdir, msgnum); make_file(frompath, sizeof(frompath), fromdir, msgnum);
ast_lock_path(topath); if (!ast_lock_path(topath)) {
recipmsgnum = 0; recipmsgnum = 0;
do { do {
make_file(topath, sizeof(topath), todir, recipmsgnum); make_file(topath, sizeof(topath), todir, recipmsgnum);
if (!EXISTS(todir, recipmsgnum, topath, chan->language)) if (!EXISTS(todir, recipmsgnum, topath, chan->language))
break; break;
recipmsgnum++; recipmsgnum++;
} while (recipmsgnum < MAXMSG); } while (recipmsgnum < MAXMSG);
if (recipmsgnum < MAXMSG) { if (recipmsgnum < MAXMSG) {
COPY(fromdir, msgnum, todir, recipmsgnum, frompath, topath); COPY(fromdir, msgnum, todir, recipmsgnum, frompath, topath);
} else {
ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
}
ast_unlock_path(topath);
notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
} else { } else {
ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context); return ERROR_LOCK_PATH;
} }
ast_unlock_path(topath);
notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name); return 0;
} }
static void run_externnotify(char *context, char *extension) static void run_externnotify(char *context, char *extension)
@@ -2156,30 +2185,30 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
ast_copy_string(fmt, vmfmts, sizeof(fmt)); ast_copy_string(fmt, vmfmts, sizeof(fmt));
if (!ast_strlen_zero(fmt)) { if (!ast_strlen_zero(fmt)) {
msgnum = 0; msgnum = 0;
if (res >= 0) { if (!ast_lock_path(dir)) {
/* Unless we're *really* silent, try to send the beep */ if (res >= 0) {
res = ast_streamfile(chan, "beep", chan->language); /* Unless we're *really* silent, try to send the beep */
if (!res) res = ast_streamfile(chan, "beep", chan->language);
res = ast_waitstream(chan, ""); if (!res)
} res = ast_waitstream(chan, "");
ast_lock_path(dir); }
do { do {
make_file(fn, sizeof(fn), dir, msgnum); make_file(fn, sizeof(fn), dir, msgnum);
if (!EXISTS(dir,msgnum,fn,chan->language)) if (!EXISTS(dir,msgnum,fn,chan->language))
break; break;
msgnum++; msgnum++;
} while (msgnum < MAXMSG); } while (msgnum < MAXMSG);
if (msgnum < MAXMSG) { if (msgnum < MAXMSG) {
/* assign a variable with the name of the voicemail file */ /* assign a variable with the name of the voicemail file */
pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn); pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
/* Store information */ /* Store information */
snprintf(txtfile, sizeof(txtfile), "%s.txt", fn); snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
txt = fopen(txtfile, "w+"); txt = fopen(txtfile, "w+");
if (txt) { if (txt) {
get_date(date, sizeof(date)); get_date(date, sizeof(date));
fprintf(txt, fprintf(txt,
";\n" ";\n"
"; Message Information file\n" "; Message Information file\n"
";\n" ";\n"
@@ -2194,64 +2223,68 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
"origdate=%s\n" "origdate=%s\n"
"origtime=%ld\n" "origtime=%ld\n"
"category=%s\n", "category=%s\n",
ext, ext,
chan->context, chan->context,
chan->macrocontext, chan->macrocontext,
chan->exten, chan->exten,
chan->priority, chan->priority,
chan->name, chan->name,
ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"), ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
date, (long)time(NULL), date, (long)time(NULL),
category ? category : ""); category ? category : "");
} else } else
ast_log(LOG_WARNING, "Error opening text file for output\n"); ast_log(LOG_WARNING, "Error opening text file for output\n");
res = play_record_review(chan, NULL, fn, vmmaxmessage, fmt, 1, vmu, &duration, dir); res = play_record_review(chan, NULL, fn, vmmaxmessage, fmt, 1, vmu, &duration, dir);
if (res == '0') { if (res == '0') {
if (txt) if (txt)
fclose(txt);
goto transfer;
}
if (res > 0)
res = 0;
if (txt) {
fprintf(txt, "duration=%d\n", duration);
fclose(txt); fclose(txt);
goto transfer; }
}
if (res > 0)
res = 0;
if (txt) {
fprintf(txt, "duration=%d\n", duration);
fclose(txt);
}
if (duration < vmminmessage) { if (duration < vmminmessage) {
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage); ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
DELETE(dir,msgnum,fn); DELETE(dir,msgnum,fn);
/* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */ /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
goto leave_vm_out; goto leave_vm_out;
}
/* Are there to be more recipients of this message? */
while (tmpptr) {
struct ast_vm_user recipu, *recip;
char *exten, *context;
exten = strsep(&tmpptr, "&");
context = strchr(exten, '@');
if (context) {
*context = '\0';
context++;
} }
if ((recip = find_user(&recipu, context, exten))) { /* Are there to be more recipients of this message? */
copy_message(chan, vmu, 0, msgnum, duration, recip, fmt); while (tmpptr) {
free_user(recip); struct ast_vm_user recipu, *recip;
char *exten, *context;
exten = strsep(&tmpptr, "&");
context = strchr(exten, '@');
if (context) {
*context = '\0';
context++;
}
if ((recip = find_user(&recipu, context, exten))) {
copy_message(chan, vmu, 0, msgnum, duration, recip, fmt);
free_user(recip);
}
} }
} if (ast_fileexists(fn, NULL, NULL)) {
if (ast_fileexists(fn, NULL, NULL)) { notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name); STORE(dir, msgnum);
STORE(dir, msgnum); DISPOSE(dir, msgnum);
DISPOSE(dir, msgnum); }
} else {
ast_unlock_path(dir);
res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
if (!res)
res = ast_waitstream(chan, "");
ast_log(LOG_WARNING, "No more messages possible\n");
} }
} else { } else {
ast_unlock_path(dir); free_user(vmu);
res = ast_streamfile(chan, "vm-mailboxfull", chan->language); return ERROR_LOCK_PATH;
if (!res)
res = ast_waitstream(chan, "");
ast_log(LOG_WARNING, "No more messages possible\n");
} }
} else } else
ast_log(LOG_WARNING, "No format for saving voicemail?\n"); ast_log(LOG_WARNING, "No format for saving voicemail?\n");
@@ -2268,7 +2301,7 @@ leave_vm_out:
} }
static void resequence_mailbox(char * dir) static int resequence_mailbox(char * dir)
{ {
/* we know max messages, so stop process when number is hit */ /* we know max messages, so stop process when number is hit */
@@ -2276,20 +2309,25 @@ static void resequence_mailbox(char * dir)
char sfn[256]; char sfn[256];
char dfn[256]; char dfn[256];
ast_lock_path(dir); if (!ast_lock_path(dir)) {
for (x=0,dest=0;x<MAXMSG;x++) { for (x=0,dest=0;x<MAXMSG;x++) {
make_file(sfn, sizeof(sfn), dir, x); make_file(sfn, sizeof(sfn), dir, x);
if (EXISTS(dir, x, sfn, NULL)) { if (EXISTS(dir, x, sfn, NULL)) {
if(x != dest) { if(x != dest) {
make_file(dfn, sizeof(dfn), dir, dest); make_file(dfn, sizeof(dfn), dir, dest);
RENAME(dir, x, dir, dest, sfn, dfn); RENAME(dir, x, dir, dest, sfn, dfn);
}
dest++;
} }
dest++;
} }
ast_unlock_path(dir);
} else {
return ERROR_LOCK_PATH;
} }
ast_unlock_path(dir);
return 0;
} }
@@ -2310,20 +2348,24 @@ static int save_to_folder(char *dir, int msg, char *context, char *username, int
make_file(sfn, sizeof(sfn), dir, msg); make_file(sfn, sizeof(sfn), dir, msg);
make_dir(ddir, sizeof(ddir), context, username, dbox); make_dir(ddir, sizeof(ddir), context, username, dbox);
mkdir(ddir, 0700); mkdir(ddir, 0700);
ast_lock_path(ddir); if (!ast_lock_path(ddir)) {
for (x=0;x<MAXMSG;x++) { for (x=0;x<MAXMSG;x++) {
make_file(dfn, sizeof(dfn), ddir, x); make_file(dfn, sizeof(dfn), ddir, x);
if (!EXISTS(ddir, x, dfn, NULL)) if (!EXISTS(ddir, x, dfn, NULL))
break; break;
} }
if (x >= MAXMSG) { if (x >= MAXMSG) {
ast_unlock_path(ddir);
return -1;
}
if (strcmp(sfn, dfn)) {
COPY(dir, msg, ddir, x, sfn, dfn);
}
ast_unlock_path(ddir); ast_unlock_path(ddir);
return -1; } else {
return ERROR_LOCK_PATH;
} }
if (strcmp(sfn, dfn)) {
COPY(dir, msg, ddir, x, sfn, dfn);
}
ast_unlock_path(ddir);
return 0; return 0;
} }
@@ -3096,7 +3138,10 @@ static int forward_message(struct ast_channel *chan, char *context, char *dir, i
ast_log(LOG_DEBUG, "%s", sys); ast_log(LOG_DEBUG, "%s", sys);
ast_safe_system(sys); ast_safe_system(sys);
todircount = count_messages(todir); if ( (res = count_messages(todir)) )
break;
else
todircount = res;
ast_copy_string(tmp, fmt, sizeof(tmp)); ast_copy_string(tmp, fmt, sizeof(tmp));
stringp = tmp; stringp = tmp;
while ((s = strsep(&stringp, "|"))) { while ((s = strsep(&stringp, "|"))) {
@@ -3419,11 +3464,18 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc
return res; return res;
} }
static void open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box) static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box)
{ {
int res = 0;
int count_msg, last_msg;
ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox)); ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
make_dir(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox); make_dir(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
vms->lastmsg = count_messages(vms->curdir) - 1; count_msg = count_messages(vms->curdir);
if (count_msg < 0)
return count_msg;
else
vms->lastmsg = count_msg - 1;
/* /*
The following test is needed in case sequencing gets messed up. The following test is needed in case sequencing gets messed up.
@@ -3432,48 +3484,65 @@ static void open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box)
detected. detected.
*/ */
if(vms->lastmsg != last_message_index(vms->curdir)) last_msg = last_message_index(vms->curdir);
if (last_msg < 0)
return last_msg;
else if(vms->lastmsg != last_msg)
{ {
ast_log(LOG_NOTICE, "Resequencing Mailbox: %s\n", vms->curdir); ast_log(LOG_NOTICE, "Resequencing Mailbox: %s\n", vms->curdir);
resequence_mailbox(vms->curdir); res = resequence_mailbox(vms->curdir);
if (res)
return res;
} }
snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox); snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
return 0;
} }
static void close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu) static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
{ {
int x; int x;
int res = 0;
if (vms->lastmsg > -1) { if (vms->lastmsg > -1) {
/* Get the deleted messages fixed */ /* Get the deleted messages fixed */
ast_lock_path(vms->curdir); if (!ast_lock_path(vms->curdir)) {
vms->curmsg = -1; vms->curmsg = -1;
for (x=0;x < MAXMSG;x++) { for (x=0;x < MAXMSG;x++) {
if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) { if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) {
/* Save this message. It's not in INBOX or hasn't been heard */ /* Save this message. It's not in INBOX or hasn't been heard */
make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
if (!EXISTS(vms->curdir, x, vms->fn, NULL))
break;
vms->curmsg++;
make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
if (strcmp(vms->fn, vms->fn2)) {
RENAME(vms->curdir, x, vms->curdir, vms->curmsg, vms->fn, vms->fn2);
}
} else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && !vms->deleted[x]) {
/* Move to old folder before deleting */
res = save_to_folder(vms->curdir, x, vmu->context, vms->username, 1);
if (res == ERROR_LOCK_PATH) {
/* If save failed do not delete the message */
vms->deleted[x] = 0;
vms->heard[x] = 0;
--x;
}
}
}
for (x = vms->curmsg + 1; x <= MAXMSG; x++) {
make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
if (!EXISTS(vms->curdir, x, vms->fn, NULL)) if (!EXISTS(vms->curdir, x, vms->fn, NULL))
break; break;
vms->curmsg++; DELETE(vms->curdir, x, vms->fn);
make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
if (strcmp(vms->fn, vms->fn2)) {
RENAME(vms->curdir, x, vms->curdir, vms->curmsg, vms->fn, vms->fn2);
}
} else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && !vms->deleted[x]) {
/* Move to old folder before deleting */
save_to_folder(vms->curdir, x, vmu->context, vms->username, 1);
} }
} ast_unlock_path(vms->curdir);
for (x = vms->curmsg + 1; x <= MAXMSG; x++) { } else {
make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); return ERROR_LOCK_PATH;
if (!EXISTS(vms->curdir, x, vms->fn, NULL)) }
break;
DELETE(vms->curdir, x, vms->fn);
}
ast_unlock_path(vms->curdir);
} }
memset(vms->deleted, 0, sizeof(vms->deleted)); memset(vms->deleted, 0, sizeof(vms->deleted));
memset(vms->heard, 0, sizeof(vms->heard)); memset(vms->heard, 0, sizeof(vms->heard));
return 0;
} }
/* In Greek even though we CAN use a syntax like "friends messages" /* In Greek even though we CAN use a syntax like "friends messages"
@@ -4704,16 +4773,22 @@ static int vm_execmain(struct ast_channel *chan, void *data)
snprintf(vms.curdir, sizeof(vms.curdir), "%s/%s/%s", VM_SPOOL_DIR, vmu->context, vms.username); snprintf(vms.curdir, sizeof(vms.curdir), "%s/%s/%s", VM_SPOOL_DIR, vmu->context, vms.username);
mkdir(vms.curdir, 0700); mkdir(vms.curdir, 0700);
/* Retrieve old and new message counts */ /* Retrieve old and new message counts */
open_mailbox(&vms, vmu, 1); res = open_mailbox(&vms, vmu, 1);
if (res == ERROR_LOCK_PATH)
goto out;
vms.oldmessages = vms.lastmsg + 1; vms.oldmessages = vms.lastmsg + 1;
/* Start in INBOX */ /* Start in INBOX */
open_mailbox(&vms, vmu, 0); res = open_mailbox(&vms, vmu, 0);
if (res == ERROR_LOCK_PATH)
goto out;
vms.newmessages = vms.lastmsg + 1; vms.newmessages = vms.lastmsg + 1;
/* Select proper mailbox FIRST!! */ /* Select proper mailbox FIRST!! */
if (!vms.newmessages && vms.oldmessages) { if (!vms.newmessages && vms.oldmessages) {
/* If we only have old messages start here */ /* If we only have old messages start here */
open_mailbox(&vms, vmu, 1); res = open_mailbox(&vms, vmu, 1);
if (res == ERROR_LOCK_PATH)
goto out;
} }
if (useadsi) if (useadsi)
@@ -4758,8 +4833,12 @@ static int vm_execmain(struct ast_channel *chan, void *data)
cmd = 0; cmd = 0;
} else if (cmd > 0) { } else if (cmd > 0) {
cmd = cmd - '0'; cmd = cmd - '0';
close_mailbox(&vms, vmu); res = close_mailbox(&vms, vmu);
open_mailbox(&vms, vmu, cmd); if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, cmd);
if (res == ERROR_LOCK_PATH)
goto out;
cmd = 0; cmd = 0;
} }
if (useadsi) if (useadsi)
@@ -4776,9 +4855,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
while ((cmd > -1) && (cmd != 't') && (cmd != '#')) { while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
switch(cmd) { switch(cmd) {
case '1': /* Reply */ case '1': /* Reply */
if (vms.lastmsg > -1) if (vms.lastmsg > -1) {
cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1); cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1);
else if (cmd == ERROR_LOCK_PATH) {
res = cmd;
goto out;
}
} else
cmd = ast_play_and_wait(chan, "vm-sorry"); cmd = ast_play_and_wait(chan, "vm-sorry");
cmd = 't'; cmd = 't';
break; break;
@@ -4789,16 +4872,23 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (cmd == 9) { if (cmd == 9) {
silentexit = 1; silentexit = 1;
goto out; goto out;
} } else if (cmd == ERROR_LOCK_PATH) {
res = cmd;
goto out;
}
} }
else else
cmd = ast_play_and_wait(chan, "vm-sorry"); cmd = ast_play_and_wait(chan, "vm-sorry");
cmd = 't'; cmd = 't';
break; break;
case '3': /* Envelope */ case '3': /* Envelope */
if (vms.lastmsg > -1) if (vms.lastmsg > -1) {
cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3); cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3);
else if (cmd == ERROR_LOCK_PATH) {
res = cmd;
goto out;
}
} else
cmd = ast_play_and_wait(chan, "vm-sorry"); cmd = ast_play_and_wait(chan, "vm-sorry");
cmd = 't'; cmd = 't';
break; break;
@@ -4816,9 +4906,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
break; break;
case '5': /* Leave VoiceMail */ case '5': /* Leave VoiceMail */
if (ast_test_flag(vmu, VM_SVMAIL)) if (ast_test_flag(vmu, VM_SVMAIL)) {
cmd = forward_message(chan, context, vms.curdir, vms.curmsg, vmu, vmfmts,1); cmd = forward_message(chan, context, vms.curdir, vms.curmsg, vmu, vmfmts,1);
else if (cmd == ERROR_LOCK_PATH) {
res = cmd;
goto out;
}
} else
cmd = ast_play_and_wait(chan,"vm-sorry"); cmd = ast_play_and_wait(chan,"vm-sorry");
cmd='t'; cmd='t';
break; break;
@@ -4899,9 +4993,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
break; break;
case '8': case '8':
if (vms.lastmsg > -1) if (vms.lastmsg > -1) {
cmd = forward_message(chan, context, vms.curdir, vms.curmsg, vmu, vmfmts,0); cmd = forward_message(chan, context, vms.curdir, vms.curmsg, vmu, vmfmts,0);
else if (cmd == ERROR_LOCK_PATH) {
res = cmd;
goto out;
}
} else
cmd = ast_play_and_wait(chan, "vm-nomore"); cmd = ast_play_and_wait(chan, "vm-nomore");
break; break;
case '9': case '9':
@@ -4915,6 +5013,10 @@ static int vm_execmain(struct ast_channel *chan, void *data)
} else if (cmd > 0) { } else if (cmd > 0) {
box = cmd = cmd - '0'; box = cmd = cmd - '0';
cmd = save_to_folder(vms.curdir, vms.curmsg, vmu->context, vms.username, cmd); cmd = save_to_folder(vms.curdir, vms.curmsg, vmu->context, vms.username, cmd);
if (cmd == ERROR_LOCK_PATH) {
res = cmd;
goto out;
}
vms.deleted[vms.curmsg]=1; vms.deleted[vms.curmsg]=1;
} }
make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg); make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
@@ -5054,6 +5156,17 @@ static int vm_exec(struct ast_channel *chan, void *data)
} }
res = leave_voicemail(chan, ext, silent, busy, unavail); res = leave_voicemail(chan, ext, silent, busy, unavail);
LOCAL_USER_REMOVE(u); LOCAL_USER_REMOVE(u);
if (res == ERROR_LOCK_PATH) {
ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
/*Send the call to n+101 priority, where n is the current priority*/
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num))
chan->priority+=100;
else
ast_log(LOG_WARNING, "Extension %s, priority %d doesn't exist.\n", chan->exten, chan->priority + 101);
res = 0;
}
return res; return res;
} }
@@ -5900,8 +6013,9 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
} else { } else {
if (find_user(NULL, vmu->context, num)) { if (find_user(NULL, vmu->context, num)) {
ast_verbose(VERBOSE_PREFIX_3 "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context); ast_verbose(VERBOSE_PREFIX_3 "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
leave_voicemail(chan, num, 1, 0, 1); res = leave_voicemail(chan, num, 1, 0, 1);
res = 't'; if (!res)
res = 't';
return res; return res;
} else { } else {
/* Sender has no mailbox, can't reply */ /* Sender has no mailbox, can't reply */