aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/app_voicemail.c112
1 files changed, 91 insertions, 21 deletions
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 097ccfcc1..8082b8c90 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -627,6 +627,7 @@ struct vm_state {
char intro[PATH_MAX];
int *deleted;
int *heard;
+ int dh_arraysize; /* used for deleted / heard allocation */
int curmsg;
int lastmsg;
int newmessages;
@@ -851,7 +852,7 @@ static int inprocess_hash_fn(const void *obj, const int flags)
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
{
struct inprocess *i = obj, *j = arg;
- if (!strcmp(i->mailbox, j->mailbox)) {
+ if (strcmp(i->mailbox, j->mailbox)) {
return 0;
}
return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
@@ -870,6 +871,9 @@ static int inprocess_count(const char *context, const char *mailbox, int delta)
ao2_ref(i, -1);
return ret;
}
+ if (delta < 0) {
+ ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
+ }
if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
ao2_unlock(inprocess_container);
return 0;
@@ -1546,6 +1550,33 @@ static void free_user(struct ast_vm_user *vmu)
}
}
+static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg) {
+
+ int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
+ if (!vms->dh_arraysize) {
+ /* initial allocation */
+ if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
+ return -1;
+ }
+ if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
+ return -1;
+ }
+ vms->dh_arraysize = arraysize;
+ } else if (vms->dh_arraysize < arraysize) {
+ if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
+ return -1;
+ }
+ if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
+ return -1;
+ }
+ memset(vms->deleted, 0, arraysize * sizeof(int));
+ memset(vms->heard, 0, arraysize * sizeof(int));
+ vms->dh_arraysize = arraysize;
+ }
+
+ return 0;
+}
+
/* All IMAP-specific functions should go in this block. This
* keeps them from being spread out all over the code */
#ifdef IMAP_STORAGE
@@ -1947,9 +1978,11 @@ static int imap_check_limits(struct ast_channel *chan, struct vm_state *vms, str
}
/* Check if we have exceeded maxmsg */
- if (msgnum >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, 0)) {
- ast_log(AST_LOG_WARNING, "Unable to leave message since we will exceed the maximum number of messages allowed (%u > %u)\n", msgnum, vmu->maxmsg);
+ ast_debug(3, "Checking message number quota: mailbox has %d messages, maximum is set to %d, current messages %d\n", msgnum, vmu->maxmsg, inprocess_count(vmu->mailbox, vmu->context, 0));
+ if (msgnum >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
+ ast_log(LOG_WARNING, "Unable to leave message since we will exceed the maximum number of messages allowed (%u >= %u)\n", msgnum, vmu->maxmsg);
ast_play_and_wait(chan, "vm-mailboxfull");
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
return -1;
}
@@ -2095,7 +2128,7 @@ static int imap_store_file(const char *dir, const char *mailboxuser, const char
if (tempcopy)
*(vmu->email) = '\0';
-
+ inprocess_count(vmu->mailbox, vmu->context, -1);
return 0;
}
@@ -2422,6 +2455,16 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
mail_search_full (vms->mailstream, NULL, pgm, NIL);
vms->lastmsg = vms->vmArrayIndex - 1;
mail_free_searchpgm(&pgm);
+ /* Since IMAP storage actually stores both old and new messages in the same IMAP folder,
+ * ensure to allocate enough space to account for all of them. Warn if old messages
+ * have not been checked first as that is required.
+ */
+ if (box == 0 && !vms->dh_arraysize) {
+ ast_log(LOG_WARNING, "The code expects the old messages to be checked first, fix the code.\n");
+ }
+ if (vm_allocate_dh(vms, vmu, box == 0 ? vms->vmArrayIndex + vms->oldmessages : vms->lastmsg)) {
+ return -1;
+ }
ast_mutex_unlock(&vms->lock);
return 0;
@@ -4533,11 +4576,18 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *c
FILE *p=NULL;
char tmp[80] = "/tmp/astmail-XXXXXX";
char tmp2[256];
+ char *stringp;
if (vmu && ast_strlen_zero(vmu->email)) {
ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
return(0);
}
+
+ /* Mail only the first format */
+ format = ast_strdupa(format);
+ stringp = format;
+ strsep(&stringp, "|");
+
if (!strcmp(format, "wav49"))
format = "WAV";
ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
@@ -5286,7 +5336,14 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
DISPOSE(tempfile, -1);
/* It's easier just to try to make it than to check for its existence */
+#ifndef IMAP_STORAGE
create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
+#else
+ snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
+ if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
+ ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
+ }
+#endif
/* Check current or macro-calling context for special extensions */
if (ast_test_flag(vmu, VM_OPERATOR)) {
@@ -5449,7 +5506,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
/* here is a big difference! We add one to it later */
msgnum = newmsgs + oldmsgs;
ast_debug(3, "Messagecount set to %d\n",msgnum);
- snprintf(fn, sizeof(fn), "%s/imap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
+ snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
/* set variable for compatibility */
pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
@@ -6527,7 +6584,11 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu,
}
ast_channel_unlock(chan);
+#ifndef IMAP_STORAGE
make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
+#else
+ snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
+#endif
make_file(fn, sizeof(fn), todir, msgnum);
snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
@@ -7326,6 +7387,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
/* Faster to make the directory than to check if it exists. */
create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
+ /* traverses directory using readdir (or select query for ODBC) */
count_msg = count_messages(vmu, vms->curdir);
if (count_msg < 0) {
return count_msg;
@@ -7333,6 +7395,10 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
vms->lastmsg = count_msg - 1;
}
+ if (vm_allocate_dh(vms, vmu, count_msg)) {
+ return -1;
+ }
+
/*
The following test is needed in case sequencing gets messed up.
There appears to be more than one way to mess up sequence, so
@@ -7345,11 +7411,14 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
return -1;
}
+ /* for local storage, checks directory for messages up to maxmsg limit */
last_msg = last_message_index(vmu, vms->curdir);
ast_unlock_path(vms->curdir);
if (last_msg < 0) {
return last_msg;
+ } else if (vms->lastmsg != last_msg) {
+ ast_log(LOG_NOTICE, "Mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg);
}
return 0;
@@ -7375,7 +7444,8 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
return ERROR_LOCK_PATH;
}
- for (x = 0; x < vmu->maxmsg; x++) {
+ /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
+ for (x = 0; x < vms->lastmsg + 1; x++) {
if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
/* Save this message. It's not in INBOX or hasn't been heard */
make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
@@ -7429,7 +7499,7 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
if (vms->deleted) {
/* Since we now expunge after each delete, deleting in reverse order
* ensures that no reordering occurs between each step. */
- for (x = vmu->maxmsg - 1; x >= 0; x--) {
+ for (x = vms->dh_arraysize - 1; x >= 0; x--) {
if (vms->deleted[x]) {
ast_debug(3, "IMAP delete of %d\n", x);
DELETE(vms->curdir, x, vms->fn, vmu);
@@ -7440,10 +7510,10 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
done:
if (vms->deleted) {
- memset(vms->deleted, 0, vmu->maxmsg * sizeof(int));
+ memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
}
if (vms->heard) {
- memset(vms->heard, 0, vmu->maxmsg * sizeof(int));
+ memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
}
return 0;
@@ -9327,20 +9397,20 @@ static int vm_execmain(struct ast_channel *chan, void *data)
/* Retrieve urgent, old and new message counts */
ast_debug(1, "Before open_mailbox\n");
res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
vms.oldmessages = vms.lastmsg + 1;
ast_debug(1, "Number of old messages: %d\n",vms.oldmessages);
/* check INBOX */
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
vms.newmessages = vms.lastmsg + 1;
ast_debug(1, "Number of new messages: %d\n",vms.newmessages);
/* Start in Urgent */
in_urgent = 1;
res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
vms.urgentmessages = vms.lastmsg + 1;
ast_debug(1, "Number of urgent messages: %d\n",vms.urgentmessages);
@@ -9354,7 +9424,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
in_urgent = 0;
res = open_mailbox(&vms, vmu, play_folder);
}
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
/* If there are no new messages, inform the user and hangup */
@@ -9370,13 +9440,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
in_urgent = 0;
play_folder = 1;
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
} else if (!vms.urgentmessages && vms.newmessages) {
/* If we have new messages but none are urgent */
in_urgent = 0;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
}
}
@@ -9444,7 +9514,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
/* If folder is not urgent, set in_urgent to zero! */
if (cmd != 11) in_urgent = 0;
res = open_mailbox(&vms, vmu, cmd);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
play_folder = cmd;
cmd = 0;
@@ -9575,7 +9645,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, 11); /* Open Urgent folder */
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n",vms.lastmsg + 1);
vms.curmsg = vms.lastmsg;
@@ -9604,7 +9674,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
vms.curmsg = -1;
@@ -9666,7 +9736,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
vms.curmsg = -1;
@@ -9703,7 +9773,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
vms.curmsg = -1;
@@ -9776,7 +9846,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
vms.curmsg = -1;