mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-23 14:44:28 +00:00
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:
@@ -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 */
|
||||||
|
Reference in New Issue
Block a user