aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2008-08-07 23:26:24 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2008-08-07 23:26:24 +0000
commit0e940b6b8c12ce77dc24a17c722c7f13250b51a3 (patch)
treec640f25a73c31cde604371d3739d8be4ab96b2e7 /apps
parentdf3168298fd8023648b14faef8beed99b8e5b9fa (diff)
Merged revisions 136715 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r136715 | mmichelson | 2008-08-07 17:25:50 -0500 (Thu, 07 Aug 2008) | 18 lines Merging the imap_consistency_trunk branch to trunk. For an explanation of what "imap_consistency" is, please see svn revision 134223 to the 1.4 branch. Coincidentally, this also fixes a recent bug report regarding the inability to save messages to the new folder when using IMAP storage since they will would be flagged as "seen" and not be recognized as new messages. (closes issue #13234) Reported by: jaroth ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@136719 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rw-r--r--apps/app_voicemail.c7109
1 files changed, 3498 insertions, 3611 deletions
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 2f7bd55f0..a74201c98 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -140,19 +140,16 @@ struct ast_vm_user;
static int init_mailstream(struct vm_state *vms, int box);
static void write_file(char *filename, char *buffer, unsigned long len);
static char *get_header_by_tag(char *header, char *tag, char *buf, size_t len);
-static void vm_imap_delete(int msgnum, struct vm_state *vms);
+static void vm_imap_delete(int msgnum, struct ast_vm_user *vmu);
static char *get_user_by_mailbox(char *mailbox, char *buf, size_t len);
static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive);
static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, int interactive);
-static struct vm_state *create_vm_state_from_user(struct ast_vm_user *vmu, char *mailbox);
+static struct vm_state *create_vm_state_from_user(struct ast_vm_user *vmu);
static void vmstate_insert(struct vm_state *vms);
static void vmstate_delete(struct vm_state *vms);
static void set_update(MAILSTREAM * stream);
static void init_vm_state(struct vm_state *vms);
-static void check_msgArray(struct vm_state *vms);
-static void copy_msgArray(struct vm_state *dst, struct vm_state *src);
static int save_body(BODY *body, struct vm_state *vms, char *section, char *format);
-static int make_gsm_file(char *dest, size_t len, char *imapuser, char *dir, int num);
static void get_mailbox_delimiter(MAILSTREAM *stream);
static void mm_parsequota (MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pquota);
static void imap_mailbox_name(char *spec, size_t len, struct vm_state *vms, int box, int target);
@@ -160,7 +157,7 @@ static int imap_store_file(char *dir, char *mailboxuser, char *mailboxcontext, i
static void update_messages_by_imapuser(const char *user, unsigned long number);
static int imap_remove_file (char *dir, int msgnum);
-static int imap_retrieve_file (char *dir, int msgnum, const char *mailbox, char *context);
+static int imap_retrieve_file (const char *dir, const int msgnum, const char *mailbox, const char *context);
static int imap_delete_old_greeting (char *dir, struct vm_state *vms);
static void check_quota(struct vm_state *vms, char *mailbox);
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box);
@@ -444,17 +441,16 @@ static char odbc_table[80];
#define EXISTS(a,b,c,d) (message_exists(a,b))
#define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f))
#define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
-#define DELETE(a,b,c) (delete_file(a,b))
+#define DELETE(a,b,c,d) (delete_file(a,b))
#else
#ifdef IMAP_STORAGE
-#define RETRIEVE(a,b,c,d) (imap_retrieve_file(a,b,c,d ))
#define DISPOSE(a,b) (imap_remove_file(a,b))
#define STORE(a,b,c,d,e,f,g,h,i) (imap_store_file(a,b,c,d,e,f,g,h,i))
#define EXISTS(a,b,c,d) (ast_fileexists(c, NULL, d) > 0)
+#define RETRIEVE(a,b,c,d) imap_retrieve_file(a,b,c,d)
#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
#define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
-#define IMAP_DELETE(a,b,c,d) (vm_imap_delete(b,d))
-#define DELETE(a,b,c) (vm_delete(c))
+#define DELETE(a,b,c,d) (vm_imap_delete(b,d))
#else
#define RETRIEVE(a,b,c,d)
#define DISPOSE(a,b)
@@ -462,7 +458,7 @@ static char odbc_table[80];
#define EXISTS(a,b,c,d) (ast_fileexists(c, NULL, d) > 0)
#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
#define COPY(a,b,c,d,e,f,g,h) (copy_plain_file(g,h));
-#define DELETE(a,b,c) (vm_delete(c))
+#define DELETE(a,b,c,d) (vm_delete(c))
#endif
#endif
@@ -1044,40 +1040,35 @@ static int make_dir(char *dest, int len, const char *context, const char *ext, c
return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
}
-#ifdef IMAP_STORAGE
-static int make_gsm_file(char *dest, size_t len, char *imapuser, char *dir, int num)
+/*!
+ * \brief Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.
+ * \param dest The variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
+ * \param len The length of the path string that was written out.
+ *
+ * The path is constructed as
+ * VM_SPOOL_DIRcontext/ext/folder
+ *
+ * \return zero on success, -1 on error.
+ */
+static int make_file(char *dest, const int len, const char *dir, const int num)
{
- int res;
- if ((res = ast_mkdir(dir, 01777))) {
- ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dir, strerror(res));
- return snprintf(dest, len, "%s/msg%04d", dir, num);
- }
return snprintf(dest, len, "%s/msg%04d", dir, num);
}
-static void vm_imap_delete(int msgnum, struct vm_state *vms)
+/* same as mkstemp, but return a FILE * */
+static FILE *vm_mkftemp(char *template)
{
- unsigned long messageNum = 0;
- char arg[10];
-
- /* find real message number based on msgnum */
- /* this may be an index into vms->msgArray based on the msgnum. */
-
- messageNum = vms->msgArray[msgnum];
- if (messageNum == 0) {
- ast_log(LOG_WARNING, "msgnum %d, mailbox message %lu is zero.\n", msgnum, messageNum);
- return;
+ FILE *p = NULL;
+ int pfd = mkstemp(template);
+ chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
+ if (pfd > -1) {
+ p = fdopen(pfd, "w+");
+ if (!p) {
+ close(pfd);
+ pfd = -1;
+ }
}
- ast_debug(3, "deleting msgnum %d, which is mailbox message %lu\n", msgnum, messageNum);
- /* delete message */
- snprintf(arg, sizeof(arg), "%lu", messageNum);
- mail_setflag(vms->mailstream, arg, "\\DELETED");
-}
-
-#endif
-static int make_file(char *dest, int len, char *dir, int num)
-{
- return snprintf(dest, len, "%s/msg%04d", dir, num);
+ return p;
}
/*! \brief basically mkdir -p $dest/$context/$ext/$folder
@@ -1101,623 +1092,1908 @@ static int create_dirpath(char *dest, int len, const char *context, const char *
return 0;
}
-/*! \brief Lock file path
- only return failure if ast_lock_path returns 'timeout',
- not if the path does not exist or any other reason
-*/
-static int vm_lock_path(const char *path)
+static const char *mbox(int id)
{
- switch (ast_lock_path(path)) {
- case AST_LOCK_TIMEOUT:
- return -1;
- default:
- return 0;
+ static const char *msgs[] = {
+#ifdef IMAP_STORAGE
+ imapfolder,
+#else
+ "INBOX",
+#endif
+ "Old",
+ "Work",
+ "Family",
+ "Friends",
+ "Cust1",
+ "Cust2",
+ "Cust3",
+ "Cust4",
+ "Cust5",
+ "Deleted",
+ "Urgent"
+ };
+ return (id >= 0 && id < (sizeof(msgs)/sizeof(msgs[0]))) ? msgs[id] : "Unknown";
+}
+
+static void free_user(struct ast_vm_user *vmu)
+{
+ if (ast_test_flag(vmu, VM_ALLOCED))
+ ast_free(vmu);
+}
+
+/* All IMAP-specific functions should go in this block. This
+* keeps them from being spread out all over the code */
+#ifdef IMAP_STORAGE
+static void vm_imap_delete(int msgnum, struct ast_vm_user *vmu)
+{
+ char arg[10];
+ struct vm_state *vms;
+ unsigned long messageNum;
+
+ /* Greetings aren't stored in IMAP, so we can't delete them there */
+ if (msgnum < 0) {
+ return;
}
+
+ if (!(vms = get_vm_state_by_mailbox(vmu->mailbox, 1)) && !(vms = get_vm_state_by_mailbox(vmu->mailbox, 0))) {
+ ast_log(LOG_WARNING, "Couldn't find a vm_state for mailbox %s. Unable to set \\DELETED flag for message %d\n", vmu->mailbox, msgnum);
+ return;
+ }
+
+ /* find real message number based on msgnum */
+ /* this may be an index into vms->msgArray based on the msgnum. */
+ messageNum = vms->msgArray[msgnum];
+ if (messageNum == 0) {
+ ast_log(LOG_WARNING, "msgnum %d, mailbox message %lu is zero.\n", msgnum, messageNum);
+ return;
+ }
+ ast_debug(3, "deleting msgnum %d, which is mailbox message %lu\n", msgnum, messageNum);
+ /* delete message */
+ snprintf(arg, sizeof(arg), "%lu", messageNum);
+ mail_setflag(vms->mailstream, arg, "\\DELETED");
}
+static int imap_retrieve_greeting (const char *dir, const int msgnum, struct ast_vm_user *vmu)
+{
+ struct vm_state *vms_p;
+ char *file, *filename;
+ char *attachment;
+ int ret = 0, i;
+ BODY *body;
-#ifdef ODBC_STORAGE
-struct generic_prepare_struct {
- char *sql;
- int argc;
- char **argv;
-};
+ /* This function is only used for retrieval of IMAP greetings
+ * regular messages are not retrieved this way, nor are greetings
+ * if they are stored locally*/
+ if (msgnum > -1 || !imapgreetings) {
+ return 0;
+ } else {
+ file = strrchr(ast_strdupa(dir), '/');
+ if (file)
+ *file++ = '\0';
+ else {
+ ast_debug (1, "Failed to procure file name from directory passed.\n");
+ return -1;
+ }
+ }
-static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
+ /* check if someone is accessing this box right now... */
+ if (!(vms_p = get_vm_state_by_mailbox(vmu->mailbox, 1)) ||!(vms_p = get_vm_state_by_mailbox(vmu->mailbox, 0))) {
+ ast_log(LOG_ERROR, "Voicemail state not found!\n");
+ return -1;
+ }
+
+ ret = init_mailstream(vms_p, GREETINGS_FOLDER);
+ if (!vms_p->mailstream) {
+ ast_log(LOG_ERROR, "IMAP mailstream is NULL\n");
+ return -1;
+ }
+
+ /*XXX Yuck, this could probably be done a lot better */
+ for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
+ mail_fetchstructure(vms_p->mailstream, i + 1, &body);
+ /* We have the body, now we extract the file name of the first attachment. */
+ if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
+ attachment = ast_strdupa(body->nested.part->next->body.parameter->value);
+ } else {
+ ast_log(LOG_ERROR, "There is no file attached to this IMAP message.\n");
+ return -1;
+ }
+ filename = strsep(&attachment, ".");
+ if (!strcmp(filename, file)) {
+ ast_copy_string(vms_p->fn, dir, sizeof(vms_p->fn));
+ vms_p->msgArray[vms_p->curmsg] = i + 1;
+ save_body(body, vms_p, "2", attachment);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int imap_retrieve_file(const char *dir, const int msgnum, const char *mailbox, const char *context)
{
- struct generic_prepare_struct *gps = data;
- int res, i;
- SQLHSTMT stmt;
+ BODY *body;
+ char *header_content;
+ char *attachedfilefmt;
+ char buf[80];
+ struct vm_state *vms;
+ char text_file[PATH_MAX];
+ FILE *text_file_ptr;
+ int res = 0;
+ struct ast_vm_user *vmu;
- res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
- return NULL;
+ if (!(vmu = find_user(NULL, context, mailbox))) {
+ ast_log(LOG_WARNING, "Couldn't find user with mailbox %s@%s\n", mailbox, context);
+ return -1;
}
- res = SQLPrepare(stmt, (unsigned char *)gps->sql, SQL_NTS);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", gps->sql);
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- return NULL;
+
+ if (msgnum < 0) {
+ if (imapgreetings) {
+ res = imap_retrieve_greeting(dir, msgnum, vmu);
+ goto exit;
+ } else {
+ res = 0;
+ goto exit;
+ }
+ }
+
+ /* Before anything can happen, we need a vm_state so that we can
+ * actually access the imap server through the vms->mailstream
+ */
+ if (!(vms = get_vm_state_by_mailbox(vmu->mailbox, 1)) && !(vms = get_vm_state_by_mailbox(vmu->mailbox, 0))) {
+ /* This should not happen. If it does, then I guess we'd
+ * need to create the vm_state, extract which mailbox to
+ * open, and then set up the msgArray so that the correct
+ * IMAP message could be accessed. If I have seen correctly
+ * though, the vms should be obtainable from the vmstates list
+ * and should have its msgArray properly set up.
+ */
+ ast_log(LOG_ERROR, "Couldn't find a vm_state for mailbox %s!!! Oh no!\n", vmu->mailbox);
+ res = -1;
+ goto exit;
+ }
+
+ make_file(vms->fn, sizeof(vms->fn), dir, msgnum);
+
+ /* Don't try to retrieve a message from IMAP if it already is on the file system */
+ if (ast_fileexists(vms->fn, NULL, NULL) > 0) {
+ res = 0;
+ goto exit;
+ }
+
+ if (option_debug > 2)
+ ast_log (LOG_DEBUG,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", msgnum, vms->msgArray[msgnum]);
+ if (vms->msgArray[msgnum] == 0) {
+ ast_log (LOG_WARNING,"Trying to access unknown message\n");
+ res = -1;
+ goto exit;
+ }
+
+ /* This will only work for new messages... */
+ header_content = mail_fetchheader (vms->mailstream, vms->msgArray[msgnum]);
+ /* empty string means no valid header */
+ if (ast_strlen_zero(header_content)) {
+ ast_log (LOG_ERROR,"Could not fetch header for message number %ld\n",vms->msgArray[msgnum]);
+ res = -1;
+ goto exit;
+ }
+
+ mail_fetchstructure (vms->mailstream,vms->msgArray[msgnum],&body);
+
+ /* We have the body, now we extract the file name of the first attachment. */
+ if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
+ attachedfilefmt = ast_strdupa(body->nested.part->next->body.parameter->value);
+ } else {
+ ast_log(LOG_ERROR, "There is no file attached to this IMAP message.\n");
+ res = -1;
+ goto exit;
}
- for (i = 0; i < gps->argc; i++)
- SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0, NULL);
+
+ /* Find the format of the attached file */
+
+ strsep(&attachedfilefmt, ".");
+ if (!attachedfilefmt) {
+ ast_log(LOG_ERROR, "File format could not be obtained from IMAP message attachment\n");
+ res = -1;
+ goto exit;
+ }
+
+ save_body(body, vms, "2", attachedfilefmt);
+
+ /* Get info from headers!! */
+ snprintf(text_file, sizeof(text_file), "%s.%s", vms->fn, "txt");
+
+ if (!(text_file_ptr = fopen(text_file, "w"))) {
+ ast_log(LOG_WARNING, "Unable to open/create file %s: %s\n", text_file, strerror(errno));
+ }
+
+ fprintf(text_file_ptr, "%s\n", "[message]");
- return stmt;
+ get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:", buf, sizeof(buf));
+ fprintf(text_file_ptr, "callerid=\"%s\" ", S_OR(buf, ""));
+ get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Name:", buf, sizeof(buf));
+ fprintf(text_file_ptr, "<%s>\n", S_OR(buf, ""));
+ get_header_by_tag(header_content, "X-Asterisk-VM-Context:", buf, sizeof(buf));
+ fprintf(text_file_ptr, "context=%s\n", S_OR(buf, ""));
+ get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:", buf, sizeof(buf));
+ fprintf(text_file_ptr, "origtime=%s\n", S_OR(buf, ""));
+ get_header_by_tag(header_content, "X-Asterisk-VM-Duration:", buf, sizeof(buf));
+ fprintf(text_file_ptr, "duration=%s\n", S_OR(buf, ""));
+ get_header_by_tag(header_content, "X-Asterisk-VM-Category:", buf, sizeof(buf));
+ fprintf(text_file_ptr, "category=%s\n", S_OR(buf, ""));
+ fclose(text_file_ptr);
+
+exit:
+ free_user(vmu);
+ return res;
}
-static int retrieve_file(char *dir, int msgnum)
+static int folder_int(const char *folder)
{
- int x = 0;
- int res;
- int fd = -1;
- size_t fdlen = 0;
- void *fdm = MAP_FAILED;
- SQLSMALLINT colcount = 0;
- SQLHSTMT stmt;
- char sql[PATH_MAX];
- char fmt[80] = "";
- char *c;
- char coltitle[256];
- SQLSMALLINT collen;
- SQLSMALLINT datatype;
- SQLSMALLINT decimaldigits;
- SQLSMALLINT nullable;
- SQLULEN colsize;
- SQLLEN colsize2;
- FILE *f = NULL;
- char rowdata[80];
+ /*assume a NULL folder means INBOX*/
+ if (!folder)
+ return 0;
+ if (!strcasecmp(folder, imapfolder))
+ return 0;
+ else if (!strcasecmp(folder, "Old"))
+ return 1;
+ else if (!strcasecmp(folder, "Work"))
+ return 2;
+ else if (!strcasecmp(folder, "Family"))
+ return 3;
+ else if (!strcasecmp(folder, "Friends"))
+ return 4;
+ else if (!strcasecmp(folder, "Cust1"))
+ return 5;
+ else if (!strcasecmp(folder, "Cust2"))
+ return 6;
+ else if (!strcasecmp(folder, "Cust3"))
+ return 7;
+ else if (!strcasecmp(folder, "Cust4"))
+ return 8;
+ else if (!strcasecmp(folder, "Cust5"))
+ return 9;
+ else /*assume they meant INBOX if folder is not found otherwise*/
+ return 0;
+}
+
+static int imap_store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum, struct ast_channel *chan, struct ast_vm_user *vmu, char *fmt, int duration, struct vm_state *vms)
+{
+ char *myserveremail = serveremail;
char fn[PATH_MAX];
- char full_fn[PATH_MAX];
- char msgnums[80];
- char *argv[] = { dir, msgnums };
- struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
+ char mailbox[256];
+ char *stringp;
+ FILE *p = NULL;
+ char tmp[80] = "/tmp/astmail-XXXXXX";
+ long len;
+ void *buf;
+ int tempcopy = 0;
+ STRING str;
+
+ /* Attach only the first format */
+ fmt = ast_strdupa(fmt);
+ stringp = fmt;
+ strsep(&stringp, "|");
- struct odbc_obj *obj;
- obj = ast_odbc_request_obj(odbc_database, 0);
- if (obj) {
- ast_copy_string(fmt, vmfmts, sizeof(fmt));
- c = strchr(fmt, '|');
- if (c)
- *c = '\0';
- if (!strcasecmp(fmt, "wav49"))
- strcpy(fmt, "WAV");
- snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
- if (msgnum > -1)
- make_file(fn, sizeof(fn), dir, msgnum);
- else
- ast_copy_string(fn, dir, sizeof(fn));
- snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
-
- if (!(f = fopen(full_fn, "w+"))) {
- ast_log(LOG_WARNING, "Failed to open/create '%s'\n", full_fn);
- goto yuck;
+ if (!ast_strlen_zero(vmu->serveremail))
+ myserveremail = vmu->serveremail;
+
+ if (msgnum > -1)
+ make_file(fn, sizeof(fn), dir, msgnum);
+ else
+ ast_copy_string (fn, dir, sizeof(fn));
+
+ if (ast_strlen_zero(vmu->email)) {
+ /* We need the vmu->email to be set when we call make_email_file, but
+ * if we keep it set, a duplicate e-mail will be created. So at the end
+ * of this function, we will revert back to an empty string if tempcopy
+ * is 1.
+ */
+ ast_copy_string(vmu->email, vmu->imapuser, sizeof(vmu->email));
+ tempcopy = 1;
+ }
+
+ if (!strcmp(fmt, "wav49"))
+ fmt = "WAV";
+ ast_debug(3, "Storing file '%s', format '%s'\n", fn, fmt);
+
+ /* Make a temporary file instead of piping directly to sendmail, in case the mail
+ command hangs. */
+ if (!(p = vm_mkftemp(tmp))) {
+ ast_log(LOG_WARNING, "Unable to store '%s' (can't create temporary file)\n", fn);
+ if (tempcopy)
+ *(vmu->email) = '\0';
+ return -1;
+ }
+
+ if (msgnum < 0 && imapgreetings) {
+ init_mailstream(vms, GREETINGS_FOLDER);
+ imap_delete_old_greeting(fn, vms);
+ }
+
+ make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), fn, fmt, duration, 1, chan, NULL, 1);
+ /* read mail file to memory */
+ len = ftell(p);
+ rewind(p);
+ if (!(buf = ast_malloc(len + 1))) {
+ ast_log(LOG_ERROR, "Can't allocate %ld bytes to read message\n", len + 1);
+ fclose(p);
+ if (tempcopy)
+ *(vmu->email) = '\0';
+ return -1;
+ }
+ fread(buf, len, 1, p);
+ ((char *)buf)[len] = '\0';
+ INIT(&str, mail_string, buf, len);
+ init_mailstream(vms, NEW_FOLDER);
+ imap_mailbox_name(mailbox, sizeof(mailbox), vms, NEW_FOLDER, 1);
+ if (!mail_append(vms->mailstream, mailbox, &str))
+ ast_log(LOG_ERROR, "Error while sending the message to %s\n", mailbox);
+ fclose(p);
+ unlink(tmp);
+ ast_free(buf);
+ ast_debug(3, "%s stored\n", fn);
+
+ if (tempcopy)
+ *(vmu->email) = '\0';
+
+ return 0;
+
+}
+
+static int messagecount(const char *context, const char *mailbox, const char *folder)
+{
+ SEARCHPGM *pgm;
+ SEARCHHEADER *hdr;
+
+ struct ast_vm_user *vmu, vmus;
+ struct vm_state *vms_p;
+ int ret = 0;
+ int fold = folder_int(folder);
+
+ if (ast_strlen_zero(mailbox))
+ return 0;
+
+ /* We have to get the user before we can open the stream! */
+ /* ast_log(LOG_DEBUG, "Before find_user, context is %s and mailbox is %s\n", context, mailbox); */
+ vmu = find_user(&vmus, context, mailbox);
+ if (!vmu) {
+ ast_log(LOG_ERROR, "Couldn't find mailbox %s in context %s\n", mailbox, context);
+ return -1;
+ } else {
+ /* No IMAP account available */
+ if (vmu->imapuser[0] == '\0') {
+ ast_log(LOG_WARNING, "IMAP user not set for mailbox %s\n", vmu->mailbox);
+ return -1;
}
-
- snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
- snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?", odbc_table);
- stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
- if (!stmt) {
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
- ast_odbc_release_obj(obj);
- goto yuck;
+ }
+
+ /* No IMAP account available */
+ if (vmu->imapuser[0] == '\0') {
+ ast_log(LOG_WARNING, "IMAP user not set for mailbox %s\n", vmu->mailbox);
+ free_user(vmu);
+ return -1;
+ }
+
+ /* check if someone is accessing this box right now... */
+ vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1);
+ if (!vms_p) {
+ vms_p = get_vm_state_by_mailbox(mailbox, 1);
+ }
+ if (vms_p) {
+ ast_debug(3, "Returning before search - user is logged in\n");
+ if (fold == 0) { /* INBOX */
+ return vms_p->newmessages;
}
- res = SQLFetch(stmt);
- if (res == SQL_NO_DATA) {
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
- } else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
+ if (fold == 1) { /* Old messages */
+ return vms_p->oldmessages;
}
- fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, VOICEMAIL_FILE_MODE);
- if (fd < 0) {
- ast_log(LOG_WARNING, "Failed to write '%s': %s\n", full_fn, strerror(errno));
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
+ }
+
+ /* add one if not there... */
+ vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0);
+ if (!vms_p) {
+ vms_p = get_vm_state_by_mailbox(mailbox, 0);
+ }
+
+ if (!vms_p) {
+ ast_debug(3, "Adding new vmstate for %s\n", vmu->imapuser);
+ if (!(vms_p = ast_calloc(1, sizeof(*vms_p)))) {
+ return -1;
}
- res = SQLNumResultCols(stmt, &colcount);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
+ ast_copy_string(vms_p->imapuser, vmu->imapuser, sizeof(vms_p->imapuser));
+ ast_copy_string(vms_p->username, mailbox, sizeof(vms_p->username)); /* save for access from interactive entry point */
+ vms_p->mailstream = NIL; /* save for access from interactive entry point */
+ ast_debug(3, "Copied %s to %s\n", vmu->imapuser, vms_p->imapuser);
+ vms_p->updated = 1;
+ /* set mailbox to INBOX! */
+ ast_copy_string(vms_p->curbox, mbox(fold), sizeof(vms_p->curbox));
+ init_vm_state(vms_p);
+ vmstate_insert(vms_p);
+ }
+ ret = init_mailstream(vms_p, fold);
+ if (!vms_p->mailstream) {
+ ast_log(LOG_ERROR, "Houston we have a problem - IMAP mailstream is NULL\n");
+ return -1;
+ }
+ if (ret == 0) {
+ pgm = mail_newsearchpgm ();
+ hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailbox);
+ pgm->header = hdr;
+ if (fold != 1) {
+ pgm->unseen = 1;
+ pgm->seen = 0;
}
- if (f)
- fprintf(f, "[message]\n");
- for (x = 0; x < colcount; x++) {
- rowdata[0] = '\0';
- collen = sizeof(coltitle);
- res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
- &datatype, &colsize, &decimaldigits, &nullable);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
- }
- if (!strcasecmp(coltitle, "recording")) {
- off_t offset;
- res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
- fdlen = colsize2;
- if (fd > -1) {
- char tmp[1] = "";
- lseek(fd, fdlen - 1, SEEK_SET);
- if (write(fd, tmp, 1) != 1) {
- close(fd);
- fd = -1;
- continue;
- }
- /* Read out in small chunks */
- for (offset = 0; offset < colsize2; offset += CHUNKSIZE) {
- if ((fdm = mmap(NULL, CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
- ast_log(LOG_WARNING, "Could not mmap the output file: %s (%d)\n", strerror(errno), errno);
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
- } else {
- res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, CHUNKSIZE, NULL);
- munmap(fdm, CHUNKSIZE);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
- unlink(full_fn);
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
- }
- }
- }
- truncate(full_fn, fdlen);
- }
- } else {
- SQLLEN ind;
- res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &ind);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- SQLINTEGER nativeerror = 0;
- SQLSMALLINT diagbytes = 0;
- unsigned char state[10], diagnostic[256];
- SQLGetDiagRec(SQL_HANDLE_STMT, stmt, 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
- ast_log(LOG_WARNING, "SQL Get Data error: %s: %s!\n[%s]\n\n", state, diagnostic, sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
+ /* In the special case where fold is 1 (old messages) we have to do things a bit
+ * differently. Old messages are stored in the INBOX but are marked as "seen"
+ */
+ else {
+ pgm->unseen = 0;
+ pgm->seen = 1;
+ }
+ pgm->undeleted = 1;
+ pgm->deleted = 0;
+
+ vms_p->vmArrayIndex = 0;
+ mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
+ if (fold == 0)
+ vms_p->newmessages = vms_p->vmArrayIndex;
+ if (fold == 1)
+ vms_p->oldmessages = vms_p->vmArrayIndex;
+ /* Freeing the searchpgm also frees the searchhdr */
+ mail_free_searchpgm(&pgm);
+ vms_p->updated = 0;
+ return vms_p->vmArrayIndex;
+ } else {
+ mail_ping(vms_p->mailstream);
+ }
+ return 0;
+}
+static int inboxcount(const char *mailbox_context, int *newmsgs, int *oldmsgs)
+{
+ char tmp[PATH_MAX] = "";
+ char *mailboxnc;
+ char *context;
+ char *mb;
+ char *cur;
+ if (newmsgs)
+ *newmsgs = 0;
+ if (oldmsgs)
+ *oldmsgs = 0;
+
+ ast_debug(3, "Mailbox is set to %s\n", mailbox_context);
+ /* If no mailbox, return immediately */
+ if (ast_strlen_zero(mailbox_context))
+ return 0;
+
+ ast_copy_string(tmp, mailbox_context, sizeof(tmp));
+ context = strchr(tmp, '@');
+ if (strchr(mailbox_context, ',')) {
+ int tmpnew, tmpold;
+ ast_copy_string(tmp, mailbox_context, sizeof(tmp));
+ mb = tmp;
+ while ((cur = strsep(&mb, ", "))) {
+ if (!ast_strlen_zero(cur)) {
+ if (inboxcount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
+ return -1;
+ else {
+ if (newmsgs)
+ *newmsgs += tmpnew;
+ if (oldmsgs)
+ *oldmsgs += tmpold;
}
- if (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir") && f)
- fprintf(f, "%s=%s\n", coltitle, rowdata);
}
}
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- } else
- ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
-yuck:
- if (f)
- fclose(f);
- if (fd > -1)
- close(fd);
- return x - 1;
+ return 0;
+ }
+ if (context) {
+ *context = '\0';
+ mailboxnc = tmp;
+ context++;
+ } else {
+ context = "default";
+ mailboxnc = (char *)mailbox_context;
+ }
+ if (newmsgs) {
+ if ((*newmsgs = messagecount(context, mailboxnc, imapfolder)) < 0)
+ return -1;
+ }
+ if (oldmsgs) {
+ if ((*oldmsgs = messagecount(context, mailboxnc, "Old")) < 0)
+ return -1;
+ }
+ return 0;
}
-static int remove_file(char *dir, int msgnum)
+/**
+* \brief Determines if the given folder has messages.
+* \param mailbox The @ delimited string for user@context. If no context is found, uses 'default' for the context.
+* \param folder the folder to look in
+*
+* This function is used when the mailbox is stored in an IMAP back end.
+* This invokes the messagecount(). Here we are interested in the presence of messages (> 0) only, not the actual count.
+* \return 1 if the folder has one or more messages. zero otherwise.
+*/
+
+static int has_voicemail(const char *mailbox, const char *folder)
{
- char fn[PATH_MAX];
- char full_fn[PATH_MAX];
- char msgnums[80];
+ char tmp[256], *tmp2, *mbox, *context;
+ ast_copy_string(tmp, mailbox, sizeof(tmp));
+ tmp2 = tmp;
+ if (strchr(tmp2, ',')) {
+ while ((mbox = strsep(&tmp2, ","))) {
+ if (!ast_strlen_zero(mbox)) {
+ if (has_voicemail(mbox, folder))
+ return 1;
+ }
+ }
+ }
+ if ((context= strchr(tmp, '@')))
+ *context++ = '\0';
+ else
+ context = "default";
+ return messagecount(context, tmp, folder) ? 1 : 0;
+}
+
+/*!
+* \brief Copies a message from one mailbox to another.
+* \param chan
+* \param vmu
+* \param imbox
+* \param msgnum
+* \param duration
+* \param recip
+* \param fmt
+* \param dir
+*
+* This works with IMAP storage based mailboxes.
+*
+* \return zero on success, -1 on error.
+*/
+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 *dir)
+{
+ struct vm_state *sendvms = NULL, *destvms = NULL;
+ char messagestring[10]; /*I guess this could be a problem if someone has more than 999999999 messages...*/
+ if (msgnum >= recip->maxmsg) {
+ ast_log(LOG_WARNING, "Unable to copy mail, mailbox %s is full\n", recip->mailbox);
+ return -1;
+ }
+ if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
+ ast_log(LOG_ERROR, "Couldn't get vm_state for originator's mailbox!!\n");
+ return -1;
+ }
+ if (!(destvms = get_vm_state_by_imapuser(recip->imapuser, 0))) {
+ ast_log(LOG_ERROR, "Couldn't get vm_state for destination mailbox!\n");
+ return -1;
+ }
+ snprintf(messagestring, sizeof(messagestring), "%ld", sendvms->msgArray[msgnum]);
+ if ((mail_copy(sendvms->mailstream, messagestring, (char *) mbox(imbox)) == T))
+ return 0;
+ ast_log(LOG_WARNING, "Unable to copy message from mailbox %s to mailbox %s\n", vmu->mailbox, recip->mailbox);
+ return -1;
+}
+
+static void imap_mailbox_name(char *spec, size_t len, struct vm_state *vms, int box, int use_folder)
+{
+ char tmp[256], *t = tmp;
+ size_t left = sizeof(tmp);
- if (msgnum > -1) {
- snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
- make_file(fn, sizeof(fn), dir, msgnum);
- } else
- ast_copy_string(fn, dir, sizeof(fn));
- ast_filedelete(fn, NULL);
- if (ast_check_realtime("voicemail_data")) {
- ast_destroy_realtime("voicemail_data", "filename", fn, NULL);
+ if (box == OLD_FOLDER) {
+ ast_copy_string(vms->curbox, mbox(NEW_FOLDER), sizeof(vms->curbox));
+ } else {
+ ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
+ }
+
+ if (box == NEW_FOLDER) {
+ ast_copy_string(vms->vmbox, "vm-INBOX", sizeof(vms->vmbox));
+ } else {
+ snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", mbox(box));
+ }
+
+ /* Build up server information */
+ ast_build_string(&t, &left, "{%s:%s/imap", imapserver, imapport);
+
+ /* Add authentication user if present */
+ if (!ast_strlen_zero(authuser))
+ ast_build_string(&t, &left, "/authuser=%s", authuser);
+
+ /* Add flags if present */
+ if (!ast_strlen_zero(imapflags))
+ ast_build_string(&t, &left, "/%s", imapflags);
+
+ /* End with username */
+ ast_build_string(&t, &left, "/user=%s}", vms->imapuser);
+ if (box == NEW_FOLDER || box == OLD_FOLDER)
+ snprintf(spec, len, "%s%s", tmp, use_folder? imapfolder: "INBOX");
+ else if (box == GREETINGS_FOLDER)
+ snprintf(spec, len, "%s%s", tmp, greetingfolder);
+ else { /* Other folders such as Friends, Family, etc... */
+ if (!ast_strlen_zero(imapparentfolder)) {
+ /* imapparentfolder would typically be set to INBOX */
+ snprintf(spec, len, "%s%s%c%s", tmp, imapparentfolder, delimiter, mbox(box));
+ } else {
+ snprintf(spec, len, "%s%s", tmp, mbox(box));
+ }
}
- snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
- unlink(full_fn);
- return 0;
}
-static int last_message_index(struct ast_vm_user *vmu, char *dir)
+static int init_mailstream(struct vm_state *vms, int box)
{
- int x = 0;
- int res;
- SQLHSTMT stmt;
- char sql[PATH_MAX];
- char rowdata[20];
- char *argv[] = { dir };
- struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
+ MAILSTREAM *stream = NIL;
+ long debug;
+ char tmp[256];
+
+ if (!vms) {
+ ast_log (LOG_ERROR,"vm_state is NULL!\n");
+ return -1;
+ }
+ if (option_debug > 2)
+ ast_log (LOG_DEBUG,"vm_state user is:%s\n",vms->imapuser);
+ if (vms->mailstream == NIL || !vms->mailstream) {
+ if (option_debug)
+ ast_log (LOG_DEBUG,"mailstream not set.\n");
+ } else {
+ stream = vms->mailstream;
+ }
+ /* debug = T; user wants protocol telemetry? */
+ debug = NIL; /* NO protocol telemetry? */
- struct odbc_obj *obj;
- obj = ast_odbc_request_obj(odbc_database, 0);
- if (obj) {
- snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table);
- stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
- if (!stmt) {
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
- ast_odbc_release_obj(obj);
- goto yuck;
+ if (delimiter == '\0') { /* did not probe the server yet */
+ char *cp;
+#ifdef USE_SYSTEM_IMAP
+#include <imap/linkage.c>
+#elif defined(USE_SYSTEM_CCLIENT)
+#include <c-client/linkage.c>
+#else
+#include "linkage.c"
+#endif
+ /* Connect to INBOX first to get folders delimiter */
+ imap_mailbox_name(tmp, sizeof(tmp), vms, 0, 1);
+ ast_mutex_lock(&vms->lock);
+ stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
+ ast_mutex_unlock(&vms->lock);
+ if (stream == NIL) {
+ ast_log (LOG_ERROR, "Can't connect to imap server %s\n", tmp);
+ return -1;
}
- res = SQLFetch(stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
+ get_mailbox_delimiter(stream);
+ /* update delimiter in imapfolder */
+ for (cp = imapfolder; *cp; cp++)
+ if (*cp == '/')
+ *cp = delimiter;
+ }
+ /* Now connect to the target folder */
+ imap_mailbox_name(tmp, sizeof(tmp), vms, box, 1);
+ if (option_debug > 2)
+ ast_log (LOG_DEBUG,"Before mail_open, server: %s, box:%d\n", tmp, box);
+ ast_mutex_lock(&vms->lock);
+ vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
+ ast_mutex_unlock(&vms->lock);
+ if (vms->mailstream == NIL) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
+{
+ SEARCHPGM *pgm;
+ SEARCHHEADER *hdr;
+ int ret, urgent = 0;
+
+ /* If Urgent, then look at INBOX */
+ if (box == 11) {
+ box = NEW_FOLDER;
+ urgent = 1;
+ }
+
+ ast_copy_string(vms->imapuser,vmu->imapuser, sizeof(vms->imapuser));
+ ast_debug(3,"Before init_mailstream, user is %s\n",vmu->imapuser);
+
+ if ((ret = init_mailstream(vms, box)) || !vms->mailstream) {
+ ast_log(LOG_ERROR, "Could not initialize mailstream\n");
+ return -1;
+ }
+
+ create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
+
+ /* Check Quota */
+ if (box == 0) {
+ ast_debug(3, "Mailbox name set to: %s, about to check quotas\n", mbox(box));
+ check_quota(vms,(char *)mbox(box));
+ }
+
+ pgm = mail_newsearchpgm();
+
+ /* Check IMAP folder for Asterisk messages only... */
+ hdr = mail_newsearchheader("X-Asterisk-VM-Extension", vmu->mailbox);
+ pgm->header = hdr;
+ pgm->deleted = 0;
+ pgm->undeleted = 1;
+
+ /* if box = NEW_FOLDER, check for new, if box = OLD_FOLDER, check for read */
+ if (box == NEW_FOLDER && urgent == 1) {
+ pgm->unseen = 1;
+ pgm->seen = 0;
+ pgm->flagged = 1;
+ pgm->unflagged = 0;
+ } else if (box == NEW_FOLDER && urgent == 0) {
+ pgm->unseen = 1;
+ pgm->seen = 0;
+ pgm->flagged = 0;
+ pgm->unflagged = 1;
+ } else if (box == OLD_FOLDER) {
+ pgm->seen = 1;
+ pgm->unseen = 0;
+ }
+
+ ast_debug(3,"Before mail_search_full, user is %s\n",vmu->imapuser);
+
+ vms->vmArrayIndex = 0;
+ mail_search_full (vms->mailstream, NULL, pgm, NIL);
+ vms->lastmsg = vms->vmArrayIndex - 1;
+ mail_free_searchpgm(&pgm);
+
+ return 0;
+}
+
+static void write_file(char *filename, char *buffer, unsigned long len)
+{
+ FILE *output;
+ ast_log(LOG_NOTICE, "The name of the file I'm writing is %s\n", filename);
+
+ output = fopen (filename, "w");
+ fwrite (buffer, len, 1, output);
+ fclose (output);
+}
+
+static void update_messages_by_imapuser(const char *user, unsigned long number)
+{
+ struct vmstate *vlist = NULL;
+
+ AST_LIST_LOCK(&vmstates);
+ AST_LIST_TRAVERSE(&vmstates, vlist, list) {
+ if (!vlist->vms) {
+ ast_debug(3, "error: vms is NULL for %s\n", user);
+ continue;
}
- res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
+ if (!vlist->vms->imapuser) {
+ ast_debug(3, "error: imapuser is NULL for %s\n", user);
+ continue;
}
- if (sscanf(rowdata, "%d", &x) != 1)
- ast_log(LOG_WARNING, "Failed to read message count!\n");
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- } else
- ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
-yuck:
- return x - 1;
+ ast_debug(3, "saving mailbox message number %lu as message %d. Interactive set to %d\n", number, vlist->vms->vmArrayIndex, vlist->vms->interactive);
+ vlist->vms->msgArray[vlist->vms->vmArrayIndex++] = number;
+ }
+ AST_LIST_UNLOCK(&vmstates);
}
-static int message_exists(char *dir, int msgnum)
+void mm_searched(MAILSTREAM *stream, unsigned long number)
{
- int x = 0;
- int res;
- SQLHSTMT stmt;
- char sql[PATH_MAX];
- char rowdata[20];
- char msgnums[20];
- char *argv[] = { dir, msgnums };
- struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
+ char *mailbox = stream->mailbox, buf[1024] = "", *user;
- struct odbc_obj *obj;
- obj = ast_odbc_request_obj(odbc_database, 0);
- if (obj) {
- snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
- snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?", odbc_table);
- stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
- if (!stmt) {
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
- ast_odbc_release_obj(obj);
- goto yuck;
- }
- res = SQLFetch(stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
+ if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))))
+ return;
+
+ update_messages_by_imapuser(user, number);
+}
+
+static struct ast_vm_user *find_user_realtime_imapuser(const char *imapuser)
+{
+ struct ast_variable *var;
+ struct ast_vm_user *vmu;
+
+ vmu = ast_calloc(1, sizeof *vmu);
+ if (!vmu)
+ return NULL;
+ ast_set_flag(vmu, VM_ALLOCED);
+ populate_defaults(vmu);
+
+ var = ast_load_realtime("voicemail", "imapuser", imapuser, NULL);
+ if (var) {
+ apply_options_full(vmu, var);
+ ast_variables_destroy(var);
+ return vmu;
+ } else {
+ free(vmu);
+ return NULL;
+ }
+}
+
+/* Interfaces to C-client */
+
+void mm_exists(MAILSTREAM * stream, unsigned long number)
+{
+ /* mail_ping will callback here if new mail! */
+ ast_debug(4, "Entering EXISTS callback for message %ld\n", number);
+ if (number == 0) return;
+ set_update(stream);
+}
+
+
+void mm_expunged(MAILSTREAM * stream, unsigned long number)
+{
+ /* mail_ping will callback here if expunged mail! */
+ ast_debug(4, "Entering EXPUNGE callback for message %ld\n", number);
+ if (number == 0) return;
+ set_update(stream);
+}
+
+
+void mm_flags(MAILSTREAM * stream, unsigned long number)
+{
+ /* mail_ping will callback here if read mail! */
+ ast_debug(4, "Entering FLAGS callback for message %ld\n", number);
+ if (number == 0) return;
+ set_update(stream);
+}
+
+
+void mm_notify(MAILSTREAM * stream, char *string, long errflg)
+{
+ ast_debug(5, "Entering NOTIFY callback, errflag is %ld, string is %s\n", errflg, string);
+ mm_log (string, errflg);
+}
+
+
+void mm_list(MAILSTREAM * stream, int delim, char *mailbox, long attributes)
+{
+ if (delimiter == '\0') {
+ delimiter = delim;
+ }
+
+ ast_debug(5, "Delimiter set to %c and mailbox %s\n",delim, mailbox);
+ if (attributes & LATT_NOINFERIORS)
+ ast_debug(5, "no inferiors\n");
+ if (attributes & LATT_NOSELECT)
+ ast_debug(5, "no select\n");
+ if (attributes & LATT_MARKED)
+ ast_debug(5, "marked\n");
+ if (attributes & LATT_UNMARKED)
+ ast_debug(5, "unmarked\n");
+}
+
+
+void mm_lsub(MAILSTREAM * stream, int delimiter, char *mailbox, long attributes)
+{
+ ast_debug(5, "Delimiter set to %c and mailbox %s\n",delimiter, mailbox);
+ if (attributes & LATT_NOINFERIORS)
+ ast_debug(5, "no inferiors\n");
+ if (attributes & LATT_NOSELECT)
+ ast_debug(5, "no select\n");
+ if (attributes & LATT_MARKED)
+ ast_debug(5, "marked\n");
+ if (attributes & LATT_UNMARKED)
+ ast_debug(5, "unmarked\n");
+}
+
+
+void mm_status(MAILSTREAM * stream, char *mailbox, MAILSTATUS * status)
+{
+ ast_log(LOG_NOTICE, " Mailbox %s", mailbox);
+ if (status->flags & SA_MESSAGES)
+ ast_log(LOG_NOTICE, ", %lu messages", status->messages);
+ if (status->flags & SA_RECENT)
+ ast_log(LOG_NOTICE, ", %lu recent", status->recent);
+ if (status->flags & SA_UNSEEN)
+ ast_log(LOG_NOTICE, ", %lu unseen", status->unseen);
+ if (status->flags & SA_UIDVALIDITY)
+ ast_log(LOG_NOTICE, ", %lu UID validity", status->uidvalidity);
+ if (status->flags & SA_UIDNEXT)
+ ast_log(LOG_NOTICE, ", %lu next UID", status->uidnext);
+ ast_log(LOG_NOTICE, "\n");
+}
+
+
+void mm_log(char *string, long errflg)
+{
+ switch ((short) errflg) {
+ case NIL:
+ ast_debug(1,"IMAP Info: %s\n", string);
+ break;
+ case PARSE:
+ case WARN:
+ ast_log(LOG_WARNING, "IMAP Warning: %s\n", string);
+ break;
+ case ERROR:
+ ast_log(LOG_ERROR, "IMAP Error: %s\n", string);
+ break;
+ }
+}
+
+
+void mm_dlog(char *string)
+{
+ ast_log(LOG_NOTICE, "%s\n", string);
+}
+
+
+void mm_login(NETMBX * mb, char *user, char *pwd, long trial)
+{
+ struct ast_vm_user *vmu;
+
+ ast_debug(4, "Entering callback mm_login\n");
+
+ ast_copy_string(user, mb->user, MAILTMPLEN);
+
+ /* We should only do this when necessary */
+ if (!ast_strlen_zero(authpassword)) {
+ ast_copy_string(pwd, authpassword, MAILTMPLEN);
+ } else {
+ AST_LIST_TRAVERSE(&users, vmu, list) {
+ if (!strcasecmp(mb->user, vmu->imapuser)) {
+ ast_copy_string(pwd, vmu->imappassword, MAILTMPLEN);
+ break;
+ }
}
- res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- goto yuck;
+ if (!vmu) {
+ if ((vmu = find_user_realtime_imapuser(mb->user))) {
+ ast_copy_string(pwd, vmu->imappassword, MAILTMPLEN);
+ free_user(vmu);
+ }
}
- if (sscanf(rowdata, "%d", &x) != 1)
- ast_log(LOG_WARNING, "Failed to read message count!\n");
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- } else
- ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
-yuck:
- return x;
+ }
}
-static int count_messages(struct ast_vm_user *vmu, char *dir)
+
+void mm_critical(MAILSTREAM * stream)
{
- return last_message_index(vmu, dir) + 1;
}
-static void delete_file(char *sdir, int smsg)
+
+void mm_nocritical(MAILSTREAM * stream)
{
- SQLHSTMT stmt;
- char sql[PATH_MAX];
- char msgnums[20];
- char *argv[] = { sdir, msgnums };
- struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
+}
- struct odbc_obj *obj;
- obj = ast_odbc_request_obj(odbc_database, 0);
- if (obj) {
- snprintf(msgnums, sizeof(msgnums), "%d", smsg);
- snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE dir=? AND msgnum=?", odbc_table);
- stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
- if (!stmt)
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
- else
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- } else
- ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
- return;
+
+long mm_diskerror(MAILSTREAM * stream, long errcode, long serious)
+{
+ kill (getpid (), SIGSTOP);
+ return NIL;
}
-static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext)
+
+void mm_fatal(char *string)
{
- SQLHSTMT stmt;
- char sql[512];
- char msgnums[20];
- char msgnumd[20];
- struct odbc_obj *obj;
- char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums };
- struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
+ ast_log(LOG_ERROR, "IMAP access FATAL error: %s\n", string);
+}
- delete_file(ddir, dmsg);
- obj = ast_odbc_request_obj(odbc_database, 0);
- if (obj) {
- snprintf(msgnums, sizeof(msgnums), "%d", smsg);
- snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
- snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, context, macrocontext, callerid, origtime, duration, recording, mailboxuser, mailboxcontext) SELECT ?,?,context,macrocontext,callerid,origtime,duration,recording,?,? FROM %s WHERE dir=? AND msgnum=?", odbc_table, odbc_table);
- stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
- if (!stmt)
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
- else
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- } else
- ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
- return;
+/* C-client callback to handle quota */
+static void mm_parsequota(MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pquota)
+{
+ struct vm_state *vms;
+ char *mailbox = stream->mailbox, *user;
+ char buf[1024] = "";
+ unsigned long usage = 0, limit = 0;
+
+ while (pquota) {
+ usage = pquota->usage;
+ limit = pquota->limit;
+ pquota = pquota->next;
+ }
+
+ if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))) || !(vms = get_vm_state_by_imapuser(user, 2))) {
+ ast_log(LOG_ERROR, "No state found.\n");
+ return;
+ }
+
+ ast_debug(3, "User %s usage is %lu, limit is %lu\n", user, usage, limit);
+
+ vms->quota_usage = usage;
+ vms->quota_limit = limit;
}
-struct insert_cb_struct {
- char *dir;
- char *msgnum;
- void *recording;
- size_t recordinglen;
- SQLLEN indlen;
- const char *context;
- const char *macrocontext;
- const char *callerid;
- const char *origtime;
- const char *duration;
- char *mailboxuser;
- char *mailboxcontext;
- const char *category;
- char *sql;
-};
+static char *get_header_by_tag(char *header, char *tag, char *buf, size_t len)
+{
+ char *start, *eol_pnt;
+ int taglen;
+
+ if (ast_strlen_zero(header) || ast_strlen_zero(tag))
+ return NULL;
+
+ taglen = strlen(tag) + 1;
+ if (taglen < 1)
+ return NULL;
+
+ if (!(start = strstr(header, tag)))
+ return NULL;
+
+ /* Since we can be called multiple times we should clear our buffer */
+ memset(buf, 0, len);
-static SQLHSTMT insert_cb(struct odbc_obj *obj, void *vd)
+ ast_copy_string(buf, start+taglen, len);
+ if ((eol_pnt = strchr(buf,'\r')) || (eol_pnt = strchr(buf,'\n')))
+ *eol_pnt = '\0';
+ return buf;
+}
+
+static char *get_user_by_mailbox(char *mailbox, char *buf, size_t len)
{
- struct insert_cb_struct *d = vd;
- int res;
- SQLHSTMT stmt;
+ char *start, *quote, *eol_pnt;
- res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
+ if (ast_strlen_zero(mailbox))
return NULL;
- }
- res = SQLPrepare(stmt, (unsigned char *)d->sql, SQL_NTS);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", d->sql);
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ if (!(start = strstr(mailbox, "/user=")))
return NULL;
- }
- SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->dir), 0, (void *)d->dir, 0, NULL);
- SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->msgnum), 0, (void *)d->msgnum, 0, NULL);
- SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, d->recordinglen, 0, (void *)d->recording, 0, &d->indlen);
- SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->context), 0, (void *)d->context, 0, NULL);
- SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->macrocontext), 0, (void *)d->macrocontext, 0, NULL);
- SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->callerid), 0, (void *)d->callerid, 0, NULL);
- SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->origtime), 0, (void *)d->origtime, 0, NULL);
- SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->duration), 0, (void *)d->duration, 0, NULL);
- SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->mailboxuser), 0, (void *)d->mailboxuser, 0, NULL);
- SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->mailboxcontext), 0, (void *)d->mailboxcontext, 0, NULL);
- if (!ast_strlen_zero(d->category)) {
- SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->category), 0, (void *)d->category, 0, NULL);
+ ast_copy_string(buf, start+6, len);
+
+ if (!(quote = strchr(buf, '\"'))) {
+ if (!(eol_pnt = strchr(buf, '/')))
+ eol_pnt = strchr(buf,'}');
+ *eol_pnt = '\0';
+ return buf;
+ } else {
+ eol_pnt = strchr(buf+1,'\"');
+ *eol_pnt = '\0';
+ return buf+1;
}
+}
+
+static struct vm_state *create_vm_state_from_user(struct ast_vm_user *vmu)
+{
+ struct vm_state *vms_p;
- return stmt;
+ if (option_debug > 4)
+ ast_log(LOG_DEBUG,"Adding new vmstate for %s\n",vmu->imapuser);
+ if (!(vms_p = ast_calloc(1, sizeof(*vms_p))))
+ return NULL;
+ ast_copy_string(vms_p->imapuser, vmu->imapuser, sizeof(vms_p->imapuser));
+ ast_copy_string(vms_p->username, vmu->mailbox, sizeof(vms_p->username)); /* save for access from interactive entry point */
+ vms_p->mailstream = NIL; /* save for access from interactive entry point */
+ if (option_debug > 4)
+ ast_log(LOG_DEBUG,"Copied %s to %s\n",vmu->imapuser,vms_p->imapuser);
+ vms_p->updated = 1;
+ /* set mailbox to INBOX! */
+ ast_copy_string(vms_p->curbox, mbox(0), sizeof(vms_p->curbox));
+ init_vm_state(vms_p);
+ vmstate_insert(vms_p);
+ return vms_p;
}
-static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum)
+static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive)
{
- int x = 0;
- int fd = -1;
- void *fdm = MAP_FAILED;
- size_t fdlen = -1;
- SQLHSTMT stmt;
- char sql[PATH_MAX];
- char msgnums[20];
- char fn[PATH_MAX];
- char full_fn[PATH_MAX];
- char fmt[80] = "";
- char *c;
- struct insert_cb_struct d = {
- .dir = dir,
- .msgnum = msgnums,
- .context = "",
- .macrocontext = "",
- .callerid = "",
- .origtime = "",
- .duration = "",
- .mailboxuser = mailboxuser,
- .mailboxcontext = mailboxcontext,
- .category = "",
- .sql = sql
- };
- struct ast_config *cfg = NULL;
- struct odbc_obj *obj;
- struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
+ struct vmstate *vlist = NULL;
- delete_file(dir, msgnum);
- obj = ast_odbc_request_obj(odbc_database, 0);
- if (obj) {
- ast_copy_string(fmt, vmfmts, sizeof(fmt));
- c = strchr(fmt, '|');
- if (c)
- *c = '\0';
- if (!strcasecmp(fmt, "wav49"))
- strcpy(fmt, "WAV");
- snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
- if (msgnum > -1)
- make_file(fn, sizeof(fn), dir, msgnum);
- else
- ast_copy_string(fn, dir, sizeof(fn));
- snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
- cfg = ast_config_load(full_fn, config_flags);
- snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
- fd = open(full_fn, O_RDWR);
- if (fd < 0) {
- ast_log(LOG_WARNING, "Open of sound file '%s' failed: %s\n", full_fn, strerror(errno));
- ast_odbc_release_obj(obj);
- goto yuck;
+ AST_LIST_LOCK(&vmstates);
+ AST_LIST_TRAVERSE(&vmstates, vlist, list) {
+ if (!vlist->vms) {
+ ast_debug(3, "error: vms is NULL for %s\n", user);
+ continue;
}
- if (cfg) {
- d.context = ast_variable_retrieve(cfg, "message", "context");
- if (!d.context) d.context = "";
- d.macrocontext = ast_variable_retrieve(cfg, "message", "macrocontext");
- if (!d.macrocontext) d.macrocontext = "";
- d.callerid = ast_variable_retrieve(cfg, "message", "callerid");
- if (!d.callerid) d.callerid = "";
- d.origtime = ast_variable_retrieve(cfg, "message", "origtime");
- if (!d.origtime) d.origtime = "";
- d.duration = ast_variable_retrieve(cfg, "message", "duration");
- if (!d.duration) d.duration = "";
- d.category = ast_variable_retrieve(cfg, "message", "category");
- if (!d.category) d.category = "";
- }
- fdlen = lseek(fd, 0, SEEK_END);
- lseek(fd, 0, SEEK_SET);
- printf("Length is %zd\n", fdlen);
- fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (fdm == MAP_FAILED) {
- ast_log(LOG_WARNING, "Memory map failed!\n");
- ast_odbc_release_obj(obj);
- goto yuck;
- }
- d.recording = fdm;
- d.recordinglen = d.indlen = fdlen; /* SQL_LEN_DATA_AT_EXEC(fdlen); */
- if (!ast_strlen_zero(d.category))
- snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,category) VALUES (?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
- else
- snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext) VALUES (?,?,?,?,?,?,?,?,?,?)", odbc_table);
- stmt = ast_odbc_prepare_and_execute(obj, insert_cb, &d);
- if (stmt) {
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ if (!vlist->vms->imapuser) {
+ ast_debug(3, "error: imapuser is NULL for %s\n", user);
+ continue;
}
- ast_odbc_release_obj(obj);
- } else
- ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
-yuck:
- if (cfg)
- ast_config_destroy(cfg);
- if (fdm != MAP_FAILED)
- munmap(fdm, fdlen);
- if (fd > -1)
- close(fd);
- return x;
+
+ if (!strcmp(vlist->vms->imapuser, user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
+ AST_LIST_UNLOCK(&vmstates);
+ return vlist->vms;
+ }
+ }
+ AST_LIST_UNLOCK(&vmstates);
+
+ ast_debug(3, "%s not found in vmstates\n", user);
+
+ return NULL;
}
-static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxcontext, char *ddir, int dmsg)
+static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, int interactive)
{
- SQLHSTMT stmt;
- char sql[PATH_MAX];
- char msgnums[20];
- char msgnumd[20];
- struct odbc_obj *obj;
- char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
- struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
- delete_file(ddir, dmsg);
- obj = ast_odbc_request_obj(odbc_database, 0);
- if (obj) {
- snprintf(msgnums, sizeof(msgnums), "%d", smsg);
- snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
- snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?", odbc_table);
- stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
- if (!stmt)
- ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
- else
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- ast_odbc_release_obj(obj);
- } else
- ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
- return;
+ struct vmstate *vlist = NULL;
+
+ AST_LIST_LOCK(&vmstates);
+ AST_LIST_TRAVERSE(&vmstates, vlist, list) {
+ if (!vlist->vms) {
+ ast_debug(3, "error: vms is NULL for %s\n", mailbox);
+ continue;
+ }
+ if (!vlist->vms->username) {
+ ast_debug(3, "error: username is NULL for %s\n", mailbox);
+ continue;
+ }
+
+ ast_debug(3, "comparing mailbox %s (i=%d) to vmstate mailbox %s (i=%d)\n", mailbox, interactive, vlist->vms->username, vlist->vms->interactive);
+
+ if (!strcmp(vlist->vms->username,mailbox) && vlist->vms->interactive == interactive) {
+ ast_debug(3, "Found it!\n");
+ AST_LIST_UNLOCK(&vmstates);
+ return vlist->vms;
+ }
+ }
+ AST_LIST_UNLOCK(&vmstates);
+
+ ast_debug(3, "%s not found in vmstates\n", mailbox);
+
+ return NULL;
}
-#else
-#ifndef IMAP_STORAGE
-static int count_messages(struct ast_vm_user *vmu, char *dir)
+static void vmstate_insert(struct vm_state *vms)
{
- /* Find all .txt files - even if they are not in sequence from 0000 */
+ struct vmstate *v;
+ struct vm_state *altvms;
- int vmcount = 0;
- DIR *vmdir = NULL;
- struct dirent *vment = NULL;
+ /* If interactive, it probably already exists, and we should
+ use the one we already have since it is more up to date.
+ We can compare the username to find the duplicate */
+ if (vms->interactive == 1) {
+ altvms = get_vm_state_by_mailbox(vms->username,0);
+ if (altvms) {
+ ast_debug(3, "Duplicate mailbox %s, copying message info...\n",vms->username);
+ vms->newmessages = altvms->newmessages;
+ vms->oldmessages = altvms->oldmessages;
+ vms->vmArrayIndex = altvms->vmArrayIndex;
+ vms->lastmsg = altvms->lastmsg;
+ vms->curmsg = altvms->curmsg;
+ /* get a pointer to the persistent store */
+ vms->persist_vms = altvms;
+ /* Reuse the mailstream? */
+ vms->mailstream = altvms->mailstream;
+ /* vms->mailstream = NIL; */
+ }
+ }
- if (vm_lock_path(dir))
- return ERROR_LOCK_PATH;
+ if (!(v = ast_calloc(1, sizeof(*v))))
+ return;
+
+ v->vms = vms;
+
+ ast_debug(3, "Inserting vm_state for user:%s, mailbox %s\n",vms->imapuser,vms->username);
- if ((vmdir = opendir(dir))) {
- while ((vment = readdir(vmdir))) {
- if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4))
- vmcount++;
+ AST_LIST_LOCK(&vmstates);
+ AST_LIST_INSERT_TAIL(&vmstates, v, list);
+ AST_LIST_UNLOCK(&vmstates);
+}
+
+static void vmstate_delete(struct vm_state *vms)
+{
+ struct vmstate *vc = NULL;
+ struct vm_state *altvms = NULL;
+
+ /* If interactive, we should copy pertinent info
+ back to the persistent state (to make update immediate) */
+ if (vms->interactive == 1 && (altvms = vms->persist_vms)) {
+ ast_debug(3, "Duplicate mailbox %s, copying message info...\n", vms->username);
+ altvms->newmessages = vms->newmessages;
+ altvms->oldmessages = vms->oldmessages;
+ altvms->updated = 1;
+ }
+
+ ast_debug(3, "Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->username);
+
+ AST_LIST_LOCK(&vmstates);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&vmstates, vc, list) {
+ if (vc->vms == vms) {
+ AST_LIST_REMOVE_CURRENT(list);
+ break;
}
- closedir(vmdir);
}
- ast_unlock_path(dir);
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&vmstates);
- return vmcount;
+ if (vc) {
+ ast_mutex_destroy(&vc->vms->lock);
+ ast_free(vc);
+ }
+ else
+ ast_log(LOG_ERROR, "No vmstate found for user:%s, mailbox %s\n", vms->imapuser, vms->username);
}
-static void rename_file(char *sfn, char *dfn)
+static void set_update(MAILSTREAM * stream)
{
- char stxt[PATH_MAX];
- char dtxt[PATH_MAX];
- ast_filerename(sfn, dfn, NULL);
- snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
- snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
- if (ast_check_realtime("voicemail_data")) {
- ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, NULL);
+ struct vm_state *vms;
+ char *mailbox = stream->mailbox, *user;
+ char buf[1024] = "";
+
+ if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))) || !(vms = get_vm_state_by_imapuser(user, 0))) {
+ if (user && option_debug > 2)
+ ast_log(LOG_WARNING, "User %s mailbox not found for update.\n", user);
+ return;
}
- rename(stxt, dtxt);
+
+ ast_debug(3, "User %s mailbox set for update.\n", user);
+
+ vms->updated = 1; /* Set updated flag since mailbox changed */
}
-#endif
-#ifndef IMAP_STORAGE
-/*! \brief
- * A negative return value indicates an error.
- * \note Should always be called with a lock already set on dir.
- */
-static int last_message_index(struct ast_vm_user *vmu, char *dir)
+static void init_vm_state(struct vm_state *vms)
{
int x;
- unsigned char map[MAXMSGLIMIT] = "";
- DIR *msgdir;
- struct dirent *msgdirent;
- int msgdirint;
-
- /* Reading the entire directory into a file map scales better than
- * doing a stat repeatedly on a predicted sequence. I suspect this
- * is partially due to stat(2) internally doing a readdir(2) itself to
- * find each file. */
- msgdir = opendir(dir);
- while ((msgdirent = readdir(msgdir))) {
- if (sscanf(msgdirent->d_name, "msg%d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
- map[msgdirint] = 1;
- }
- closedir(msgdir);
-
- for (x = 0; x < vmu->maxmsg; x++) {
- if (map[x] == 0)
- break;
+ vms->vmArrayIndex = 0;
+ for (x = 0; x < 256; x++) {
+ vms->msgArray[x] = 0;
}
+ ast_mutex_init(&vms->lock);
+}
- return x - 1;
+static int save_body(BODY *body, struct vm_state *vms, char *section, char *format)
+{
+ char *body_content;
+ char *body_decoded;
+ unsigned long len;
+ unsigned long newlen;
+ char filename[256];
+
+ if (!body || body == NIL)
+ return -1;
+ body_content = mail_fetchbody (vms->mailstream, vms->msgArray[vms->curmsg], section, &len);
+ if (body_content != NIL) {
+ snprintf(filename, sizeof(filename), "%s.%s", vms->fn, format);
+ /* ast_log (LOG_DEBUG,body_content); */
+ body_decoded = rfc822_base64 ((unsigned char *)body_content, len, &newlen);
+ write_file (filename, (char *) body_decoded, newlen);
+ }
+ return 0;
+}
+/*!
+* \brief Get delimiter via mm_list callback
+* \param stream
+*
+* Determines the delimiter character that is used by the underlying IMAP based mail store.
+*/
+static void get_mailbox_delimiter(MAILSTREAM *stream) {
+ char tmp[50];
+ snprintf(tmp, sizeof(tmp), "{%s}", imapserver);
+ mail_list(stream, tmp, "*");
+}
+
+/*!
+* \brief Check Quota for user
+* \param vms a pointer to a vm_state struct, will use the mailstream property of this.
+* \param mailbox the mailbox to check the quota for.
+*
+* Calls imap_getquotaroot, which will populate its results into the vm_state vms input structure.
+*/
+static void check_quota(struct vm_state *vms, char *mailbox) {
+ mail_parameters(NULL, SET_QUOTA, (void *) mm_parsequota);
+ ast_debug(3, "Mailbox name set to: %s, about to check quotas\n", mailbox);
+ if (vms && vms->mailstream != NULL) {
+ imap_getquotaroot(vms->mailstream, mailbox);
+ } else {
+ ast_log(LOG_WARNING, "Mailstream not available for mailbox: %s\n", mailbox);
+ }
}
+#endif /* IMAP_STORAGE */
+
+ /*! \brief Lock file path
+ only return failure if ast_lock_path returns 'timeout',
+ not if the path does not exist or any other reason
+ */
+ static int vm_lock_path(const char *path)
+ {
+ switch (ast_lock_path(path)) {
+ case AST_LOCK_TIMEOUT:
+ return -1;
+ default:
+ return 0;
+ }
+ }
+
+
+#ifdef ODBC_STORAGE
+ struct generic_prepare_struct {
+ char *sql;
+ int argc;
+ char **argv;
+ };
+
+ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
+ {
+ struct generic_prepare_struct *gps = data;
+ int res, i;
+ SQLHSTMT stmt;
+
+ res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
+ return NULL;
+ }
+ res = SQLPrepare(stmt, (unsigned char *)gps->sql, SQL_NTS);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", gps->sql);
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ return NULL;
+ }
+ for (i = 0; i < gps->argc; i++)
+ SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0, NULL);
+
+ return stmt;
+ }
+
+ static int retrieve_file(char *dir, int msgnum)
+ {
+ int x = 0;
+ int res;
+ int fd = -1;
+ size_t fdlen = 0;
+ void *fdm = MAP_FAILED;
+ SQLSMALLINT colcount = 0;
+ SQLHSTMT stmt;
+ char sql[PATH_MAX];
+ char fmt[80] = "";
+ char *c;
+ char coltitle[256];
+ SQLSMALLINT collen;
+ SQLSMALLINT datatype;
+ SQLSMALLINT decimaldigits;
+ SQLSMALLINT nullable;
+ SQLULEN colsize;
+ SQLLEN colsize2;
+ FILE *f = NULL;
+ char rowdata[80];
+ char fn[PATH_MAX];
+ char full_fn[PATH_MAX];
+ char msgnums[80];
+ char *argv[] = { dir, msgnums };
+ struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
+
+ struct odbc_obj *obj;
+ obj = ast_odbc_request_obj(odbc_database, 0);
+ if (obj) {
+ ast_copy_string(fmt, vmfmts, sizeof(fmt));
+ c = strchr(fmt, '|');
+ if (c)
+ *c = '\0';
+ if (!strcasecmp(fmt, "wav49"))
+ strcpy(fmt, "WAV");
+ snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
+ if (msgnum > -1)
+ make_file(fn, sizeof(fn), dir, msgnum);
+ else
+ ast_copy_string(fn, dir, sizeof(fn));
+ snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
+
+ if (!(f = fopen(full_fn, "w+"))) {
+ ast_log(LOG_WARNING, "Failed to open/create '%s'\n", full_fn);
+ goto yuck;
+ }
+
+ snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
+ snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?", odbc_table);
+ stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
+ if (!stmt) {
+ ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ res = SQLFetch(stmt);
+ if (res == SQL_NO_DATA) {
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ } else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, VOICEMAIL_FILE_MODE);
+ if (fd < 0) {
+ ast_log(LOG_WARNING, "Failed to write '%s': %s\n", full_fn, strerror(errno));
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ res = SQLNumResultCols(stmt, &colcount);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ if (f)
+ fprintf(f, "[message]\n");
+ for (x = 0; x < colcount; x++) {
+ rowdata[0] = '\0';
+ collen = sizeof(coltitle);
+ res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
+ &datatype, &colsize, &decimaldigits, &nullable);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ if (!strcasecmp(coltitle, "recording")) {
+ off_t offset;
+ res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
+ fdlen = colsize2;
+ if (fd > -1) {
+ char tmp[1] = "";
+ lseek(fd, fdlen - 1, SEEK_SET);
+ if (write(fd, tmp, 1) != 1) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+ /* Read out in small chunks */
+ for (offset = 0; offset < colsize2; offset += CHUNKSIZE) {
+ if ((fdm = mmap(NULL, CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
+ ast_log(LOG_WARNING, "Could not mmap the output file: %s (%d)\n", strerror(errno), errno);
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ } else {
+ res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, CHUNKSIZE, NULL);
+ munmap(fdm, CHUNKSIZE);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
+ unlink(full_fn);
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ }
+ }
+ truncate(full_fn, fdlen);
+ }
+ } else {
+ SQLLEN ind;
+ res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &ind);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ SQLINTEGER nativeerror = 0;
+ SQLSMALLINT diagbytes = 0;
+ unsigned char state[10], diagnostic[256];
+ SQLGetDiagRec(SQL_HANDLE_STMT, stmt, 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
+ ast_log(LOG_WARNING, "SQL Get Data error: %s: %s!\n[%s]\n\n", state, diagnostic, sql);
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ if (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir") && f)
+ fprintf(f, "%s=%s\n", coltitle, rowdata);
+ }
+ }
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ } else
+ ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+ yuck:
+ if (f)
+ fclose(f);
+ if (fd > -1)
+ close(fd);
+ return x - 1;
+ }
+
+ /*!
+ * \brief Determines the highest message number in use for a given user and mailbox folder.
+ * \param vmu
+ * \param dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause.
+ *
+ * This method is used when mailboxes are stored in an ODBC back end.
+ * Typical use to set the msgnum would be to take the value returned from this method and add one to it.
+ *
+ * \return the value of zero or greaterto indicate the last message index in use, -1 to indicate none.
+ */
+ static int last_message_index(struct ast_vm_user *vmu, char *dir)
+ {
+ int x = 0;
+ int res;
+ SQLHSTMT stmt;
+ char sql[PATH_MAX];
+ char rowdata[20];
+ char *argv[] = { dir };
+ struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
+
+ struct odbc_obj *obj;
+ obj = ast_odbc_request_obj(odbc_database, 0);
+ if (obj) {
+ snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table);
+ stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
+ if (!stmt) {
+ ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ res = SQLFetch(stmt);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ if (sscanf(rowdata, "%d", &x) != 1)
+ ast_log(LOG_WARNING, "Failed to read message count!\n");
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ } else
+ ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+ yuck:
+ return x - 1;
+ }
+
+ static int message_exists(char *dir, int msgnum)
+ {
+ int x = 0;
+ int res;
+ SQLHSTMT stmt;
+ char sql[PATH_MAX];
+ char rowdata[20];
+ char msgnums[20];
+ char *argv[] = { dir, msgnums };
+ struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
+
+ struct odbc_obj *obj;
+ obj = ast_odbc_request_obj(odbc_database, 0);
+ if (obj) {
+ snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
+ snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?", odbc_table);
+ stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
+ if (!stmt) {
+ ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ res = SQLFetch(stmt);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ if (sscanf(rowdata, "%d", &x) != 1)
+ ast_log(LOG_WARNING, "Failed to read message count!\n");
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ } else
+ ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+ yuck:
+ return x;
+ }
+
+ static int count_messages(struct ast_vm_user *vmu, char *dir)
+ {
+ return last_message_index(vmu, dir) + 1;
+ }
+
+ static void delete_file(char *sdir, int smsg)
+ {
+ SQLHSTMT stmt;
+ char sql[PATH_MAX];
+ char msgnums[20];
+ char *argv[] = { sdir, msgnums };
+ struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
+
+ struct odbc_obj *obj;
+ obj = ast_odbc_request_obj(odbc_database, 0);
+ if (obj) {
+ snprintf(msgnums, sizeof(msgnums), "%d", smsg);
+ snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE dir=? AND msgnum=?", odbc_table);
+ stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
+ if (!stmt)
+ ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
+ else
+ SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ } else
+ ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+ return;
+ }
+
+ static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext)
+ {
+ SQLHSTMT stmt;
+ char sql[512];
+ char msgnums[20];
+ char msgnumd[20];
+ struct odbc_obj *obj;
+ char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums };
+ struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
+
+ delete_file(ddir, dmsg);
+ obj = ast_odbc_request_obj(odbc_database, 0);
+ if (obj) {
+ snprintf(msgnums, sizeof(msgnums), "%d", smsg);
+ snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
+ snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, context, macrocontext, callerid, origtime, duration, recording, mailboxuser, mailboxcontext) SELECT ?,?,context,macrocontext,callerid,origtime,duration,recording,?,? FROM %s WHERE dir=? AND msgnum=?", odbc_table, odbc_table);
+ stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
+ if (!stmt)
+ ast_log(LOG_WARNING, "SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
+ else
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ } else
+ ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+ return;
+ }
+
+ struct insert_cb_struct {
+ char *dir;
+ char *msgnum;
+ void *recording;
+ size_t recordinglen;
+ SQLLEN indlen;
+ const char *context;
+ const char *macrocontext;
+ const char *callerid;
+ const char *origtime;
+ const char *duration;
+ char *mailboxuser;
+ char *mailboxcontext;
+ const char *category;
+ char *sql;
+ };
+
+ static SQLHSTMT insert_cb(struct odbc_obj *obj, void *vd)
+ {
+ struct insert_cb_struct *d = vd;
+ int res;
+ SQLHSTMT stmt;
+
+ res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
+ return NULL;
+ }
+
+ res = SQLPrepare(stmt, (unsigned char *)d->sql, SQL_NTS);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", d->sql);
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ return NULL;
+ }
+
+ SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->dir), 0, (void *)d->dir, 0, NULL);
+ SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->msgnum), 0, (void *)d->msgnum, 0, NULL);
+ SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, d->recordinglen, 0, (void *)d->recording, 0, &d->indlen);
+ SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->context), 0, (void *)d->context, 0, NULL);
+ SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->macrocontext), 0, (void *)d->macrocontext, 0, NULL);
+ SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->callerid), 0, (void *)d->callerid, 0, NULL);
+ SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->origtime), 0, (void *)d->origtime, 0, NULL);
+ SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->duration), 0, (void *)d->duration, 0, NULL);
+ SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->mailboxuser), 0, (void *)d->mailboxuser, 0, NULL);
+ SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->mailboxcontext), 0, (void *)d->mailboxcontext, 0, NULL);
+ if (!ast_strlen_zero(d->category)) {
+ SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(d->category), 0, (void *)d->category, 0, NULL);
+ }
+
+ return stmt;
+ }
+
+ static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum)
+ {
+ int x = 0;
+ int fd = -1;
+ void *fdm = MAP_FAILED;
+ size_t fdlen = -1;
+ SQLHSTMT stmt;
+ char sql[PATH_MAX];
+ char msgnums[20];
+ char fn[PATH_MAX];
+ char full_fn[PATH_MAX];
+ char fmt[80] = "";
+ char *c;
+ struct insert_cb_struct d = {
+ .dir = dir,
+ .msgnum = msgnums,
+ .context = "",
+ .macrocontext = "",
+ .callerid = "",
+ .origtime = "",
+ .duration = "",
+ .mailboxuser = mailboxuser,
+ .mailboxcontext = mailboxcontext,
+ .category = "",
+ .sql = sql
+ };
+ struct ast_config *cfg = NULL;
+ struct odbc_obj *obj;
+ struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
+
+ delete_file(dir, msgnum);
+ obj = ast_odbc_request_obj(odbc_database, 0);
+ if (obj) {
+ ast_copy_string(fmt, vmfmts, sizeof(fmt));
+ c = strchr(fmt, '|');
+ if (c)
+ *c = '\0';
+ if (!strcasecmp(fmt, "wav49"))
+ strcpy(fmt, "WAV");
+ snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
+ if (msgnum > -1)
+ make_file(fn, sizeof(fn), dir, msgnum);
+ else
+ ast_copy_string(fn, dir, sizeof(fn));
+ snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
+ cfg = ast_config_load(full_fn, config_flags);
+ snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
+ fd = open(full_fn, O_RDWR);
+ if (fd < 0) {
+ ast_log(LOG_WARNING, "Open of sound file '%s' failed: %s\n", full_fn, strerror(errno));
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ if (cfg) {
+ d.context = ast_variable_retrieve(cfg, "message", "context");
+ if (!d.context) d.context = "";
+ d.macrocontext = ast_variable_retrieve(cfg, "message", "macrocontext");
+ if (!d.macrocontext) d.macrocontext = "";
+ d.callerid = ast_variable_retrieve(cfg, "message", "callerid");
+ if (!d.callerid) d.callerid = "";
+ d.origtime = ast_variable_retrieve(cfg, "message", "origtime");
+ if (!d.origtime) d.origtime = "";
+ d.duration = ast_variable_retrieve(cfg, "message", "duration");
+ if (!d.duration) d.duration = "";
+ d.category = ast_variable_retrieve(cfg, "message", "category");
+ if (!d.category) d.category = "";
+ }
+ fdlen = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+ printf("Length is %zd\n", fdlen);
+ fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (fdm == MAP_FAILED) {
+ ast_log(LOG_WARNING, "Memory map failed!\n");
+ ast_odbc_release_obj(obj);
+ goto yuck;
+ }
+ d.recording = fdm;
+ d.recordinglen = d.indlen = fdlen; /* SQL_LEN_DATA_AT_EXEC(fdlen); */
+ if (!ast_strlen_zero(d.category))
+ snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,category) VALUES (?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
+ else
+ snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext) VALUES (?,?,?,?,?,?,?,?,?,?)", odbc_table);
+ stmt = ast_odbc_prepare_and_execute(obj, insert_cb, &d);
+ if (stmt) {
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ }
+ ast_odbc_release_obj(obj);
+ } else
+ ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+ yuck:
+ if (cfg)
+ ast_config_destroy(cfg);
+ if (fdm != MAP_FAILED)
+ munmap(fdm, fdlen);
+ if (fd > -1)
+ close(fd);
+ return x;
+ }
+
+ static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxcontext, char *ddir, int dmsg)
+ {
+ SQLHSTMT stmt;
+ char sql[PATH_MAX];
+ char msgnums[20];
+ char msgnumd[20];
+ struct odbc_obj *obj;
+ char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
+ struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
+
+ delete_file(ddir, dmsg);
+ obj = ast_odbc_request_obj(odbc_database, 0);
+ if (obj) {
+ snprintf(msgnums, sizeof(msgnums), "%d", smsg);
+ snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
+ snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?", odbc_table);
+ stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
+ if (!stmt)
+ ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
+ else
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ } else
+ ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+ return;
+ }
+
+#else
+#ifndef IMAP_STORAGE
+ static int count_messages(struct ast_vm_user *vmu, char *dir)
+ {
+ /* Find all .txt files - even if they are not in sequence from 0000 */
+
+ int vmcount = 0;
+ DIR *vmdir = NULL;
+ struct dirent *vment = NULL;
+
+ if (vm_lock_path(dir))
+ return ERROR_LOCK_PATH;
+
+ if ((vmdir = opendir(dir))) {
+ while ((vment = readdir(vmdir))) {
+ if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4))
+ vmcount++;
+ }
+ closedir(vmdir);
+ }
+ ast_unlock_path(dir);
+
+ return vmcount;
+ }
+
+ static void rename_file(char *sfn, char *dfn)
+ {
+ char stxt[PATH_MAX];
+ char dtxt[PATH_MAX];
+ ast_filerename(sfn, dfn, NULL);
+ snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
+ snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
+ if (ast_check_realtime("voicemail_data")) {
+ ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, NULL);
+ }
+ rename(stxt, dtxt);
+ }
+#endif
+
+#ifndef IMAP_STORAGE
+ /*! \brief
+ * A negative return value indicates an error.
+ * \note Should always be called with a lock already set on dir.
+ */
+ static int last_message_index(struct ast_vm_user *vmu, char *dir)
+ {
+ int x;
+ unsigned char map[MAXMSGLIMIT] = "";
+ DIR *msgdir;
+ struct dirent *msgdirent;
+ int msgdirint;
+
+ /* Reading the entire directory into a file map scales better than
+ * doing a stat repeatedly on a predicted sequence. I suspect this
+ * is partially due to stat(2) internally doing a readdir(2) itself to
+ * find each file. */
+ msgdir = opendir(dir);
+ while ((msgdirent = readdir(msgdir))) {
+ if (sscanf(msgdirent->d_name, "msg%d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
+ map[msgdirint] = 1;
+ }
+ closedir(msgdir);
+
+ for (x = 0; x < vmu->maxmsg; x++) {
+ if (map[x] == 0)
+ break;
+ }
+
+ return x - 1;
+ }
+#if (defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
+ /*!
+ * \brief Removes a voicemail message file.
+ * \param dir the path to the message file.
+ * \param msgnum the unique number for the message within the mailbox.
+ *
+ * Removes the message content file and the information file.
+ * This method is used by the DISPOSE macro when mailboxes are stored in an ODBC back end.
+ * Typical use is to clean up after a RETRIEVE operation.
+ * Note that this does not remove the message from the mailbox folders, to do that we would use delete_file().
+ * \return zero on success, -1 on error.
+ */
+ static int remove_file(char *dir, int msgnum)
+ {
+ char fn[PATH_MAX];
+ char full_fn[PATH_MAX];
+ char msgnums[80];
+
+ if (msgnum > -1) {
+ snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
+ make_file(fn, sizeof(fn), dir, msgnum);
+ } else
+ ast_copy_string(fn, dir, sizeof(fn));
+ ast_filedelete(fn, NULL);
+ snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
+ unlink(full_fn);
+ return 0;
+ }
+#endif
+
#endif /* #ifndef IMAP_STORAGE */
#endif /* #else of #ifdef ODBC_STORAGE */
@@ -1813,6 +3089,15 @@ static void copy_plain_file(char *frompath, char *topath)
ast_variables_destroy(var);
}
+#if (!defined(ODBC_STORAGE) && !defined(IMAP_STORAGE))
+/*!
+* \brief Removes the voicemail sound and information file.
+* \param file The path to the sound file. This will be the the folder and message index, without the extension.
+*
+* This is used by the DELETE macro when voicemails are stored on the file system.
+*
+* \return zero on success, -1 on error.
+*/
static int vm_delete(char *file)
{
char *txt;
@@ -1821,8 +3106,8 @@ static int vm_delete(char *file)
txtsize = (strlen(file) + 5) * sizeof(char);
txt = alloca(txtsize);
/* Sprintf here would safe because we alloca'd exactly the right length,
- * but trying to eliminate all sprintf's anyhow
- */
+ * but trying to eliminate all sprintf's anyhow
+ */
if (ast_check_realtime("voicemail_data")) {
ast_destroy_realtime("voicemail_data", "filename", file, NULL);
}
@@ -1830,7 +3115,7 @@ static int vm_delete(char *file)
unlink(txt);
return ast_filedelete(file, NULL);
}
-
+#endif
static int inbuf(struct baseio *bio, FILE *fi)
{
int l;
@@ -1973,9 +3258,9 @@ static char *quote(const char *from, char *to, size_t len)
}
/*! \brief
- * fill in *tm for current time according to the proper timezone, if any.
- * Return tm so it can be used as a function argument.
- */
+* fill in *tm for current time according to the proper timezone, if any.
+* Return tm so it can be used as a function argument.
+*/
static const struct ast_tm *vmu_tm(const struct ast_vm_user *vmu, struct ast_tm *tm)
{
const struct vm_zone *z = NULL;
@@ -1995,22 +3280,6 @@ static const struct ast_tm *vmu_tm(const struct ast_vm_user *vmu, struct ast_tm
return tm;
}
-/*! \brief same as mkstemp, but return a FILE * */
-static FILE *vm_mkftemp(char *template)
-{
- FILE *p = NULL;
- int pfd = mkstemp(template);
- chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
- if (pfd > -1) {
- p = fdopen(pfd, "w+");
- if (!p) {
- close(pfd);
- pfd = -1;
- }
- }
- return p;
-}
-
static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap)
{
char date[256];
@@ -2113,6 +3382,8 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
if (!ast_strlen_zero(category)) {
fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
+ } else {
+ fprintf(p, "X-Asterisk-VM-Category: " ENDL);
}
fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
@@ -2219,7 +3490,7 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *c
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));
/* Make a temporary file instead of piping directly to sendmail, in case the mail
- command hangs */
+ command hangs */
if ((p = vm_mkftemp(tmp)) == NULL) {
ast_log(LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
return -1;
@@ -2377,77 +3648,11 @@ static int invent_message(struct ast_channel *chan, struct ast_vm_user *vmu, cha
return res;
}
-static void free_user(struct ast_vm_user *vmu)
-{
- if (!ast_test_flag(vmu, VM_ALLOCED))
- return;
-
- ast_free(vmu);
-}
-
static void free_zone(struct vm_zone *z)
{
ast_free(z);
}
-static const char *mbox(int id)
-{
- static const char *msgs[] = {
-#ifdef IMAP_STORAGE
- imapfolder,
-#else
- "INBOX",
-#endif
- "Old",
- "Work",
- "Family",
- "Friends",
- "Cust1",
- "Cust2",
- "Cust3",
- "Cust4",
- "Cust5",
- "Deleted",
- };
- return (id >= 0 && id < (sizeof(msgs) / sizeof(msgs[0]))) ? msgs[id] : "tmp";
-}
-#ifdef IMAP_STORAGE
-static int folder_int(const char *folder)
-{
- /* assume a NULL folder means INBOX */
- if (!folder)
- return 0;
-#ifdef IMAP_STORAGE
- if (!strcasecmp(folder, imapfolder))
-#else
- if (!strcasecmp(folder, "INBOX"))
-#endif
- return 0;
- else if (!strcasecmp(folder, "Old"))
- return 1;
- else if (!strcasecmp(folder, "Work"))
- return 2;
- else if (!strcasecmp(folder, "Family"))
- return 3;
- else if (!strcasecmp(folder, "Friends"))
- return 4;
- else if (!strcasecmp(folder, "Cust1"))
- return 5;
- else if (!strcasecmp(folder, "Cust2"))
- return 6;
- else if (!strcasecmp(folder, "Cust3"))
- return 7;
- else if (!strcasecmp(folder, "Cust4"))
- return 8;
- else if (!strcasecmp(folder, "Cust5"))
- return 9;
- else if (!strcasecmp(folder, "Deleted"))
- return 10;
- else /* assume they meant INBOX if folder is not found otherwise */
- return 0;
-}
-#endif
-
#ifdef ODBC_STORAGE
/*! XXX \todo Fix this function to support multiple mailboxes in the intput string */
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
@@ -2600,2715 +3805,2012 @@ static int has_voicemail(const char *mailbox, const char *folder)
#elif defined(IMAP_STORAGE)
-static int imap_store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum, struct ast_channel *chan, struct ast_vm_user *vmu, char *fmt, int duration, struct vm_state *vms)
-{
- char *myserveremail = serveremail;
- char fn[PATH_MAX];
- char mailbox[256];
- char *stringp;
- FILE *p = NULL;
- char tmp[80] = "/tmp/astmail-XXXXXX";
- long len;
- void *buf;
- int tempcopy = 0;
- STRING str;
-
- /* Attach only the first format */
- fmt = ast_strdupa(fmt);
- stringp = fmt;
- strsep(&stringp, "|");
+#endif
+#ifndef IMAP_STORAGE
+ /* copy message only used by file storage */
+ 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 *dir)
+ {
+ char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
+ const char *frombox = mbox(imbox);
+ int recipmsgnum;
- if (!ast_strlen_zero(vmu->serveremail))
- myserveremail = vmu->serveremail;
+ ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
- if (msgnum > -1)
- make_file(fn, sizeof(fn), dir, msgnum);
- else
- ast_copy_string (fn, dir, sizeof(fn));
-
- if (ast_strlen_zero(vmu->email)) {
- /* We need the vmu->email to be set when we call make_email_file, but
- * if we keep it set, a duplicate e-mail will be created. So at the end
- * of this function, we will revert back to an empty string if tempcopy
- * is 1.
- */
- ast_copy_string(vmu->email, vmu->imapuser, sizeof(vmu->email));
- tempcopy = 1;
- }
+ create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
+
+ if (!dir)
+ make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
+ else
+ ast_copy_string(fromdir, dir, sizeof(fromdir));
- if (!strcmp(fmt, "wav49"))
- fmt = "WAV";
- ast_debug(3, "Storing file '%s', format '%s'\n", fn, fmt);
+ make_file(frompath, sizeof(frompath), fromdir, msgnum);
+ make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
- /* Make a temporary file instead of piping directly to sendmail, in case the mail
- command hangs. */
- if (!(p = vm_mkftemp(tmp))) {
- ast_log(LOG_WARNING, "Unable to store '%s' (can't create temporary file)\n", fn);
- if (tempcopy)
- *(vmu->email) = '\0';
- return -1;
- }
+ if (vm_lock_path(todir))
+ return ERROR_LOCK_PATH;
- if (msgnum < 0 && imapgreetings) {
- init_mailstream(vms, GREETINGS_FOLDER);
- imap_delete_old_greeting(fn, vms);
+ recipmsgnum = last_message_index(recip, todir) + 1;
+ if (recipmsgnum < recip->maxmsg) {
+ make_file(topath, sizeof(topath), todir, recipmsgnum);
+ COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
+ } else {
+ ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
+ }
+ ast_unlock_path(todir);
+ notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
+
+ return 0;
}
-
- make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), fn, fmt, duration, 1, chan, NULL, 1);
- /* read mail file to memory */
- len = ftell(p);
- rewind(p);
- if (!(buf = ast_malloc(len + 1))) {
- ast_log(LOG_ERROR, "Can't allocate %ld bytes to read message\n", len + 1);
- fclose(p);
- if (tempcopy)
- *(vmu->email) = '\0';
- return -1;
+#endif
+#if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
+ static int messagecount(const char *context, const char *mailbox, const char *folder)
+ {
+ return __has_voicemail(context, mailbox, folder, 0);
}
- fread(buf, len, 1, p);
- ((char *)buf)[len] = '\0';
- INIT(&str, mail_string, buf, len);
- init_mailstream(vms, NEW_FOLDER);
- imap_mailbox_name(mailbox, sizeof(mailbox), vms, NEW_FOLDER, 1);
- if (!mail_append(vms->mailstream, mailbox, &str))
- ast_log(LOG_ERROR, "Error while sending the message to %s\n", mailbox);
- fclose(p);
- unlink(tmp);
- ast_free(buf);
- ast_debug(3, "%s stored\n", fn);
-
- if (tempcopy)
- *(vmu->email) = '\0';
-
- return 0;
-}
-static int messagecount(const char *context, const char *mailbox, const char *folder)
-{
- SEARCHPGM *pgm;
- SEARCHHEADER *hdr;
+ static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
+ {
+ DIR *dir;
+ struct dirent *de;
+ char fn[256];
+ int ret = 0;
- struct ast_vm_user *vmu, vmus;
- struct vm_state *vms_p;
- int ret = 0;
- int fold = folder_int(folder);
-
- if (ast_strlen_zero(mailbox))
- return 0;
+ /* If no mailbox, return immediately */
+ if (ast_strlen_zero(mailbox))
+ return 0;
- /* We have to get the user before we can open the stream! */
- /* ast_log(LOG_DEBUG, "Before find_user, context is %s and mailbox is %s\n", context, mailbox); */
- vmu = find_user(&vmus, context, mailbox);
- if (!vmu) {
- ast_log(LOG_ERROR, "Couldn't find mailbox %s in context %s\n", mailbox, context);
- return -1;
- } else {
- /* No IMAP account available */
- if (vmu->imapuser[0] == '\0') {
- ast_log(LOG_WARNING, "IMAP user not set for mailbox %s\n", vmu->mailbox);
- return -1;
- }
- }
-
- /* No IMAP account available */
- if (vmu->imapuser[0] == '\0') {
- ast_log(LOG_WARNING, "IMAP user not set for mailbox %s\n", vmu->mailbox);
- free_user(vmu);
- return -1;
- }
+ if (ast_strlen_zero(folder))
+ folder = "INBOX";
+ if (ast_strlen_zero(context))
+ context = "default";
- /* check if someone is accessing this box right now... */
- vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1);
- if (!vms_p) {
- vms_p = get_vm_state_by_mailbox(mailbox, 1);
- }
- if (vms_p) {
- ast_debug(3, "Returning before search - user is logged in\n");
- if (fold == 0) { /* INBOX */
- return vms_p->newmessages;
- }
- if (fold == 1) { /* Old messages */
- return vms_p->oldmessages;
- }
- }
+ snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
- /* add one if not there... */
- vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0);
- if (!vms_p) {
- vms_p = get_vm_state_by_mailbox(mailbox, 0);
- }
+ if (!(dir = opendir(fn)))
+ return 0;
- if (!vms_p) {
- ast_debug(3, "Adding new vmstate for %s\n", vmu->imapuser);
- if (!(vms_p = ast_calloc(1, sizeof(*vms_p)))) {
- return -1;
- }
- ast_copy_string(vms_p->imapuser, vmu->imapuser, sizeof(vms_p->imapuser));
- ast_copy_string(vms_p->username, mailbox, sizeof(vms_p->username)); /* save for access from interactive entry point */
- vms_p->mailstream = NIL; /* save for access from interactive entry point */
- ast_debug(3, "Copied %s to %s\n", vmu->imapuser, vms_p->imapuser);
- vms_p->updated = 1;
- /* set mailbox to INBOX! */
- ast_copy_string(vms_p->curbox, mbox(fold), sizeof(vms_p->curbox));
- init_vm_state(vms_p);
- vmstate_insert(vms_p);
- }
- ret = init_mailstream(vms_p, fold);
- if (!vms_p->mailstream) {
- ast_log(LOG_ERROR, "Houston we have a problem - IMAP mailstream is NULL\n");
- return -1;
- }
- if (ret == 0) {
- pgm = mail_newsearchpgm ();
- hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailbox);
- pgm->header = hdr;
- if (fold != 1) {
- pgm->unseen = 1;
- pgm->seen = 0;
- }
- /* In the special case where fold is 1 (old messages) we have to do things a bit
- * differently. Old messages are stored in the INBOX but are marked as "seen"
- */
- else {
- pgm->unseen = 0;
- pgm->seen = 1;
+ while ((de = readdir(dir))) {
+ if (!strncasecmp(de->d_name, "msg", 3)) {
+ if (shortcircuit) {
+ ret = 1;
+ break;
+ } else if (!strncasecmp(de->d_name + 8, "txt", 3))
+ ret++;
+ }
}
- pgm->undeleted = 1;
- pgm->deleted = 0;
- vms_p->vmArrayIndex = 0;
- mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
- if (fold == 0)
- vms_p->newmessages = vms_p->vmArrayIndex;
- if (fold == 1)
- vms_p->oldmessages = vms_p->vmArrayIndex;
- /* Freeing the searchpgm also frees the searchhdr */
- mail_free_searchpgm(&pgm);
- vms_p->updated = 0;
- return vms_p->vmArrayIndex;
- } else {
- mail_ping(vms_p->mailstream);
- }
- return 0;
-}
-static int inboxcount(const char *mailbox_context, int *newmsgs, int *oldmsgs)
-{
- char tmp[PATH_MAX] = "";
- char *mailboxnc;
- char *context;
- char *mb;
- char *cur;
- if (newmsgs)
- *newmsgs = 0;
- if (oldmsgs)
- *oldmsgs = 0;
+ closedir(dir);
- ast_debug(3, "Mailbox is set to %s\n", mailbox_context);
- /* If no mailbox, return immediately */
- if (ast_strlen_zero(mailbox_context))
- return 0;
-
- ast_copy_string(tmp, mailbox_context, sizeof(tmp));
- context = strchr(tmp, '@');
- if (strchr(mailbox_context, ',')) {
- int tmpnew, tmpold;
- ast_copy_string(tmp, mailbox_context, sizeof(tmp));
- mb = tmp;
- while ((cur = strsep(&mb, ", "))) {
- if (!ast_strlen_zero(cur)) {
- if (inboxcount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
- return -1;
- else {
- if (newmsgs)
- *newmsgs += tmpnew;
- if (oldmsgs)
- *oldmsgs += tmpold;
- }
- }
- }
- return 0;
+ return ret;
}
- if (context) {
- *context = '\0';
- mailboxnc = tmp;
- context++;
- } else {
- context = "default";
- mailboxnc = (char *)mailbox_context;
- }
- if (newmsgs) {
- if ((*newmsgs = messagecount(context, mailboxnc, imapfolder)) < 0)
- return -1;
- }
- if (oldmsgs) {
- if ((*oldmsgs = messagecount(context, mailboxnc, "Old")) < 0)
- return -1;
- }
- return 0;
-}
-
-static int has_voicemail(const char *mailbox, const char *folder)
-{
- char tmp[256], *tmp2, *mbox, *context;
- ast_copy_string(tmp, mailbox, sizeof(tmp));
- tmp2 = tmp;
- if (strchr(tmp2, ',')) {
+
+ static int has_voicemail(const char *mailbox, const char *folder)
+ {
+ char tmp[256], *tmp2 = tmp, *mbox, *context;
+ ast_copy_string(tmp, mailbox, sizeof(tmp));
while ((mbox = strsep(&tmp2, ","))) {
- if (!ast_strlen_zero(mbox)) {
- if (has_voicemail(mbox, folder))
- return 1;
- }
+ if ((context = strchr(mbox, '@')))
+ *context++ = '\0';
+ else
+ context = "default";
+ if (__has_voicemail(context, mbox, folder, 1))
+ return 1;
}
- }
- if ((context= strchr(tmp, '@')))
- *context++ = '\0';
- else
- context = "default";
- return messagecount(context, tmp, folder) ? 1 : 0;
-}
-
-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 *dir)
-{
- struct vm_state *sendvms = NULL, *destvms = NULL;
- char messagestring[10]; /* I guess this could be a problem if someone has more than 999,999,999 messages... */
- if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
- ast_log(LOG_ERROR, "Couldn't get vm_state for originator's mailbox!!\n");
- return -1;
- }
- if (!(destvms = get_vm_state_by_imapuser(recip->imapuser, 0))) {
- ast_log(LOG_ERROR, "Couldn't get vm_state for destination mailbox!\n");
- return -1;
- }
- snprintf(messagestring, sizeof(messagestring), "%ld", sendvms->msgArray[msgnum]);
- if ((mail_copy(sendvms->mailstream, messagestring, (char *) mbox(imbox)) == T))
return 0;
- ast_log(LOG_WARNING, "Unable to copy message from mailbox %s to mailbox %s\n", vmu->mailbox, recip->mailbox);
- return -1;
-}
-
-#endif
-#ifndef IMAP_STORAGE
-/* copy message only used by file storage */
-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 *dir)
-{
- char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
- const char *frombox = mbox(imbox);
- int recipmsgnum;
-
- ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
-
- create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
-
- if (!dir)
- make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
- else
- ast_copy_string(fromdir, dir, sizeof(fromdir));
-
- make_file(frompath, sizeof(frompath), fromdir, msgnum);
- make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
-
- if (vm_lock_path(todir))
- return ERROR_LOCK_PATH;
-
- recipmsgnum = last_message_index(recip, todir) + 1;
- if (recipmsgnum < recip->maxmsg) {
- make_file(topath, sizeof(topath), todir, recipmsgnum);
- COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
- } else {
- ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
}
- ast_unlock_path(todir);
- notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
-
- return 0;
-}
-#endif
-#if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
-static int messagecount(const char *context, const char *mailbox, const char *folder)
-{
- return __has_voicemail(context, mailbox, folder, 0);
-}
-static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
-{
- DIR *dir;
- struct dirent *de;
- char fn[256];
- int ret = 0;
+ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
+ {
+ char tmp[256];
+ char *context;
- /* If no mailbox, return immediately */
- if (ast_strlen_zero(mailbox))
- return 0;
+ /* If no mailbox, return immediately */
+ if (ast_strlen_zero(mailbox))
+ return 0;
- if (ast_strlen_zero(folder))
- folder = "INBOX";
- if (ast_strlen_zero(context))
- context = "default";
+ if (newmsgs)
+ *newmsgs = 0;
+ if (oldmsgs)
+ *oldmsgs = 0;
- snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
+ if (strchr(mailbox, ',')) {
+ int tmpnew, tmpold;
+ char *mb, *cur;
- if (!(dir = opendir(fn)))
- return 0;
-
- while ((de = readdir(dir))) {
- if (!strncasecmp(de->d_name, "msg", 3)) {
- if (shortcircuit) {
- ret = 1;
- break;
- } else if (!strncasecmp(de->d_name + 8, "txt", 3))
- ret++;
+ ast_copy_string(tmp, mailbox, sizeof(tmp));
+ mb = tmp;
+ while ((cur = strsep(&mb, ", "))) {
+ if (!ast_strlen_zero(cur)) {
+ if (inboxcount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
+ return -1;
+ else {
+ if (newmsgs)
+ *newmsgs += tmpnew;
+ if (oldmsgs)
+ *oldmsgs += tmpold;
+ }
+ }
+ }
+ return 0;
}
- }
-
- closedir(dir);
-
- return ret;
-}
-
-static int has_voicemail(const char *mailbox, const char *folder)
-{
- char tmp[256], *tmp2 = tmp, *mbox, *context;
- ast_copy_string(tmp, mailbox, sizeof(tmp));
- while ((mbox = strsep(&tmp2, ","))) {
- if ((context = strchr(mbox, '@')))
+ ast_copy_string(tmp, mailbox, sizeof(tmp));
+
+ if ((context = strchr(tmp, '@')))
*context++ = '\0';
else
context = "default";
- if (__has_voicemail(context, mbox, folder, 1))
- return 1;
- }
- return 0;
-}
+ if (newmsgs)
+ *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
+ if (oldmsgs)
+ *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
-static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
-{
- char tmp[256];
- char *context;
-
- /* If no mailbox, return immediately */
- if (ast_strlen_zero(mailbox))
- return 0;
-
- if (newmsgs)
- *newmsgs = 0;
- if (oldmsgs)
- *oldmsgs = 0;
-
- if (strchr(mailbox, ',')) {
- int tmpnew, tmpold;
- char *mb, *cur;
-
- ast_copy_string(tmp, mailbox, sizeof(tmp));
- mb = tmp;
- while ((cur = strsep(&mb, ", "))) {
- if (!ast_strlen_zero(cur)) {
- if (inboxcount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
- return -1;
- else {
- if (newmsgs)
- *newmsgs += tmpnew;
- if (oldmsgs)
- *oldmsgs += tmpold;
- }
- }
- }
return 0;
}
- ast_copy_string(tmp, mailbox, sizeof(tmp));
-
- if ((context = strchr(tmp, '@')))
- *context++ = '\0';
- else
- context = "default";
-
- if (newmsgs)
- *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
- if (oldmsgs)
- *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
-
- return 0;
-}
-
#endif
-static void run_externnotify(char *context, char *extension)
-{
- char arguments[255];
- char ext_context[256] = "";
- int newvoicemails = 0, oldvoicemails = 0;
- struct ast_smdi_mwi_message *mwi_msg;
-
- if (!ast_strlen_zero(context))
- snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
- else
- ast_copy_string(ext_context, extension, sizeof(ext_context));
+ static void run_externnotify(char *context, char *extension)
+ {
+ char arguments[255];
+ char ext_context[256] = "";
+ int newvoicemails = 0, oldvoicemails = 0;
+ struct ast_smdi_mwi_message *mwi_msg;
- if (smdi_iface) {
- if (ast_app_has_voicemail(ext_context, NULL))
- ast_smdi_mwi_set(smdi_iface, extension);
+ if (!ast_strlen_zero(context))
+ snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
else
- ast_smdi_mwi_unset(smdi_iface, extension);
-
- if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
- ast_log(LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
- if (!strncmp(mwi_msg->cause, "INV", 3))
- ast_log(LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
- else if (!strncmp(mwi_msg->cause, "BLK", 3))
- ast_log(LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
- ast_log(LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
- ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
- } else {
- ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
+ ast_copy_string(ext_context, extension, sizeof(ext_context));
+
+ if (smdi_iface) {
+ if (ast_app_has_voicemail(ext_context, NULL))
+ ast_smdi_mwi_set(smdi_iface, extension);
+ else
+ ast_smdi_mwi_unset(smdi_iface, extension);
+
+ if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
+ ast_log(LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
+ if (!strncmp(mwi_msg->cause, "INV", 3))
+ ast_log(LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
+ else if (!strncmp(mwi_msg->cause, "BLK", 3))
+ ast_log(LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
+ ast_log(LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
+ ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
+ } else {
+ ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
+ }
}
- }
- if (!ast_strlen_zero(externnotify)) {
- if (inboxcount(ext_context, &newvoicemails, &oldvoicemails)) {
- ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
- } else {
- snprintf(arguments, sizeof(arguments), "%s %s %s %d&", externnotify, context, extension, newvoicemails);
- ast_debug(1, "Executing %s\n", arguments);
- ast_safe_system(arguments);
+ if (!ast_strlen_zero(externnotify)) {
+ if (inboxcount(ext_context, &newvoicemails, &oldvoicemails)) {
+ ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
+ } else {
+ snprintf(arguments, sizeof(arguments), "%s %s %s %d&", externnotify, context, extension, newvoicemails);
+ ast_debug(1, "Executing %s\n", arguments);
+ ast_safe_system(arguments);
+ }
}
}
-}
-struct leave_vm_options {
- unsigned int flags;
- signed char record_gain;
- char *exitcontext;
-};
+ struct leave_vm_options {
+ unsigned int flags;
+ signed char record_gain;
+ char *exitcontext;
+ };
-static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
-{
+ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
+ {
#ifdef IMAP_STORAGE
- int newmsgs, oldmsgs;
- struct vm_state *vms = NULL;
+ int newmsgs, oldmsgs;
#endif
- char txtfile[PATH_MAX], tmptxtfile[PATH_MAX];
- char callerid[256];
- FILE *txt;
- char date[256];
- int txtdes;
- int res = 0;
- int msgnum;
- int duration = 0;
- int ausemacro = 0;
- int ousemacro = 0;
- int ouseexten = 0;
- int rtmsgid = 0;
- char tmpid[16];
- char tmpdur[16];
- char priority[16];
- char origtime[16];
- char dir[PATH_MAX], tmpdir[PATH_MAX];
- char fn[PATH_MAX];
- char prefile[PATH_MAX] = "";
- char tempfile[PATH_MAX] = "";
- char ext_context[256] = "";
- char fmt[80];
- char *context;
- char ecodes[17] = "#";
- char tmp[1024] = "", *tmpptr;
- struct ast_vm_user *vmu;
- struct ast_vm_user svm;
- const char *category = NULL, *code, *alldtmf = "0123456789ABCD*#";
-
- ast_copy_string(tmp, ext, sizeof(tmp));
- ext = tmp;
- if ((context = strchr(tmp, '@'))) {
- *context++ = '\0';
- tmpptr = strchr(context, '&');
- } else {
- tmpptr = strchr(ext, '&');
- }
+ char txtfile[PATH_MAX], tmptxtfile[PATH_MAX];
+ struct vm_state *vms = NULL;
+ char callerid[256];
+ FILE *txt;
+ char date[256];
+ int txtdes;
+ int res = 0;
+ int msgnum;
+ int duration = 0;
+ int ausemacro = 0;
+ int ousemacro = 0;
+ int ouseexten = 0;
+ int rtmsgid = 0;
+ char tmpid[16];
+ char tmpdur[16];
+ char priority[16];
+ char origtime[16];
+ char dir[PATH_MAX], tmpdir[PATH_MAX];
+ char fn[PATH_MAX];
+ char prefile[PATH_MAX] = "";
+ char tempfile[PATH_MAX] = "";
+ char ext_context[256] = "";
+ char fmt[80];
+ char *context;
+ char ecodes[17] = "#";
+ char tmp[1024] = "", *tmpptr;
+ struct ast_vm_user *vmu;
+ struct ast_vm_user svm;
+ const char *category = NULL, *code, *alldtmf = "0123456789ABCD*#";
+
+ ast_copy_string(tmp, ext, sizeof(tmp));
+ ext = tmp;
+ if ((context = strchr(tmp, '@'))) {
+ *context++ = '\0';
+ tmpptr = strchr(context, '&');
+ } else {
+ tmpptr = strchr(ext, '&');
+ }
- if (tmpptr)
- *tmpptr++ = '\0';
+ if (tmpptr)
+ *tmpptr++ = '\0';
- category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
+ category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
- ast_debug(3, "Before find_user\n");
- if (!(vmu = find_user(&svm, context, ext))) {
- ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
- pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
- return res;
- }
- /* Setup pre-file if appropriate */
- if (strcmp(vmu->context, "default"))
- snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
- else
- ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
- if (ast_test_flag(options, OPT_BUSY_GREETING)) {
- snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
- } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
- snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
- }
- snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
- if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
- ast_log(LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
- return -1;
- }
- RETRIEVE(tempfile, -1, ext, context);
- if (ast_fileexists(tempfile, NULL, NULL) > 0)
- ast_copy_string(prefile, tempfile, sizeof(prefile));
- DISPOSE(tempfile, -1);
- /* It's easier just to try to make it than to check for its existence */
- create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
+ ast_debug(3, "Before find_user\n");
+ if (!(vmu = find_user(&svm, context, ext))) {
+ ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
+ return res;
+ }
+ /* Setup pre-file if appropriate */
+ if (strcmp(vmu->context, "default"))
+ snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
+ else
+ ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
+ if (ast_test_flag(options, OPT_BUSY_GREETING)) {
+ snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
+ } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
+ snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
+ }
+ snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
+ if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
+ ast_log(LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
+ return -1;
+ }
+ RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
+ if (ast_fileexists(tempfile, NULL, NULL) > 0)
+ ast_copy_string(prefile, tempfile, sizeof(prefile));
+ DISPOSE(tempfile, -1);
+ /* It's easier just to try to make it than to check for its existence */
+ create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
- /* Check current or macro-calling context for special extensions */
- if (ast_test_flag(vmu, VM_OPERATOR)) {
- if (!ast_strlen_zero(vmu->exit)) {
- if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
+ /* Check current or macro-calling context for special extensions */
+ if (ast_test_flag(vmu, VM_OPERATOR)) {
+ if (!ast_strlen_zero(vmu->exit)) {
+ if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
+ strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
+ ouseexten = 1;
+ }
+ } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
ouseexten = 1;
+ } else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
+ strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
+ ousemacro = 1;
}
- } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
- strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
- ouseexten = 1;
- } else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
- strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
- ousemacro = 1;
}
- }
- if (!ast_strlen_zero(vmu->exit)) {
- if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
+ if (!ast_strlen_zero(vmu->exit)) {
+ if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
+ strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
+ } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
- } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
- strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
- else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
- strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
- ausemacro = 1;
- }
-
- if (ast_test_flag(options, OPT_DTMFEXIT)) {
- for (code = alldtmf; *code; code++) {
- char e[2] = "";
- e[0] = *code;
- if (strchr(ecodes, e[0]) == NULL && ast_canmatch_extension(chan, chan->context, e, 1, chan->cid.cid_num))
- strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
+ else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
+ strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
+ ausemacro = 1;
}
- }
- /* Play the beginning intro if desired */
- if (!ast_strlen_zero(prefile)) {
- res = play_greeting(chan, vmu, prefile, ecodes);
- if (res == -2) {
- /* The file did not exist */
- ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
- res = invent_message(chan, vmu, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
+ if (ast_test_flag(options, OPT_DTMFEXIT)) {
+ for (code = alldtmf; *code; code++) {
+ char e[2] = "";
+ e[0] = *code;
+ if (strchr(ecodes, e[0]) == NULL && ast_canmatch_extension(chan, chan->context, e, 1, chan->cid.cid_num))
+ strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
+ }
}
- if (res < 0) {
- ast_debug(1, "Hang up during prefile playback\n");
- free_user(vmu);
- pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
- return -1;
+
+ /* Play the beginning intro if desired */
+ if (!ast_strlen_zero(prefile)) {
+ res = play_greeting(chan, vmu, prefile, ecodes);
+ if (res == -2) {
+ /* The file did not exist */
+ ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
+ res = invent_message(chan, vmu, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
+ }
+ if (res < 0) {
+ ast_debug(1, "Hang up during prefile playback\n");
+ free_user(vmu);
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
+ return -1;
+ }
}
- }
- if (res == '#') {
- /* On a '#' we skip the instructions */
- ast_set_flag(options, OPT_SILENT);
- res = 0;
- }
- if (!res && !ast_test_flag(options, OPT_SILENT)) {
- res = ast_stream_and_wait(chan, INTRO, ecodes);
if (res == '#') {
+ /* On a '#' we skip the instructions */
ast_set_flag(options, OPT_SILENT);
res = 0;
}
- }
- if (res > 0)
- ast_stopstream(chan);
- /* Check for a '*' here in case the caller wants to escape from voicemail to something
- other than the operator -- an automated attendant or mailbox login for example */
- if (res == '*') {
- chan->exten[0] = 'a';
- chan->exten[1] = '\0';
- if (!ast_strlen_zero(vmu->exit)) {
- ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
- } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
- ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
+ if (!res && !ast_test_flag(options, OPT_SILENT)) {
+ res = ast_stream_and_wait(chan, INTRO, ecodes);
+ if (res == '#') {
+ ast_set_flag(options, OPT_SILENT);
+ res = 0;
+ }
}
- chan->priority = 0;
- free_user(vmu);
- pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
- return 0;
- }
-
- /* Check for a '0' here */
- if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
- transfer:
- if (ouseexten || ousemacro) {
- chan->exten[0] = 'o';
+ if (res > 0)
+ ast_stopstream(chan);
+ /* Check for a '*' here in case the caller wants to escape from voicemail to something
+ other than the operator -- an automated attendant or mailbox login for example */
+ if (res == '*') {
+ chan->exten[0] = 'a';
chan->exten[1] = '\0';
if (!ast_strlen_zero(vmu->exit)) {
ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
- } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
+ } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
}
- ast_play_and_wait(chan, "transfer");
chan->priority = 0;
free_user(vmu);
pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
+ return 0;
}
- return 0;
- }
- /* Allow all other digits to exit Voicemail and return to the dialplan */
- if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
- if (!ast_strlen_zero(options->exitcontext))
- ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
- free_user(vmu);
- pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
- return res;
- }
-
- if (res < 0) {
- free_user(vmu);
- pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
- return -1;
- }
- /* The meat of recording the message... All the announcements and beeps have been played*/
- ast_copy_string(fmt, vmfmts, sizeof(fmt));
- if (!ast_strlen_zero(fmt)) {
- msgnum = 0;
-
-#ifdef IMAP_STORAGE
- /* Is ext a mailbox? */
- /* must open stream for this user to get info! */
- res = inboxcount(ext_context, &newmsgs, &oldmsgs);
- if (res < 0) {
- ast_log(LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
- return -1;
- }
- if (!(vms = get_vm_state_by_mailbox(ext, 0))) {
- /* It is possible under certain circumstances that inboxcount did not
- * create a vm_state when it was needed. This is a catchall which will
- * rarely be used.
- */
- if (!(vms = ast_calloc(1, sizeof(*vms)))) {
- ast_log(LOG_ERROR, "Couldn't allocate necessary space\n");
- return -1;
+ /* Check for a '0' here */
+ if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
+ transfer:
+ if (ouseexten || ousemacro) {
+ chan->exten[0] = 'o';
+ chan->exten[1] = '\0';
+ if (!ast_strlen_zero(vmu->exit)) {
+ ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
+ } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
+ ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
+ }
+ ast_play_and_wait(chan, "transfer");
+ chan->priority = 0;
+ free_user(vmu);
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
}
- ast_copy_string(vms->imapuser, vmu->imapuser, sizeof(vms->imapuser));
- ast_copy_string(vms->username, ext, sizeof(vms->username));
- vms->mailstream = NIL;
- ast_debug(3, "Copied %s to %s\n", vmu->imapuser, vms->imapuser);
- vms->updated = 1;
- ast_copy_string(vms->curbox, mbox(0), sizeof(vms->curbox));
- init_vm_state(vms);
- vmstate_insert(vms);
- vms = get_vm_state_by_mailbox(ext, 0);
- }
- vms->newmessages++;
-
- /* 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);
- /* set variable for compatibility */
- pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
-
- /* Check if mailbox is full */
- check_quota(vms, imapfolder);
- if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
- ast_debug(1, "*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
- ast_play_and_wait(chan, "vm-mailboxfull");
- return -1;
- }
-
- /* Check if we have exceeded maxmsg */
- if (msgnum >= vmu->maxmsg) {
- 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");
- return -1;
+ return 0;
}
-#else
- if (count_messages(vmu, dir) >= vmu->maxmsg) {
- res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
- if (!res)
- res = ast_waitstream(chan, "");
- ast_log(LOG_WARNING, "No more messages possible\n");
- pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
- goto leave_vm_out;
+ /* Allow all other digits to exit Voicemail and return to the dialplan */
+ if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
+ if (!ast_strlen_zero(options->exitcontext))
+ ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
+ free_user(vmu);
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
+ return res;
}
-#endif
- snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
- txtdes = mkstemp(tmptxtfile);
- chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
- if (txtdes < 0) {
- res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
- if (!res)
- res = ast_waitstream(chan, "");
- ast_log(LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
+ if (res < 0) {
+ free_user(vmu);
pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
- goto leave_vm_out;
+ return -1;
}
+ /* The meat of recording the message... All the announcements and beeps have been played*/
+ ast_copy_string(fmt, vmfmts, sizeof(fmt));
+ if (!ast_strlen_zero(fmt)) {
+ msgnum = 0;
- /* Now play the beep once we have the message number for our next message. */
- if (res >= 0) {
- /* Unless we're *really* silent, try to send the beep */
- res = ast_stream_and_wait(chan, "beep", "");
- }
-
- /* Store information in real-time storage */
- if (ast_check_realtime("voicemail_data")) {
- snprintf(priority, sizeof(priority), "%d", chan->priority);
- snprintf(origtime, sizeof(origtime), "%ld", (long)time(NULL));
- get_date(date, sizeof(date));
- rtmsgid = ast_store_realtime("voicemail_data", "origmailbox", ext, "context", chan->context, "macrocontext", chan->macrocontext, "exten", chan->exten, "priority", priority, "callerchan", chan->name, "callerid", ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"), "origdate", date, "origtime", origtime, "category", category ? category : "", NULL);
- }
-
- /* Store information */
- txt = fdopen(txtdes, "w+");
- if (txt) {
- get_date(date, sizeof(date));
- fprintf(txt,
- ";\n"
- "; Message Information file\n"
- ";\n"
- "[message]\n"
- "origmailbox=%s\n"
- "context=%s\n"
- "macrocontext=%s\n"
- "exten=%s\n"
- "priority=%d\n"
- "callerchan=%s\n"
- "callerid=%s\n"
- "origdate=%s\n"
- "origtime=%ld\n"
- "category=%s\n",
- ext,
- chan->context,
- chan->macrocontext,
- chan->exten,
- chan->priority,
- chan->name,
- ast_callerid_merge(callerid, sizeof(callerid), S_OR(chan->cid.cid_name, NULL), S_OR(chan->cid.cid_num, NULL), "Unknown"),
- date, (long)time(NULL),
- category ? category : "");
- } else
- ast_log(LOG_WARNING, "Error opening text file for output\n");
#ifdef IMAP_STORAGE
- res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms);
+ /* Is ext a mailbox? */
+ /* must open stream for this user to get info! */
+ res = inboxcount(ext_context, &newmsgs, &oldmsgs);
+ if (res < 0) {
+ ast_log(LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
+ return -1;
+ }
+ if (!(vms = get_vm_state_by_mailbox(ext, 0))) {
+ /* It is possible under certain circumstances that inboxcount did not
+ * create a vm_state when it was needed. This is a catchall which will
+ * rarely be used.
+ */
+ if (!(vms = create_vm_state_from_user(vmu))) {
+ ast_log(LOG_ERROR, "Couldn't allocate necessary space\n");
+ return -1;
+ }
+ }
+ vms->newmessages++;
+
+ /* 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);
+ /* set variable for compatibility */
+ pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
+
+ /* Check if mailbox is full */
+ check_quota(vms, imapfolder);
+ if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
+ ast_debug(1, "*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
+ ast_play_and_wait(chan, "vm-mailboxfull");
+ return -1;
+ }
+
+ /* Check if we have exceeded maxmsg */
+ if (msgnum >= vmu->maxmsg) {
+ 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");
+ return -1;
+ }
#else
- res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, NULL);
+ if (count_messages(vmu, dir) >= vmu->maxmsg) {
+ res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
+ if (!res)
+ res = ast_waitstream(chan, "");
+ ast_log(LOG_WARNING, "No more messages possible\n");
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
+ goto leave_vm_out;
+ }
+
#endif
+ snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
+ txtdes = mkstemp(tmptxtfile);
+ chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
+ if (txtdes < 0) {
+ res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
+ if (!res)
+ res = ast_waitstream(chan, "");
+ ast_log(LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
+ goto leave_vm_out;
+ }
- if (txt) {
- if (duration < vmminsecs) {
- fclose(txt);
- ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminsecs);
- ast_filedelete(tmptxtfile, NULL);
- unlink(tmptxtfile);
- if (ast_check_realtime("voicemail_data")) {
- snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
- ast_destroy_realtime("voicemail_data", "id", tmpid, NULL);
- }
- } else {
- fprintf(txt, "duration=%d\n", duration);
- fclose(txt);
- if (vm_lock_path(dir)) {
- ast_log(LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
- /* Delete files */
+ /* Now play the beep once we have the message number for our next message. */
+ if (res >= 0) {
+ /* Unless we're *really* silent, try to send the beep */
+ res = ast_stream_and_wait(chan, "beep", "");
+ }
+
+ /* Store information in real-time storage */
+ if (ast_check_realtime("voicemail_data")) {
+ snprintf(priority, sizeof(priority), "%d", chan->priority);
+ snprintf(origtime, sizeof(origtime), "%ld", (long)time(NULL));
+ get_date(date, sizeof(date));
+ rtmsgid = ast_store_realtime("voicemail_data", "origmailbox", ext, "context", chan->context, "macrocontext", chan->macrocontext, "exten", chan->exten, "priority", priority, "callerchan", chan->name, "callerid", ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"), "origdate", date, "origtime", origtime, "category", category ? category : "", NULL);
+ }
+
+ /* Store information */
+ txt = fdopen(txtdes, "w+");
+ if (txt) {
+ get_date(date, sizeof(date));
+ fprintf(txt,
+ ";\n"
+ "; Message Information file\n"
+ ";\n"
+ "[message]\n"
+ "origmailbox=%s\n"
+ "context=%s\n"
+ "macrocontext=%s\n"
+ "exten=%s\n"
+ "priority=%d\n"
+ "callerchan=%s\n"
+ "callerid=%s\n"
+ "origdate=%s\n"
+ "origtime=%ld\n"
+ "category=%s\n",
+ ext,
+ chan->context,
+ chan->macrocontext,
+ chan->exten,
+ chan->priority,
+ chan->name,
+ ast_callerid_merge(callerid, sizeof(callerid), S_OR(chan->cid.cid_name, NULL), S_OR(chan->cid.cid_num, NULL), "Unknown"),
+ date, (long)time(NULL),
+ category ? category : "");
+ } else
+ ast_log(LOG_WARNING, "Error opening text file for output\n");
+ res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms);
+
+ if (txt) {
+ if (duration < vmminsecs) {
+ fclose(txt);
+ ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminsecs);
ast_filedelete(tmptxtfile, NULL);
unlink(tmptxtfile);
- } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
- ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
- unlink(tmptxtfile);
- ast_unlock_path(dir);
if (ast_check_realtime("voicemail_data")) {
snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
ast_destroy_realtime("voicemail_data", "id", tmpid, NULL);
}
} else {
+ fprintf(txt, "duration=%d\n", duration);
+ fclose(txt);
+ if (vm_lock_path(dir)) {
+ ast_log(LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
+ /* Delete files */
+ ast_filedelete(tmptxtfile, NULL);
+ unlink(tmptxtfile);
+ } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
+ ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
+ unlink(tmptxtfile);
+ ast_unlock_path(dir);
+ if (ast_check_realtime("voicemail_data")) {
+ snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
+ ast_destroy_realtime("voicemail_data", "id", tmpid, NULL);
+ }
+ } else {
#ifndef IMAP_STORAGE
- msgnum = last_message_index(vmu, dir) + 1;
+ msgnum = last_message_index(vmu, dir) + 1;
#endif
- make_file(fn, sizeof(fn), dir, msgnum);
+ make_file(fn, sizeof(fn), dir, msgnum);
- /* assign a variable with the name of the voicemail file */
+ /* assign a variable with the name of the voicemail file */
#ifndef IMAP_STORAGE
- pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
+ pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
#else
- pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
+ pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
#endif
- snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
- ast_filerename(tmptxtfile, fn, NULL);
- rename(tmptxtfile, txtfile);
+ snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
+ ast_filerename(tmptxtfile, fn, NULL);
+ rename(tmptxtfile, txtfile);
- /* Properly set permissions on voicemail text descriptor file.
- Unfortunately mkstemp() makes this file 0600 on most unix systems. */
- if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
- ast_log(LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
-
- ast_unlock_path(dir);
- if (ast_check_realtime("voicemail_data")) {
- snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
- snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
- ast_update_realtime("voicemail_data", "id", tmpid, "filename", fn, "duration", tmpdur, NULL);
- }
- /* We must store the file first, before copying the message, because
- * ODBC storage does the entire copy with SQL.
- */
- if (ast_fileexists(fn, NULL, NULL) > 0) {
- STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms);
- }
+ /* Properly set permissions on voicemail text descriptor file.
+ Unfortunately mkstemp() makes this file 0600 on most unix systems. */
+ if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
+ ast_log(LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
- /* 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++;
+ ast_unlock_path(dir);
+ if (ast_check_realtime("voicemail_data")) {
+ snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
+ snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
+ ast_update_realtime("voicemail_data", "id", tmpid, "filename", fn, "duration", tmpdur, NULL);
}
- if ((recip = find_user(&recipu, context, exten))) {
- copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir);
- free_user(recip);
+ /* We must store the file first, before copying the message, because
+ * ODBC storage does the entire copy with SQL.
+ */
+ if (ast_fileexists(fn, NULL, NULL) > 0) {
+ STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms);
}
- }
- /* Notification and disposal needs to happen after the copy, though. */
- if (ast_fileexists(fn, NULL, NULL)) {
+
+ /* 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))) {
+ copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir);
+ free_user(recip);
+ }
+ }
+ /* Notification and disposal needs to happen after the copy, though. */
+ if (ast_fileexists(fn, NULL, NULL)) {
#ifdef IMAP_STORAGE
- notify_new_message(chan, vmu, vms, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
+ notify_new_message(chan, vmu, vms, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
#else
- notify_new_message(chan, vmu, NULL, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
+ notify_new_message(chan, vmu, NULL, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
#endif
- DISPOSE(dir, msgnum);
+ DISPOSE(dir, msgnum);
+ }
}
}
}
- }
- if (res == '0') {
- goto transfer;
- } else if (res > 0)
- res = 0;
+ if (res == '0') {
+ goto transfer;
+ } else if (res > 0)
+ res = 0;
- if (duration < vmminsecs)
- /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
- pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
- else
- pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
- } else
- ast_log(LOG_WARNING, "No format for saving voicemail?\n");
-leave_vm_out:
- free_user(vmu);
-
- return res;
-}
+ if (duration < vmminsecs)
+ /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
+ else
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
+ } else
+ ast_log(LOG_WARNING, "No format for saving voicemail?\n");
+ leave_vm_out:
+ free_user(vmu);
+
+ return res;
+ }
#ifndef IMAP_STORAGE
-static int resequence_mailbox(struct ast_vm_user *vmu, char *dir)
-{
- /* we know max messages, so stop process when number is hit */
+ static int resequence_mailbox(struct ast_vm_user *vmu, char *dir)
+ {
+ /* we know max messages, so stop process when number is hit */
- int x, dest;
- char sfn[PATH_MAX];
- char dfn[PATH_MAX];
+ int x, dest;
+ char sfn[PATH_MAX];
+ char dfn[PATH_MAX];
- if (vm_lock_path(dir))
- return ERROR_LOCK_PATH;
+ if (vm_lock_path(dir))
+ return ERROR_LOCK_PATH;
- for (x = 0, dest = 0; x < vmu->maxmsg; x++) {
- make_file(sfn, sizeof(sfn), dir, x);
- if (EXISTS(dir, x, sfn, NULL)) {
-
- if (x != dest) {
- make_file(dfn, sizeof(dfn), dir, dest);
- RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
+ for (x = 0, dest = 0; x < vmu->maxmsg; x++) {
+ make_file(sfn, sizeof(sfn), dir, x);
+ if (EXISTS(dir, x, sfn, NULL)) {
+
+ if (x != dest) {
+ make_file(dfn, sizeof(dfn), dir, dest);
+ RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
+ }
+
+ dest++;
}
-
- dest++;
}
- }
- ast_unlock_path(dir);
+ ast_unlock_path(dir);
- return 0;
-}
+ return 0;
+ }
#endif
-static int say_and_wait(struct ast_channel *chan, int num, const char *language)
-{
- int d;
- d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
- return d;
-}
+ static int say_and_wait(struct ast_channel *chan, int num, const char *language)
+ {
+ int d;
+ d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
+ return d;
+ }
-static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
-{
+ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
+ {
#ifdef IMAP_STORAGE
- /* we must use mbox(x) folder names, and copy the message there */
- /* simple. huh? */
- long res;
- char sequence[10];
- char mailbox[256];
-
- /* if save to Old folder, just leave in INBOX */
- if (box == 1) return 10;
- /* get the real IMAP message number for this message */
- snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
- /* Create the folder if it don't exist */
- imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
- ast_debug(5, "Checking if folder exists: %s\n",mailbox);
- if (mail_create(vms->mailstream, mailbox) == NIL)
- ast_debug(5, "Folder exists.\n");
- else
- ast_log(LOG_NOTICE, "Folder %s created!\n",mbox(box));
-
- ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(box));
- res = mail_copy(vms->mailstream, sequence, (char *)mbox(box));
- if (res == 1) return 0;
- return 1;
+ /* we must use mbox(x) folder names, and copy the message there */
+ /* simple. huh? */
+ char sequence[10];
+ char mailbox[256];
+ /* get the real IMAP message number for this message */
+ snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
+
+ ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(box));
+ if (box == OLD_FOLDER) {
+ mail_setflag(vms->mailstream, sequence, "\\Seen");
+ } else if (box == NEW_FOLDER) {
+ mail_clearflag(vms->mailstream, sequence, "\\Seen");
+ }
+ if (!strcasecmp(mbox(NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER))
+ return 0;
+ /* Create the folder if it don't exist */
+ imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
+ ast_debug(5, "Checking if folder exists: %s\n",mailbox);
+ if (mail_create(vms->mailstream, mailbox) == NIL)
+ ast_debug(5, "Folder exists.\n");
+ else
+ ast_log(LOG_NOTICE, "Folder %s created!\n",mbox(box));
+ return !mail_copy(vms->mailstream, sequence, (char *)mbox(box));
#else
- char *dir = vms->curdir;
- char *username = vms->username;
- char *context = vmu->context;
- char sfn[PATH_MAX];
- char dfn[PATH_MAX];
- char ddir[PATH_MAX];
- const char *dbox = mbox(box);
- int x, i;
- create_dirpath(ddir, sizeof(ddir), context, username, dbox);
-
- if (vm_lock_path(ddir))
- return ERROR_LOCK_PATH;
-
- x = last_message_index(vmu, ddir) + 1;
-
- if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
- x--;
- for (i = 1; i <= x; i++) {
- /* Push files down a "slot". The oldest file (msg0000) will be deleted. */
- make_file(sfn, sizeof(sfn), ddir, i);
- make_file(dfn, sizeof(dfn), ddir, i - 1);
- if (EXISTS(ddir, i, sfn, NULL)) {
- RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
- } else
- break;
+ char *dir = vms->curdir;
+ char *username = vms->username;
+ char *context = vmu->context;
+ char sfn[PATH_MAX];
+ char dfn[PATH_MAX];
+ char ddir[PATH_MAX];
+ const char *dbox = mbox(box);
+ int x, i;
+ create_dirpath(ddir, sizeof(ddir), context, username, dbox);
+
+ if (vm_lock_path(ddir))
+ return ERROR_LOCK_PATH;
+
+ x = last_message_index(vmu, ddir) + 1;
+
+ if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
+ x--;
+ for (i = 1; i <= x; i++) {
+ /* Push files down a "slot". The oldest file (msg0000) will be deleted. */
+ make_file(sfn, sizeof(sfn), ddir, i);
+ make_file(dfn, sizeof(dfn), ddir, i - 1);
+ if (EXISTS(ddir, i, sfn, NULL)) {
+ RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
+ } else
+ break;
+ }
+ } else {
+ if (x >= vmu->maxmsg) {
+ ast_unlock_path(ddir);
+ return ERROR_MAILBOX_FULL;
+ }
}
- } else {
- if (x >= vmu->maxmsg) {
- ast_unlock_path(ddir);
- return ERROR_MAILBOX_FULL;
+ make_file(sfn, sizeof(sfn), dir, msg);
+ make_file(dfn, sizeof(dfn), ddir, x);
+ if (strcmp(sfn, dfn)) {
+ COPY(dir, msg, ddir, x, username, context, sfn, dfn);
}
- }
- make_file(sfn, sizeof(sfn), dir, msg);
- make_file(dfn, sizeof(dfn), ddir, x);
- if (strcmp(sfn, dfn)) {
- COPY(dir, msg, ddir, x, username, context, sfn, dfn);
- }
- ast_unlock_path(ddir);
+ ast_unlock_path(ddir);
#endif
- return 0;
-}
+ return 0;
+ }
-static int adsi_logo(unsigned char *buf)
-{
- int bytes = 0;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
- return bytes;
-}
+ static int adsi_logo(unsigned char *buf)
+ {
+ int bytes = 0;
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
+ return bytes;
+ }
-static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
-{
- unsigned char buf[256];
- int bytes = 0;
- int x;
- char num[5];
+ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
+ {
+ unsigned char buf[256];
+ int bytes = 0;
+ int x;
+ char num[5];
- *useadsi = 0;
- bytes += ast_adsi_data_mode(buf + bytes);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ *useadsi = 0;
+ bytes += ast_adsi_data_mode(buf + bytes);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
- bytes = 0;
- bytes += adsi_logo(buf);
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
+ bytes = 0;
+ bytes += adsi_logo(buf);
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
#ifdef DISPLAY
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .", "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .", "");
#endif
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_data_mode(buf + bytes);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-
- if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
- bytes = 0;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ bytes += ast_adsi_data_mode(buf + bytes);
ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
- return 0;
- }
+
+ if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
+ bytes = 0;
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ return 0;
+ }
#ifdef DISPLAY
- /* Add a dot */
- bytes = 0;
- bytes += ast_adsi_logo(buf);
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ..", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ /* Add a dot */
+ bytes = 0;
+ bytes += ast_adsi_logo(buf);
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ..", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
#endif
- bytes = 0;
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
+ bytes = 0;
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
#ifdef DISPLAY
- /* Add another dot */
- bytes = 0;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ /* Add another dot */
+ bytes = 0;
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
#endif
- bytes = 0;
- /* These buttons we load but don't use yet */
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
+ bytes = 0;
+ /* These buttons we load but don't use yet */
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
#ifdef DISPLAY
- /* Add another dot */
- bytes = 0;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ....", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ /* Add another dot */
+ bytes = 0;
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ....", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
#endif
- bytes = 0;
- for (x = 0; x < 5; x++) {
- snprintf(num, sizeof(num), "%d", x);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
- }
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
+ bytes = 0;
+ for (x = 0; x < 5; x++) {
+ snprintf(num, sizeof(num), "%d", x);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
+ }
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
#ifdef DISPLAY
- /* Add another dot */
- bytes = 0;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .....", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ /* Add another dot */
+ bytes = 0;
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .....", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
#endif
- if (ast_adsi_end_download(chan)) {
+ if (ast_adsi_end_download(chan)) {
+ bytes = 0;
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ return 0;
+ }
bytes = 0;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_download_disconnect(buf + bytes);
bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
- return 0;
- }
- bytes = 0;
- bytes += ast_adsi_download_disconnect(buf + bytes);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
- ast_debug(1, "Done downloading scripts...\n");
+ ast_debug(1, "Done downloading scripts...\n");
#ifdef DISPLAY
- /* Add last dot */
- bytes = 0;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ......", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ /* Add last dot */
+ bytes = 0;
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ......", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
#endif
- ast_debug(1, "Restarting session...\n");
+ ast_debug(1, "Restarting session...\n");
- bytes = 0;
- /* Load the session now */
- if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
- *useadsi = 1;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
- } else
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
+ bytes = 0;
+ /* Load the session now */
+ if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
+ *useadsi = 1;
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
+ } else
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
- return 0;
-}
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ return 0;
+ }
-static void adsi_begin(struct ast_channel *chan, int *useadsi)
-{
- int x;
- if (!ast_adsi_available(chan))
- return;
- x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
- if (x < 0)
- return;
- if (!x) {
- if (adsi_load_vmail(chan, useadsi)) {
- ast_log(LOG_WARNING, "Unable to upload voicemail scripts\n");
+ static void adsi_begin(struct ast_channel *chan, int *useadsi)
+ {
+ int x;
+ if (!ast_adsi_available(chan))
return;
- }
- } else
- *useadsi = 1;
-}
+ x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
+ if (x < 0)
+ return;
+ if (!x) {
+ if (adsi_load_vmail(chan, useadsi)) {
+ ast_log(LOG_WARNING, "Unable to upload voicemail scripts\n");
+ return;
+ }
+ } else
+ *useadsi = 1;
+ }
-static void adsi_login(struct ast_channel *chan)
-{
- unsigned char buf[256];
- int bytes = 0;
- unsigned char keys[8];
- int x;
- if (!ast_adsi_available(chan))
- return;
+ static void adsi_login(struct ast_channel *chan)
+ {
+ unsigned char buf[256];
+ int bytes = 0;
+ unsigned char keys[8];
+ int x;
+ if (!ast_adsi_available(chan))
+ return;
- for (x = 0; x < 8; x++)
- keys[x] = 0;
- /* Set one key for next */
- keys[3] = ADSI_KEY_APPS + 3;
+ for (x = 0; x < 8; x++)
+ keys[x] = 0;
+ /* Set one key for next */
+ keys[3] = ADSI_KEY_APPS + 3;
- bytes += adsi_logo(buf + bytes);
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
- bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
- bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
- bytes += ast_adsi_set_keys(buf + bytes, keys);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
+ bytes += adsi_logo(buf + bytes);
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
+ bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
+ bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
+ bytes += ast_adsi_set_keys(buf + bytes, keys);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ }
-static void adsi_password(struct ast_channel *chan)
-{
- unsigned char buf[256];
- int bytes = 0;
- unsigned char keys[8];
- int x;
- if (!ast_adsi_available(chan))
- return;
+ static void adsi_password(struct ast_channel *chan)
+ {
+ unsigned char buf[256];
+ int bytes = 0;
+ unsigned char keys[8];
+ int x;
+ if (!ast_adsi_available(chan))
+ return;
- for (x = 0; x < 8; x++)
- keys[x] = 0;
- /* Set one key for next */
- keys[3] = ADSI_KEY_APPS + 3;
+ for (x = 0; x < 8; x++)
+ keys[x] = 0;
+ /* Set one key for next */
+ keys[3] = ADSI_KEY_APPS + 3;
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
- bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
- bytes += ast_adsi_set_keys(buf + bytes, keys);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
+ bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
+ bytes += ast_adsi_set_keys(buf + bytes, keys);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ }
-static void adsi_folders(struct ast_channel *chan, int start, char *label)
-{
- unsigned char buf[256];
- int bytes = 0;
- unsigned char keys[8];
- int x, y;
+ static void adsi_folders(struct ast_channel *chan, int start, char *label)
+ {
+ unsigned char buf[256];
+ int bytes = 0;
+ unsigned char keys[8];
+ int x, y;
- if (!ast_adsi_available(chan))
- return;
+ if (!ast_adsi_available(chan))
+ return;
- for (x = 0; x < 5; x++) {
- y = ADSI_KEY_APPS + 12 + start + x;
- if (y > ADSI_KEY_APPS + 12 + 4)
- y = 0;
- keys[x] = ADSI_KEY_SKT | y;
- }
- keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
- keys[6] = 0;
- keys[7] = 0;
+ for (x = 0; x < 5; x++) {
+ y = ADSI_KEY_APPS + 12 + start + x;
+ if (y > ADSI_KEY_APPS + 12 + 4)
+ y = 0;
+ keys[x] = ADSI_KEY_SKT | y;
+ }
+ keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
+ keys[6] = 0;
+ keys[7] = 0;
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_set_keys(buf + bytes, keys);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_set_keys(buf + bytes, keys);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ }
-static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
-{
- int bytes = 0;
- unsigned char buf[256];
- char buf1[256], buf2[256];
- char fn2[PATH_MAX];
+ static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
+ {
+ int bytes = 0;
+ unsigned char buf[256];
+ char buf1[256], buf2[256];
+ char fn2[PATH_MAX];
- char cid[256] = "";
- char *val;
- char *name, *num;
- char datetime[21] = "";
- FILE *f;
+ char cid[256] = "";
+ char *val;
+ char *name, *num;
+ char datetime[21] = "";
+ FILE *f;
- unsigned char keys[8];
+ unsigned char keys[8];
- int x;
+ int x;
- if (!ast_adsi_available(chan))
- return;
+ if (!ast_adsi_available(chan))
+ return;
- /* Retrieve important info */
- snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
- f = fopen(fn2, "r");
- if (f) {
- while (!feof(f)) {
- fgets((char *)buf, sizeof(buf), f);
- if (!feof(f)) {
- char *stringp = NULL;
- stringp = (char *)buf;
- strsep(&stringp, "=");
- val = strsep(&stringp, "=");
- if (!ast_strlen_zero(val)) {
- if (!strcmp((char *)buf, "callerid"))
- ast_copy_string(cid, val, sizeof(cid));
- if (!strcmp((char *)buf, "origdate"))
- ast_copy_string(datetime, val, sizeof(datetime));
+ /* Retrieve important info */
+ snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
+ f = fopen(fn2, "r");
+ if (f) {
+ while (!feof(f)) {
+ fgets((char *)buf, sizeof(buf), f);
+ if (!feof(f)) {
+ char *stringp = NULL;
+ stringp = (char *)buf;
+ strsep(&stringp, "=");
+ val = strsep(&stringp, "=");
+ if (!ast_strlen_zero(val)) {
+ if (!strcmp((char *)buf, "callerid"))
+ ast_copy_string(cid, val, sizeof(cid));
+ if (!strcmp((char *)buf, "origdate"))
+ ast_copy_string(datetime, val, sizeof(datetime));
+ }
}
}
+ fclose(f);
}
- fclose(f);
- }
- /* New meaning for keys */
- for (x = 0; x < 5; x++)
- keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
- keys[6] = 0x0;
- keys[7] = 0x0;
+ /* New meaning for keys */
+ for (x = 0; x < 5; x++)
+ keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
+ keys[6] = 0x0;
+ keys[7] = 0x0;
- if (!vms->curmsg) {
- /* No prev key, provide "Folder" instead */
- keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
- }
- if (vms->curmsg >= vms->lastmsg) {
- /* If last message ... */
- if (vms->curmsg) {
- /* but not only message, provide "Folder" instead */
- keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ if (!vms->curmsg) {
+ /* No prev key, provide "Folder" instead */
+ keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
+ }
+ if (vms->curmsg >= vms->lastmsg) {
+ /* If last message ... */
+ if (vms->curmsg) {
+ /* but not only message, provide "Folder" instead */
+ keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- } else {
- /* Otherwise if only message, leave blank */
- keys[3] = 1;
+ } else {
+ /* Otherwise if only message, leave blank */
+ keys[3] = 1;
+ }
}
- }
- if (!ast_strlen_zero(cid)) {
- ast_callerid_parse(cid, &name, &num);
- if (!name)
- name = num;
- } else
- name = "Unknown Caller";
+ if (!ast_strlen_zero(cid)) {
+ ast_callerid_parse(cid, &name, &num);
+ if (!name)
+ name = num;
+ } else
+ name = "Unknown Caller";
- /* If deleted, show "undeleted" */
+ /* If deleted, show "undeleted" */
- if (vms->deleted[vms->curmsg])
- keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
+ if (vms->deleted[vms->curmsg])
+ keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
- /* Except "Exit" */
- keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
- snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
- strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
- snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
+ /* Except "Exit" */
+ keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
+ snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
+ strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
+ snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_set_keys(buf + bytes, keys);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_set_keys(buf + bytes, keys);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ }
-static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
-{
- int bytes = 0;
- unsigned char buf[256];
- unsigned char keys[8];
+ static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
+ {
+ int bytes = 0;
+ unsigned char buf[256];
+ unsigned char keys[8];
- int x;
+ int x;
- if (!ast_adsi_available(chan))
- return;
+ if (!ast_adsi_available(chan))
+ return;
- /* New meaning for keys */
- for (x = 0; x < 5; x++)
- keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
+ /* New meaning for keys */
+ for (x = 0; x < 5; x++)
+ keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
- keys[6] = 0x0;
- keys[7] = 0x0;
+ keys[6] = 0x0;
+ keys[7] = 0x0;
- if (!vms->curmsg) {
- /* No prev key, provide "Folder" instead */
- keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
- }
- if (vms->curmsg >= vms->lastmsg) {
- /* If last message ... */
- if (vms->curmsg) {
- /* but not only message, provide "Folder" instead */
- keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
- } else {
- /* Otherwise if only message, leave blank */
- keys[3] = 1;
+ if (!vms->curmsg) {
+ /* No prev key, provide "Folder" instead */
+ keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
+ }
+ if (vms->curmsg >= vms->lastmsg) {
+ /* If last message ... */
+ if (vms->curmsg) {
+ /* but not only message, provide "Folder" instead */
+ keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
+ } else {
+ /* Otherwise if only message, leave blank */
+ keys[3] = 1;
+ }
}
- }
- /* If deleted, show "undeleted" */
- if (vms->deleted[vms->curmsg])
- keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
+ /* If deleted, show "undeleted" */
+ if (vms->deleted[vms->curmsg])
+ keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
- /* Except "Exit" */
- keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
- bytes += ast_adsi_set_keys(buf + bytes, keys);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ /* Except "Exit" */
+ keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
+ bytes += ast_adsi_set_keys(buf + bytes, keys);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ }
-static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
-{
- unsigned char buf[256] = "";
- char buf1[256] = "", buf2[256] = "";
- int bytes = 0;
- unsigned char keys[8];
- int x;
+ static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
+ {
+ unsigned char buf[256] = "";
+ char buf1[256] = "", buf2[256] = "";
+ int bytes = 0;
+ unsigned char keys[8];
+ int x;
- char *newm = (vms->newmessages == 1) ? "message" : "messages";
- char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
- if (!ast_adsi_available(chan))
- return;
- if (vms->newmessages) {
- snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
- if (vms->oldmessages) {
- strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
- snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
+ char *newm = (vms->newmessages == 1) ? "message" : "messages";
+ char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
+ if (!ast_adsi_available(chan))
+ return;
+ if (vms->newmessages) {
+ snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
+ if (vms->oldmessages) {
+ strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
+ snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
+ } else {
+ snprintf(buf2, sizeof(buf2), "%s.", newm);
+ }
+ } else if (vms->oldmessages) {
+ snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
+ snprintf(buf2, sizeof(buf2), "%s.", oldm);
} else {
- snprintf(buf2, sizeof(buf2), "%s.", newm);
+ strcpy(buf1, "You have no messages.");
+ buf2[0] = ' ';
+ buf2[1] = '\0';
}
- } else if (vms->oldmessages) {
- snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
- snprintf(buf2, sizeof(buf2), "%s.", oldm);
- } else {
- strcpy(buf1, "You have no messages.");
- buf2[0] = ' ';
- buf2[1] = '\0';
- }
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- for (x = 0; x < 6; x++)
- keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
- keys[6] = 0;
- keys[7] = 0;
+ for (x = 0; x < 6; x++)
+ keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
+ keys[6] = 0;
+ keys[7] = 0;
- /* Don't let them listen if there are none */
- if (vms->lastmsg < 0)
- keys[0] = 1;
- bytes += ast_adsi_set_keys(buf + bytes, keys);
+ /* Don't let them listen if there are none */
+ if (vms->lastmsg < 0)
+ keys[0] = 1;
+ bytes += ast_adsi_set_keys(buf + bytes, keys);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ }
-static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
-{
- unsigned char buf[256] = "";
- char buf1[256] = "", buf2[256] = "";
- int bytes = 0;
- unsigned char keys[8];
- int x;
+ static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
+ {
+ unsigned char buf[256] = "";
+ char buf1[256] = "", buf2[256] = "";
+ int bytes = 0;
+ unsigned char keys[8];
+ int x;
- char *mess = (vms->lastmsg == 0) ? "message" : "messages";
+ char *mess = (vms->lastmsg == 0) ? "message" : "messages";
- if (!ast_adsi_available(chan))
- return;
+ if (!ast_adsi_available(chan))
+ return;
- /* Original command keys */
- for (x = 0; x < 6; x++)
- keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
+ /* Original command keys */
+ for (x = 0; x < 6; x++)
+ keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
- keys[6] = 0;
- keys[7] = 0;
+ keys[6] = 0;
+ keys[7] = 0;
- if ((vms->lastmsg + 1) < 1)
- keys[0] = 0;
+ if ((vms->lastmsg + 1) < 1)
+ keys[0] = 0;
- snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
- strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
+ snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
+ strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
- if (vms->lastmsg + 1)
- snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
- else
- strcpy(buf2, "no messages.");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_set_keys(buf + bytes, keys);
+ if (vms->lastmsg + 1)
+ snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
+ else
+ strcpy(buf2, "no messages.");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_set_keys(buf + bytes, keys);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-
-}
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+
+ }
-/*
-static void adsi_clear(struct ast_channel *chan)
-{
- char buf[256];
- int bytes = 0;
- if (!ast_adsi_available(chan))
- return;
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ /*
+ static void adsi_clear(struct ast_channel *chan)
+ {
+ char buf[256];
+ int bytes = 0;
+ if (!ast_adsi_available(chan))
+ return;
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
-*/
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ }
+ */
-static void adsi_goodbye(struct ast_channel *chan)
-{
- unsigned char buf[256];
- int bytes = 0;
+ static void adsi_goodbye(struct ast_channel *chan)
+ {
+ unsigned char buf[256];
+ int bytes = 0;
- if (!ast_adsi_available(chan))
- return;
- bytes += adsi_logo(buf + bytes);
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
- bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
- bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
- bytes += ast_adsi_voice_mode(buf + bytes, 0);
+ if (!ast_adsi_available(chan))
+ return;
+ bytes += adsi_logo(buf + bytes);
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
+ bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
+ bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
+ bytes += ast_adsi_voice_mode(buf + bytes, 0);
- ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
+ ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
+ }
-/*!\brief get_folder: Folder menu
- * Plays "press 1 for INBOX messages" etc.
- * Should possibly be internationalized
- */
-static int get_folder(struct ast_channel *chan, int start)
-{
- int x;
- int d;
- char fn[PATH_MAX];
- d = ast_play_and_wait(chan, "vm-press"); /* "Press" */
- if (d)
- return d;
- for (x = start; x < 5; x++) { /* For all folders */
- if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
- return d;
- d = ast_play_and_wait(chan, "vm-for"); /* "for" */
- if (d)
- return d;
- snprintf(fn, sizeof(fn), "vm-%s", mbox(x)); /* Folder name */
- d = vm_play_folder_name(chan, fn);
+ /*!\brief get_folder: Folder menu
+ * Plays "press 1 for INBOX messages" etc.
+ * Should possibly be internationalized
+ */
+ static int get_folder(struct ast_channel *chan, int start)
+ {
+ int x;
+ int d;
+ char fn[PATH_MAX];
+ d = ast_play_and_wait(chan, "vm-press"); /* "Press" */
if (d)
return d;
- d = ast_waitfordigit(chan, 500);
+ for (x = start; x < 5; x++) { /* For all folders */
+ if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
+ return d;
+ d = ast_play_and_wait(chan, "vm-for"); /* "for" */
+ if (d)
+ return d;
+ snprintf(fn, sizeof(fn), "vm-%s", mbox(x)); /* Folder name */
+ d = vm_play_folder_name(chan, fn);
+ if (d)
+ return d;
+ d = ast_waitfordigit(chan, 500);
+ if (d)
+ return d;
+ }
+ d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
if (d)
return d;
- }
- d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
- if (d)
+ d = ast_waitfordigit(chan, 4000);
return d;
- d = ast_waitfordigit(chan, 4000);
- return d;
-}
-
-static int get_folder2(struct ast_channel *chan, char *fn, int start)
-{
- int res = 0;
- res = ast_play_and_wait(chan, fn); /* Folder name */
- while (((res < '0') || (res > '9')) &&
- (res != '#') && (res >= 0)) {
- res = get_folder(chan, 0);
}
- return res;
-}
-static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vmfmts,
- char *context, signed char record_gain, long *duration, struct vm_state *vms)
-{
- int cmd = 0;
- int retries = 0, prepend_duration = 0, already_recorded = 0;
- signed char zero_gain = 0;
- struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
- struct ast_config *msg_cfg;
- const char *duration_str;
- char msgfile[PATH_MAX], backup[PATH_MAX];
- char textfile[PATH_MAX];
-
- /* Must always populate duration correctly */
- make_file(msgfile, sizeof(msgfile), curdir, curmsg);
- strcpy(textfile, msgfile);
- strcpy(backup, msgfile);
- strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
- strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
-
- if ((msg_cfg = ast_config_load(textfile, config_flags)) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
- *duration = atoi(duration_str);
- } else {
- *duration = 0;
+ static int get_folder2(struct ast_channel *chan, char *fn, int start)
+ {
+ int res = 0;
+ res = ast_play_and_wait(chan, fn); /* Folder name */
+ while (((res < '0') || (res > '9')) &&
+ (res != '#') && (res >= 0)) {
+ res = get_folder(chan, 0);
+ }
+ return res;
}
- while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
- if (cmd)
- retries = 0;
- switch (cmd) {
- case '1':
- /* prepend a message to the current message, update the metadata and return */
- prepend_duration = 0;
-
- /* if we can't read the message metadata, stop now */
- if (!msg_cfg) {
- cmd = 0;
- break;
- }
-
- /* Back up the original file, so we can retry the prepend */
- if (already_recorded)
- ast_filecopy(backup, msgfile, NULL);
- else
- ast_filecopy(msgfile, backup, NULL);
- already_recorded = 1;
+ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vmfmts,
+ char *context, signed char record_gain, long *duration, struct vm_state *vms)
+ {
+ int cmd = 0;
+ int retries = 0, prepend_duration = 0, already_recorded = 0;
+ signed char zero_gain = 0;
+ struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
+ struct ast_config *msg_cfg;
+ const char *duration_str;
+ char msgfile[PATH_MAX], backup[PATH_MAX];
+ char textfile[PATH_MAX];
+
+ /* Must always populate duration correctly */
+ make_file(msgfile, sizeof(msgfile), curdir, curmsg);
+ strcpy(textfile, msgfile);
+ strcpy(backup, msgfile);
+ strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
+ strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
+
+ if ((msg_cfg = ast_config_load(textfile, config_flags)) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
+ *duration = atoi(duration_str);
+ } else {
+ *duration = 0;
+ }
- if (record_gain)
- ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
+ while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
+ if (cmd)
+ retries = 0;
+ switch (cmd) {
+ case '1':
+ /* prepend a message to the current message, update the metadata and return */
+ prepend_duration = 0;
- cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vmfmts, &prepend_duration, 1, silencethreshold, maxsilence);
- if (record_gain)
- ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
+ /* if we can't read the message metadata, stop now */
+ if (!msg_cfg) {
+ cmd = 0;
+ break;
+ }
- if (prepend_duration) {
- struct ast_category *msg_cat;
- /* need enough space for a maximum-length message duration */
- char duration_str[12];
-
- prepend_duration += *duration;
- msg_cat = ast_category_get(msg_cfg, "message");
- snprintf(duration_str, sizeof(duration_str), "%d", prepend_duration);
- if (!ast_variable_update(msg_cat, "duration", duration_str, NULL, 0)) {
- config_text_file_save(textfile, msg_cfg, "app_voicemail");
- STORE(curdir, vmu->mailbox, context, curmsg, chan, vmu, vmfmts, prepend_duration, vms);
+ /* Back up the original file, so we can retry the prepend */
+ if (already_recorded)
+ ast_filecopy(backup, msgfile, NULL);
+ else
+ ast_filecopy(msgfile, backup, NULL);
+ already_recorded = 1;
+
+ if (record_gain)
+ ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
+
+ cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vmfmts, &prepend_duration, 1, silencethreshold, maxsilence);
+ if (record_gain)
+ ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
+
+ if (prepend_duration) {
+ struct ast_category *msg_cat;
+ /* need enough space for a maximum-length message duration */
+ char duration_str[12];
+
+ prepend_duration += *duration;
+ msg_cat = ast_category_get(msg_cfg, "message");
+ snprintf(duration_str, sizeof(duration_str), "%d", prepend_duration);
+ if (!ast_variable_update(msg_cat, "duration", duration_str, NULL, 0)) {
+ config_text_file_save(textfile, msg_cfg, "app_voicemail");
+ STORE(curdir, vmu->mailbox, context, curmsg, chan, vmu, vmfmts, prepend_duration, vms);
+ }
}
- }
- break;
- case '2':
- cmd = 't';
- break;
- case '*':
- cmd = '*';
- break;
- default:
- cmd = ast_play_and_wait(chan, "vm-forwardoptions");
- /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
- if (!cmd)
- cmd = ast_play_and_wait(chan, "vm-starmain");
- /* "press star to return to the main menu" */
- if (!cmd)
- cmd = ast_waitfordigit(chan, 6000);
- if (!cmd)
- retries++;
- if (retries > 3)
+ break;
+ case '2':
cmd = 't';
+ break;
+ case '*':
+ cmd = '*';
+ break;
+ default:
+ cmd = ast_play_and_wait(chan, "vm-forwardoptions");
+ /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
+ if (!cmd)
+ cmd = ast_play_and_wait(chan, "vm-starmain");
+ /* "press star to return to the main menu" */
+ if (!cmd)
+ cmd = ast_waitfordigit(chan, 6000);
+ if (!cmd)
+ retries++;
+ if (retries > 3)
+ cmd = 't';
+ }
}
- }
- if (msg_cfg)
- ast_config_destroy(msg_cfg);
- if (already_recorded)
- ast_filedelete(backup, NULL);
- if (prepend_duration)
- *duration = prepend_duration;
+ if (msg_cfg)
+ ast_config_destroy(msg_cfg);
+ if (already_recorded)
+ ast_filedelete(backup, NULL);
+ if (prepend_duration)
+ *duration = prepend_duration;
- if (cmd == 't' || cmd == 'S')
- cmd = 0;
- return cmd;
-}
+ if (cmd == 't' || cmd == 'S')
+ cmd = 0;
+ return cmd;
+ }
-static void queue_mwi_event(const char *mbox, int new, int old)
-{
- struct ast_event *event;
- char *mailbox, *context;
+ static void queue_mwi_event(const char *mbox, int new, int old)
+ {
+ struct ast_event *event;
+ char *mailbox, *context;
- /* Strip off @default */
- context = mailbox = ast_strdupa(mbox);
- strsep(&context, "@");
- if (ast_strlen_zero(context))
- context = "default";
+ /* Strip off @default */
+ context = mailbox = ast_strdupa(mbox);
+ strsep(&context, "@");
+ if (ast_strlen_zero(context))
+ context = "default";
- if (!(event = ast_event_new(AST_EVENT_MWI,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, new,
- AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
- AST_EVENT_IE_END))) {
- return;
- }
+ if (!(event = ast_event_new(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+ AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, new,
+ AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
+ AST_EVENT_IE_END))) {
+ return;
+ }
- ast_event_queue_and_cache(event,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_END);
-}
+ ast_event_queue_and_cache(event,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
+ AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
+ AST_EVENT_IE_END);
+ }
-static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
-{
- char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
- int newmsgs = 0, oldmsgs = 0;
- const char *category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
- char *myserveremail = serveremail;
+ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
+ {
+ char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
+ int newmsgs = 0, oldmsgs = 0;
+ const char *category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
+ char *myserveremail = serveremail;
- make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
- make_file(fn, sizeof(fn), todir, msgnum);
- snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
+ make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
+ make_file(fn, sizeof(fn), todir, msgnum);
+ snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
- if (!ast_strlen_zero(vmu->attachfmt)) {
- if (strstr(fmt, vmu->attachfmt))
- fmt = vmu->attachfmt;
- else
- ast_log(LOG_WARNING, "Attachment format '%s' is not one of the recorded formats '%s'. Falling back to default format for '%s@%s'.\n", vmu->attachfmt, fmt, vmu->mailbox, vmu->context);
- }
+ if (!ast_strlen_zero(vmu->attachfmt)) {
+ if (strstr(fmt, vmu->attachfmt))
+ fmt = vmu->attachfmt;
+ else
+ ast_log(LOG_WARNING, "Attachment format '%s' is not one of the recorded formats '%s'. Falling back to default format for '%s@%s'.\n", vmu->attachfmt, fmt, vmu->mailbox, vmu->context);
+ }
- /* Attach only the first format */
- fmt = ast_strdupa(fmt);
- stringp = fmt;
- strsep(&stringp, "|");
+ /* Attach only the first format */
+ fmt = ast_strdupa(fmt);
+ stringp = fmt;
+ strsep(&stringp, "|");
- if (!ast_strlen_zero(vmu->serveremail))
- myserveremail = vmu->serveremail;
+ if (!ast_strlen_zero(vmu->serveremail))
+ myserveremail = vmu->serveremail;
- if (!ast_strlen_zero(vmu->email)) {
- int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
- if (!attach_user_voicemail)
- attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
+ if (!ast_strlen_zero(vmu->email)) {
+ int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
+ if (!attach_user_voicemail)
+ attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
- if (attach_user_voicemail)
- RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
+ if (attach_user_voicemail)
+ RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
- /* XXX possible imap issue, should category be NULL XXX */
- sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, fn, fmt, duration, attach_user_voicemail, chan, category);
+ /* XXX possible imap issue, should category be NULL XXX */
+ sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, fn, fmt, duration, attach_user_voicemail, chan, category);
- if (attach_user_voicemail)
- DISPOSE(todir, msgnum);
- }
+ if (attach_user_voicemail)
+ DISPOSE(todir, msgnum);
+ }
- if (!ast_strlen_zero(vmu->pager))
- sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, duration, vmu, category);
+ if (!ast_strlen_zero(vmu->pager))
+ sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, duration, vmu, category);
- if (ast_test_flag(vmu, VM_DELETE))
- DELETE(todir, msgnum, fn);
+ if (ast_test_flag(vmu, VM_DELETE))
+ DELETE(todir, msgnum, fn, vmu);
- /* Leave voicemail for someone */
- if (ast_app_has_voicemail(ext_context, NULL))
- ast_app_inboxcount(ext_context, &newmsgs, &oldmsgs);
+ /* Leave voicemail for someone */
+ if (ast_app_has_voicemail(ext_context, NULL))
+ ast_app_inboxcount(ext_context, &newmsgs, &oldmsgs);
- queue_mwi_event(ext_context, newmsgs, oldmsgs);
+ queue_mwi_event(ext_context, newmsgs, oldmsgs);
- manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
- run_externnotify(vmu->context, vmu->mailbox);
+ manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
+ run_externnotify(vmu->context, vmu->mailbox);
-#ifdef IMAP_STORAGE
- DELETE(todir, msgnum, fn); /* Delete the file, but not the IMAP message */
- if (ast_test_flag(vmu, VM_DELETE)) { /* Delete the IMAP message if delete = yes */
- IMAP_DELETE(vms->curdir, vms->curmsg, vms->fn, vms);
- vms->newmessages--; /* Fix new message count */
+ return 0;
}
-#endif
- return 0;
-}
-static int forward_message(struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int flag, signed char record_gain)
-{
+ static int forward_message(struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int flag, signed char record_gain)
+ {
#ifdef IMAP_STORAGE
- BODY *body;
- char *header_content;
- char *temp;
- char todir[256];
- int todircount = 0;
- struct vm_state *dstvms;
+ int todircount = 0;
+ struct vm_state *dstvms;
#endif
- char username[70] = "";
- char fn[PATH_MAX]; /* for playback of name greeting */
- char ecodes[16] = "#";
- int res = 0, cmd = 0;
- struct ast_vm_user *receiver = NULL, *vmtmp;
- AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
- char *stringp;
- const char *s;
- int saved_messages = 0, found = 0;
- int valid_extensions = 0;
- char *dir;
- int curmsg;
-
- if (vms == NULL) return -1;
- dir = vms->curdir;
- curmsg = vms->curmsg;
-
- while (!res && !valid_extensions) {
- int use_directory = 0;
- if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
- int done = 0;
- int retries = 0;
- cmd = 0;
- while ((cmd >= 0) && !done) {
- if (cmd)
- retries = 0;
- switch (cmd) {
- case '1':
- use_directory = 0;
- done = 1;
- break;
- case '2':
- use_directory = 1;
- done = 1;
- break;
- case '*':
- cmd = 't';
- done = 1;
- break;
- default:
- /* Press 1 to enter an extension press 2 to use the directory */
- cmd = ast_play_and_wait(chan, "vm-forward");
- if (!cmd)
- cmd = ast_waitfordigit(chan, 3000);
- if (!cmd)
- retries++;
- if (retries > 3) {
+ char username[70] = "";
+ char fn[PATH_MAX]; /* for playback of name greeting */
+ char ecodes[16] = "#";
+ int res = 0, cmd = 0;
+ struct ast_vm_user *receiver = NULL, *vmtmp;
+ AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
+ char *stringp;
+ const char *s;
+ int saved_messages = 0, found = 0;
+ int valid_extensions = 0;
+ char *dir;
+ int curmsg;
+
+ if (vms == NULL) return -1;
+ dir = vms->curdir;
+ curmsg = vms->curmsg;
+
+ while (!res && !valid_extensions) {
+ int use_directory = 0;
+ if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
+ int done = 0;
+ int retries = 0;
+ cmd = 0;
+ while ((cmd >= 0) && !done) {
+ if (cmd)
+ retries = 0;
+ switch (cmd) {
+ case '1':
+ use_directory = 0;
+ done = 1;
+ break;
+ case '2':
+ use_directory = 1;
+ done = 1;
+ break;
+ case '*':
cmd = 't';
done = 1;
+ break;
+ default:
+ /* Press 1 to enter an extension press 2 to use the directory */
+ cmd = ast_play_and_wait(chan, "vm-forward");
+ if (!cmd)
+ cmd = ast_waitfordigit(chan, 3000);
+ if (!cmd)
+ retries++;
+ if (retries > 3) {
+ cmd = 't';
+ done = 1;
+ }
+
}
-
}
+ if (cmd < 0 || cmd == 't')
+ break;
}
- if (cmd < 0 || cmd == 't')
- break;
- }
-
- if (use_directory) {
- /* use app_directory */
-
- char old_context[sizeof(chan->context)];
- char old_exten[sizeof(chan->exten)];
- int old_priority;
- struct ast_app* app;
-
- app = pbx_findapp("Directory");
- if (app) {
- char vmcontext[256];
- /* make backup copies */
- memcpy(old_context, chan->context, sizeof(chan->context));
- memcpy(old_exten, chan->exten, sizeof(chan->exten));
- old_priority = chan->priority;
+ if (use_directory) {
+ /* use app_directory */
- /* call the the Directory, changes the channel */
- snprintf(vmcontext, sizeof(vmcontext), "%s||v", context ? context : "default");
- res = pbx_exec(chan, app, vmcontext);
-
- ast_copy_string(username, chan->exten, sizeof(username));
-
- /* restore the old context, exten, and priority */
- memcpy(chan->context, old_context, sizeof(chan->context));
- memcpy(chan->exten, old_exten, sizeof(chan->exten));
- chan->priority = old_priority;
+ char old_context[sizeof(chan->context)];
+ char old_exten[sizeof(chan->exten)];
+ int old_priority;
+ struct ast_app* app;
+
+ app = pbx_findapp("Directory");
+ if (app) {
+ char vmcontext[256];
+ /* make backup copies */
+ memcpy(old_context, chan->context, sizeof(chan->context));
+ memcpy(old_exten, chan->exten, sizeof(chan->exten));
+ old_priority = chan->priority;
+
+ /* call the the Directory, changes the channel */
+ snprintf(vmcontext, sizeof(vmcontext), "%s||v", context ? context : "default");
+ res = pbx_exec(chan, app, vmcontext);
+
+ ast_copy_string(username, chan->exten, sizeof(username));
+
+ /* restore the old context, exten, and priority */
+ memcpy(chan->context, old_context, sizeof(chan->context));
+ memcpy(chan->exten, old_exten, sizeof(chan->exten));
+ chan->priority = old_priority;
+
+ } else {
+ ast_log(LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
+ ast_clear_flag((&globalflags), VM_DIRECFORWARD);
+ }
} else {
- ast_log(LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
- ast_clear_flag((&globalflags), VM_DIRECFORWARD);
- }
- } else {
- /* Ask for an extension */
- res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
- if (res)
- break;
- if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
- break;
- }
-
- /* start all over if no username */
- if (ast_strlen_zero(username))
- continue;
- stringp = username;
- s = strsep(&stringp, "*");
- /* start optimistic */
- valid_extensions = 1;
- while (s) {
- /* Don't forward to ourselves but allow leaving a message for ourselves (flag == 1). find_user is going to malloc since we have a NULL as first argument */
- if ((flag == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
- AST_LIST_INSERT_HEAD(&extensions, receiver, list);
- found++;
- } else {
- valid_extensions = 0;
- break;
+ /* Ask for an extension */
+ res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
+ if (res)
+ break;
+ if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
+ break;
}
+
+ /* start all over if no username */
+ if (ast_strlen_zero(username))
+ continue;
+ stringp = username;
+ s = strsep(&stringp, "*");
+ /* start optimistic */
+ valid_extensions = 1;
+ while (s) {
+ /* Don't forward to ourselves but allow leaving a message for ourselves (flag == 1). find_user is going to malloc since we have a NULL as first argument */
+ if ((flag == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
+ AST_LIST_INSERT_HEAD(&extensions, receiver, list);
+ found++;
+ } else {
+ valid_extensions = 0;
+ break;
+ }
- /* play name if available, else play extension number */
- snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
- RETRIEVE(fn, -1, s, receiver->context);
- if (ast_fileexists(fn, NULL, NULL) > 0) {
- res = ast_stream_and_wait(chan, fn, ecodes);
- if (res) {
+ /* play name if available, else play extension number */
+ snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
+ RETRIEVE(fn, -1, s, receiver->context);
+ if (ast_fileexists(fn, NULL, NULL) > 0) {
+ res = ast_stream_and_wait(chan, fn, ecodes);
+ if (res) {
+ DISPOSE(fn, -1);
+ return res;
+ }
+ } else {
+ /* Dispose just in case */
DISPOSE(fn, -1);
- return res;
+ res = ast_say_digit_str(chan, s, ecodes, chan->language);
}
- } else {
- /* Dispose just in case */
- DISPOSE(fn, -1);
- res = ast_say_digit_str(chan, s, ecodes, chan->language);
- }
- s = strsep(&stringp, "*");
+ s = strsep(&stringp, "*");
+ }
+ /* break from the loop of reading the extensions */
+ if (valid_extensions)
+ break;
+ /* "I am sorry, that's not a valid extension. Please try again." */
+ res = ast_play_and_wait(chan, "pbx-invalid");
}
- /* break from the loop of reading the extensions */
- if (valid_extensions)
- break;
- /* "I am sorry, that's not a valid extension. Please try again." */
- res = ast_play_and_wait(chan, "pbx-invalid");
- }
- /* check if we're clear to proceed */
- if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
- return res;
- if (flag==1) {
- struct leave_vm_options leave_options;
- char mailbox[AST_MAX_EXTENSION * 2 + 2];
- /* Make sure that context doesn't get set as a literal "(null)" (or else find_user won't find it) */
- if (context)
- snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
- else
- ast_copy_string(mailbox, username, sizeof(mailbox));
-
- /* Send VoiceMail */
- memset(&leave_options, 0, sizeof(leave_options));
- leave_options.record_gain = record_gain;
- cmd = leave_voicemail(chan, mailbox, &leave_options);
- } else {
- /* Forward VoiceMail */
- long duration = 0;
- char origmsgfile[PATH_MAX], msgfile[PATH_MAX];
- struct vm_state vmstmp;
- memcpy(&vmstmp, vms, sizeof(vmstmp));
-
- make_file(origmsgfile, sizeof(origmsgfile), dir, curmsg);
- create_dirpath(vmstmp.curdir, sizeof(vmstmp.curdir), sender->context, vmstmp.username, "tmp");
- make_file(msgfile, sizeof(msgfile), vmstmp.curdir, curmsg);
-
- RETRIEVE(dir, curmsg, sender->mailbox, context);
+ /* check if we're clear to proceed */
+ if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
+ return res;
+ if (flag==1) {
+ struct leave_vm_options leave_options;
+ char mailbox[AST_MAX_EXTENSION * 2 + 2];
+ /* Make sure that context doesn't get set as a literal "(null)" (or else find_user won't find it) */
+ if (context)
+ snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
+ else
+ ast_copy_string(mailbox, username, sizeof(mailbox));
- /* Alter a surrogate file, only */
- copy_plain_file(origmsgfile, msgfile);
+ /* Send VoiceMail */
+ memset(&leave_options, 0, sizeof(leave_options));
+ leave_options.record_gain = record_gain;
+ cmd = leave_voicemail(chan, mailbox, &leave_options);
+ } else {
+ /* Forward VoiceMail */
+ long duration = 0;
+ char origmsgfile[PATH_MAX], msgfile[PATH_MAX];
+ struct vm_state vmstmp;
+ memcpy(&vmstmp, vms, sizeof(vmstmp));
+
+ make_file(origmsgfile, sizeof(origmsgfile), dir, curmsg);
+ create_dirpath(vmstmp.curdir, sizeof(vmstmp.curdir), sender->context, vmstmp.username, "tmp");
+ make_file(msgfile, sizeof(msgfile), vmstmp.curdir, curmsg);
+
+ RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
+
+ /* Alter a surrogate file, only */
+ copy_plain_file(origmsgfile, msgfile);
- cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp);
- if (!cmd) {
- AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
+ cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp);
+ if (!cmd) {
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
#ifdef IMAP_STORAGE
- char *myserveremail = serveremail;
- int attach_user_voicemail;
- char buf[1024] = "";
-
- /* Need to get message content */
- ast_debug(3, "Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", vms->curmsg, vms->msgArray[vms->curmsg]);
- if (!vms->msgArray[vms->curmsg]) {
- ast_log(LOG_WARNING, "Trying to access unknown message\n");
- return -1;
- }
-
- /* This will only work for new messages... */
- header_content = mail_fetchheader (vms->mailstream, vms->msgArray[vms->curmsg]);
- /* empty string means no valid header */
- if (ast_strlen_zero(header_content)) {
- ast_log(LOG_ERROR, "Could not fetch header for message number %ld\n", vms->msgArray[vms->curmsg]);
- return -1;
- }
- /* Get header info needed by sendmail */
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:", buf, sizeof(buf))))
- duration = atoi(temp);
- else
- duration = 0;
-
- /* Attach only the first format */
- if ((fmt = ast_strdupa(fmt))) {
- stringp = fmt;
- strsep(&stringp, "|");
- } else {
- ast_log(LOG_ERROR, "audio format not set. Default to WAV\n");
- fmt = "WAV";
- }
- if (!strcasecmp(fmt, "wav49"))
- fmt = "WAV";
- ast_debug(3, "**** format set to %s, vmfmts set to %s\n", fmt, vmfmts);
- snprintf(todir, sizeof(todir), "%s%s/%s/tmp", VM_SPOOL_DIR, vmtmp->context, vmtmp->mailbox);
- make_gsm_file(vms->fn, sizeof(vms->fn), vms->imapuser, todir, vms->curmsg);
-
- ast_debug(3, "Before mail_fetchstructure, message number is %ld, filename is:%s\n", vms->msgArray[vms->curmsg], vms->fn);
- mail_fetchstructure(vms->mailstream, vms->msgArray[vms->curmsg], &body);
- save_body(body, vms, "3", "gsm");
- /* should not assume "fmt" here! */
- save_body(body, vms, "2", fmt);
-
- /* get destination mailbox */
- dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, 0);
- if (!dstvms) {
- dstvms = create_vm_state_from_user(vmtmp, vmtmp->mailbox);
- }
- if (dstvms) {
- init_mailstream(dstvms, 0);
- if (!dstvms->mailstream) {
- ast_log(LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
+ char *myserveremail = serveremail;
+ int attach_user_voicemail;
+ /* get destination mailbox */
+ dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, 0);
+ if (!dstvms) {
+ dstvms = create_vm_state_from_user(vmtmp);
+ }
+ if (dstvms) {
+ init_mailstream(dstvms, 0);
+ if (!dstvms->mailstream) {
+ ast_log(LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
+ } else {
+ STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms);
+ run_externnotify(vmtmp->context, vmtmp->mailbox);
+ }
} else {
- STORE(todir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms);
- run_externnotify(vmtmp->context, vmtmp->mailbox);
+ ast_log(LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
}
- } else {
- ast_log(LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
- }
-
- if (!ast_strlen_zero(vmtmp->serveremail))
- myserveremail = vmtmp->serveremail;
- attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
- /* NULL category for IMAP storage */
- sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vms->fn, fmt, duration, attach_user_voicemail, chan, NULL);
-
+ if (!ast_strlen_zero(vmtmp->serveremail))
+ myserveremail = vmtmp->serveremail;
+ attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
+ /* NULL category for IMAP storage */
+ sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vms->fn, fmt, duration, attach_user_voicemail, chan, NULL);
#else
- copy_message(chan, sender, -1, curmsg, duration, vmtmp, fmt, vmstmp.curdir);
+ copy_message(chan, sender, -1, curmsg, duration, vmtmp, fmt, vmstmp.curdir);
#endif
- saved_messages++;
- AST_LIST_REMOVE_CURRENT(list);
- free_user(vmtmp);
- if (res)
- break;
+ saved_messages++;
+ AST_LIST_REMOVE_CURRENT(list);
+ free_user(vmtmp);
+ if (res)
+ break;
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+ if (saved_messages > 0) {
+ /* give confirmation that the message was saved */
+ /* commented out since we can't forward batches yet
+ if (saved_messages == 1)
+ res = ast_play_and_wait(chan, "vm-message");
+ else
+ res = ast_play_and_wait(chan, "vm-messages");
+ if (!res)
+ res = ast_play_and_wait(chan, "vm-saved"); */
+ res = ast_play_and_wait(chan, "vm-msgsaved");
+ }
}
- AST_LIST_TRAVERSE_SAFE_END;
- if (saved_messages > 0) {
- /* give confirmation that the message was saved */
- /* commented out since we can't forward batches yet
- if (saved_messages == 1)
- res = ast_play_and_wait(chan, "vm-message");
- else
- res = ast_play_and_wait(chan, "vm-messages");
- if (!res)
- res = ast_play_and_wait(chan, "vm-saved"); */
- res = ast_play_and_wait(chan, "vm-msgsaved");
- }
+ /* Remove surrogate file */
+ DISPOSE(dir, curmsg);
}
- /* Remove surrogate file */
- vm_delete(msgfile);
+ /* If anything failed above, we still have this list to free */
+ while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
+ free_user(vmtmp);
+ return res ? res : cmd;
}
- /* If anything failed above, we still have this list to free */
- while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
- free_user(vmtmp);
- return res ? res : cmd;
-}
+ static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
+ {
+ int res;
+ if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0)
+ ast_log(LOG_WARNING, "Unable to play message %s\n", file);
+ return res;
+ }
-static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
-{
- int res;
- if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0)
- ast_log(LOG_WARNING, "Unable to play message %s\n", file);
- return res;
-}
+ static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
+ {
+ return ast_control_streamfile(chan, file, listen_control_forward_key, listen_control_reverse_key, listen_control_stop_key, listen_control_pause_key, listen_control_restart_key, skipms, NULL);
+ }
-static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
-{
- return ast_control_streamfile(chan, file, listen_control_forward_key, listen_control_reverse_key, listen_control_stop_key, listen_control_pause_key, listen_control_restart_key, skipms, NULL);
-}
+ static int play_message_category(struct ast_channel *chan, const char *category)
+ {
+ int res = 0;
-static int play_message_category(struct ast_channel *chan, const char *category)
-{
- int res = 0;
+ if (!ast_strlen_zero(category))
+ res = ast_play_and_wait(chan, category);
- if (!ast_strlen_zero(category))
- res = ast_play_and_wait(chan, category);
+ if (res) {
+ ast_log(LOG_WARNING, "No sound file for category '%s' was found.\n", category);
+ res = 0;
+ }
- if (res) {
- ast_log(LOG_WARNING, "No sound file for category '%s' was found.\n", category);
- res = 0;
+ return res;
}
- return res;
-}
+ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
+ {
+ int res = 0;
+ struct vm_zone *the_zone = NULL;
+ time_t t;
-static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
-{
- int res = 0;
- struct vm_zone *the_zone = NULL;
- time_t t;
-
- if (ast_get_time_t(origtime, &t, 0, NULL)) {
- ast_log(LOG_WARNING, "Couldn't find origtime in %s\n", filename);
- return 0;
- }
+ if (ast_get_time_t(origtime, &t, 0, NULL)) {
+ ast_log(LOG_WARNING, "Couldn't find origtime in %s\n", filename);
+ return 0;
+ }
- /* Does this user have a timezone specified? */
- if (!ast_strlen_zero(vmu->zonetag)) {
- /* Find the zone in the list */
- struct vm_zone *z;
- AST_LIST_LOCK(&zones);
- AST_LIST_TRAVERSE(&zones, z, list) {
- if (!strcmp(z->name, vmu->zonetag)) {
- the_zone = z;
- break;
+ /* Does this user have a timezone specified? */
+ if (!ast_strlen_zero(vmu->zonetag)) {
+ /* Find the zone in the list */
+ struct vm_zone *z;
+ AST_LIST_LOCK(&zones);
+ AST_LIST_TRAVERSE(&zones, z, list) {
+ if (!strcmp(z->name, vmu->zonetag)) {
+ the_zone = z;
+ break;
+ }
}
+ AST_LIST_UNLOCK(&zones);
}
- AST_LIST_UNLOCK(&zones);
- }
-/* No internal variable parsing for now, so we'll comment it out for the time being */
+ /* No internal variable parsing for now, so we'll comment it out for the time being */
#if 0
- /* Set the DIFF_* variables */
- ast_localtime(&t, &time_now, NULL);
- tv_now = ast_tvnow();
- ast_localtime(&tv_now, &time_then, NULL);
-
- /* Day difference */
- if (time_now.tm_year == time_then.tm_year)
- snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
- else
- snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
- pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
+ /* Set the DIFF_* variables */
+ ast_localtime(&t, &time_now, NULL);
+ tv_now = ast_tvnow();
+ ast_localtime(&tv_now, &time_then, NULL);
+
+ /* Day difference */
+ if (time_now.tm_year == time_then.tm_year)
+ snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
+ else
+ snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
+ pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
- /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
+ /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
#endif
- if (the_zone)
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
- else if (!strcasecmp(chan->language, "pl")) /* POLISH syntax */
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
- else if (!strcasecmp(chan->language, "se")) /* SWEDISH syntax */
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
- else if (!strcasecmp(chan->language, "no")) /* NORWEGIAN syntax */
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
- else if (!strcasecmp(chan->language, "de")) /* GERMAN syntax */
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
- else if (!strcasecmp(chan->language, "nl")) /* DUTCH syntax */
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
- else if (!strcasecmp(chan->language, "it")) /* ITALIAN syntax */
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
- else if (!strcasecmp(chan->language, "gr"))
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q H 'digits/kai' M ", NULL);
- else if (!strcasecmp(chan->language, "pt_BR"))
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
- else if (!strcasecmp(chan->language, "tw")) /* CHINESE (Taiwan) syntax */
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
- else
- res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
+ if (the_zone) {
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
+ }
+ else if (!strcasecmp(chan->language,"pl")) /* POLISH syntax */
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
+ else if (!strcasecmp(chan->language, "se")) /* SWEDISH syntax */
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
+ else if (!strcasecmp(chan->language, "no")) /* NORWEGIAN syntax */
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
+ else if (!strcasecmp(chan->language, "de")) /* GERMAN syntax */
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
+ else if (!strcasecmp(chan->language, "nl")) /* DUTCH syntax */
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
+ else if (!strcasecmp(chan->language, "it")) /* ITALIAN syntax */
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
+ else if (!strcasecmp(chan->language, "gr"))
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q H 'digits/kai' M ", NULL);
+ else if (!strcasecmp(chan->language, "pt_BR"))
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
+ else if (!strcasecmp(chan->language, "tw")) /* CHINESE (Taiwan) syntax */
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
+ else {
+ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
+ }
#if 0
- pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
+ pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
#endif
- return res;
-}
+ return res;
+ }
-static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
-{
- int res = 0;
- int i;
- char *callerid, *name;
- char prefile[PATH_MAX] = "";
-
+ static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
+ {
+ int res = 0;
+ int i;
+ char *callerid, *name;
+ char prefile[PATH_MAX] = "";
+
- /* If voicemail cid is not enabled, or we didn't get cid or context from
- * the attribute file, leave now.
- *
- * TODO Still need to change this so that if this function is called by the
- * message envelope (and someone is explicitly requesting to hear the CID),
- * it does not check to see if CID is enabled in the config file.
- */
- if ((cid == NULL)||(context == NULL))
- return res;
+ /* If voicemail cid is not enabled, or we didn't get cid or context from
+ * the attribute file, leave now.
+ *
+ * TODO Still need to change this so that if this function is called by the
+ * message envelope (and someone is explicitly requesting to hear the CID),
+ * it does not check to see if CID is enabled in the config file.
+ */
+ if ((cid == NULL)||(context == NULL))
+ return res;
- /* Strip off caller ID number from name */
- ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
- ast_callerid_parse(cid, &name, &callerid);
- if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
- /* Check for internal contexts and only */
- /* say extension when the call didn't come from an internal context in the list */
- for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++) {
- ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
- if ((strcmp(cidinternalcontexts[i], context) == 0))
- break;
- }
- if (i != MAX_NUM_CID_CONTEXTS) { /* internal context? */
- if (!res) {
- snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
- if (!ast_strlen_zero(prefile)) {
- /* See if we can find a recorded name for this person instead of their extension number */
- if (ast_fileexists(prefile, NULL, NULL) > 0) {
- ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
- if (!callback)
- res = wait_file2(chan, vms, "vm-from");
- res = ast_stream_and_wait(chan, prefile, "");
- } else {
- ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
- /* Say "from extension" as one saying to sound smoother */
- if (!callback)
- res = wait_file2(chan, vms, "vm-from-extension");
- res = ast_say_digit_str(chan, callerid, "", chan->language);
+ /* Strip off caller ID number from name */
+ ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
+ ast_callerid_parse(cid, &name, &callerid);
+ if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
+ /* Check for internal contexts and only */
+ /* say extension when the call didn't come from an internal context in the list */
+ for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++) {
+ ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
+ if ((strcmp(cidinternalcontexts[i], context) == 0))
+ break;
+ }
+ if (i != MAX_NUM_CID_CONTEXTS) { /* internal context? */
+ if (!res) {
+ snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
+ if (!ast_strlen_zero(prefile)) {
+ /* See if we can find a recorded name for this person instead of their extension number */
+ if (ast_fileexists(prefile, NULL, NULL) > 0) {
+ ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
+ if (!callback)
+ res = wait_file2(chan, vms, "vm-from");
+ res = ast_stream_and_wait(chan, prefile, "");
+ } else {
+ ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
+ /* Say "from extension" as one saying to sound smoother */
+ if (!callback)
+ res = wait_file2(chan, vms, "vm-from-extension");
+ res = ast_say_digit_str(chan, callerid, "", chan->language);
+ }
}
}
+ } else if (!res) {
+ ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
+ /* Since this is all nicely figured out, why not say "from phone number" in this case? */
+ if (!callback)
+ res = wait_file2(chan, vms, "vm-from-phonenumber");
+ res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
}
- } else if (!res) {
- ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
- /* Since this is all nicely figured out, why not say "from phone number" in this case? */
- if (!callback)
- res = wait_file2(chan, vms, "vm-from-phonenumber");
- res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
+ } else {
+ /* Number unknown */
+ ast_debug(1, "VM-CID: From an unknown number\n");
+ /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
+ res = wait_file2(chan, vms, "vm-unknown-caller");
}
- } else {
- /* Number unknown */
- ast_debug(1, "VM-CID: From an unknown number\n");
- /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
- res = wait_file2(chan, vms, "vm-unknown-caller");
+ return res;
}
- return res;
-}
-static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
-{
- int res = 0;
- int durationm;
- int durations;
- /* Verify that we have a duration for the message */
- if (duration == NULL)
- return res;
+ static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
+ {
+ int res = 0;
+ int durationm;
+ int durations;
+ /* Verify that we have a duration for the message */
+ if (duration == NULL)
+ return res;
- /* Convert from seconds to minutes */
- durations = atoi(duration);
- durationm = durations / 60;
+ /* Convert from seconds to minutes */
+ durations = atoi(duration);
+ durationm = durations / 60;
- ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
+ ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
- if ((!res) && (durationm >= minduration)) {
- res = wait_file2(chan, vms, "vm-duration");
+ if ((!res) && (durationm >= minduration)) {
+ res = wait_file2(chan, vms, "vm-duration");
- /* POLISH syntax */
- if (!strcasecmp(chan->language, "pl")) {
- div_t num = div(durationm, 10);
+ /* POLISH syntax */
+ if (!strcasecmp(chan->language, "pl")) {
+ div_t num = div(durationm, 10);
- if (durationm == 1) {
- res = ast_play_and_wait(chan, "digits/1z");
- res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
- } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
- if (num.rem == 2) {
- if (!num.quot) {
- res = ast_play_and_wait(chan, "digits/2-ie");
+ if (durationm == 1) {
+ res = ast_play_and_wait(chan, "digits/1z");
+ res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
+ } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
+ if (num.rem == 2) {
+ if (!num.quot) {
+ res = ast_play_and_wait(chan, "digits/2-ie");
+ } else {
+ res = say_and_wait(chan, durationm - 2 , chan->language);
+ res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
+ }
} else {
- res = say_and_wait(chan, durationm - 2 , chan->language);
- res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
+ res = say_and_wait(chan, durationm, chan->language);
}
+ res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
} else {
res = say_and_wait(chan, durationm, chan->language);
+ res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
}
- res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
+ /* DEFAULT syntax */
} else {
- res = say_and_wait(chan, durationm, chan->language);
- res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
+ res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
+ res = wait_file2(chan, vms, "vm-minutes");
}
- /* DEFAULT syntax */
- } else {
- res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
- res = wait_file2(chan, vms, "vm-minutes");
- }
- }
- return res;
-}
-
-#ifdef IMAP_STORAGE
-static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
-{
- BODY *body;
- char *header_content;
- char cid[256], cidN[256];
- char context[256];
- char origtime[32];
- char duration[16];
- char category[32];
- char todir[PATH_MAX];
- int res = 0;
- char *attachedfilefmt;
- char *temp;
- char buf[1024];
-
- vms->starting = 0;
- ast_debug(3, "Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", vms->curmsg, vms->msgArray[vms->curmsg]);
-
- if (!vms->msgArray[vms->curmsg]) {
- ast_log(LOG_WARNING, "Trying to access unknown message\n");
- return -1;
- }
-
- /* This will only work for new messages... */
- header_content = mail_fetchheader (vms->mailstream, vms->msgArray[vms->curmsg]);
- /* empty string means no valid header */
- if (ast_strlen_zero(header_content)) {
- ast_log(LOG_ERROR, "Could not fetch header for message number %ld\n", vms->msgArray[vms->curmsg]);
- return -1;
- }
- snprintf(todir, sizeof(todir), "%s%s/%s/tmp", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
- make_gsm_file(vms->fn, sizeof(vms->fn), vms->imapuser, todir, vms->curmsg);
-
- mail_fetchstructure (vms->mailstream, vms->msgArray[vms->curmsg], &body);
-
- /* We have the body, now we extract the file name of the first attachment. */
- if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
- attachedfilefmt = ast_strdupa(body->nested.part->next->body.parameter->value);
- } else {
- ast_log(LOG_ERROR, "There is no file attached to this IMAP message.\n");
- return -1;
- }
-
-
- /* Find the format of the attached file */
-
- strsep(&attachedfilefmt, ".");
- if (!attachedfilefmt) {
- ast_log(LOG_ERROR, "File format could not be obtained from IMAP message attachment\n");
- return -1;
- }
- save_body(body, vms, "2", attachedfilefmt);
-
- adsi_message(chan, vms);
- if (!vms->curmsg)
- res = wait_file2(chan, vms, "vm-first"); /* "First" */
- else if (vms->curmsg == vms->lastmsg)
- res = wait_file2(chan, vms, "vm-last"); /* "last" */
-
- if (!res) {
- res = wait_file2(chan, vms, "vm-message"); /* "message" */
- if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
- if (!res)
- res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
}
+ return res;
}
- /* Get info from headers!! */
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Name:", buf, sizeof(buf))))
- ast_copy_string(cidN, temp, sizeof(cidN));
- else
- cidN[0] = '\0';
-
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:", buf, sizeof(buf))))
- snprintf(cid, sizeof(cid), "\"%s\" <%s>", cidN, temp);
- else
- cid[0] = '\0';
-
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Context:", buf, sizeof(buf))))
- ast_copy_string(context, temp, sizeof(context));
- else
- context[0] = '\0';
-
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:", buf, sizeof(buf))))
- ast_copy_string(origtime, temp, sizeof(origtime));
- else
- origtime[0] = '\0';
-
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:", buf, sizeof(buf))))
- ast_copy_string(duration, temp, sizeof(duration));
- else
- duration[0] = '\0';
-
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Category:", buf, sizeof(buf))))
- ast_copy_string(category, temp, sizeof(category));
- else
- category[0] = '\0';
-
- if (res == '1')
- res = 0;
-
- if ((!res) && !ast_strlen_zero(category)) {
- res = play_message_category(chan, category);
- }
-
- if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)) && origtime[0] != '\0')
- res = play_message_datetime(chan, vmu, origtime, "IMAP_STORAGE");
- if ((!res) && (ast_test_flag(vmu, VM_SAYCID)) && cid[0] != '\0' && context[0] != '\0')
- res = play_message_callerid(chan, vms, cid, context, 0);
-
- if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)) && duration[0] != '\0')
- res = play_message_duration(chan, vms, duration, vmu->saydurationm);
-
- res = 0;
+ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
+ {
+ int res = 0;
+ char filename[256], *cid;
+ const char *origtime, *context, *category, *duration;
+ struct ast_config *msg_cfg;
+ struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
- if (!res) {
- vms->heard[vms->curmsg] = 1;
- res = wait_file(chan, vms, vms->fn);
- }
- DISPOSE(vms->curdir, vms->curmsg);
- DELETE(0, 0, vms->fn);
- return res;
-}
-#else
-static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
-{
- int res = 0;
- char filename[256], *cid;
- const char *origtime, *context, *category, *duration;
- struct ast_config *msg_cfg;
- struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
-
- vms->starting = 0;
- make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
- adsi_message(chan, vms);
- if (!vms->curmsg)
- res = wait_file2(chan, vms, "vm-first"); /* "First" */
- else if (vms->curmsg == vms->lastmsg)
- res = wait_file2(chan, vms, "vm-last"); /* "last" */
- if (!res) {
- /* POLISH syntax */
- if (!strcasecmp(chan->language, "pl")) {
- if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
- int ten, one;
- char nextmsg[256];
- ten = (vms->curmsg + 1) / 10;
- one = (vms->curmsg + 1) % 10;
-
- if (vms->curmsg < 20) {
- snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
- res = wait_file2(chan, vms, nextmsg);
- } else {
- snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
- res = wait_file2(chan, vms, nextmsg);
- if (one > 0) {
- if (!res) {
- snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
- res = wait_file2(chan, vms, nextmsg);
+ vms->starting = 0;
+ make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
+ adsi_message(chan, vms);
+ if (!vms->curmsg)
+ res = wait_file2(chan, vms, "vm-first"); /* "First" */
+ else if (vms->curmsg == vms->lastmsg)
+ res = wait_file2(chan, vms, "vm-last"); /* "last" */
+ if (!res) {
+ /* POLISH syntax */
+ if (!strcasecmp(chan->language, "pl")) {
+ if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
+ int ten, one;
+ char nextmsg[256];
+ ten = (vms->curmsg + 1) / 10;
+ one = (vms->curmsg + 1) % 10;
+
+ if (vms->curmsg < 20) {
+ snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
+ res = wait_file2(chan, vms, nextmsg);
+ } else {
+ snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
+ res = wait_file2(chan, vms, nextmsg);
+ if (one > 0) {
+ if (!res) {
+ snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
+ res = wait_file2(chan, vms, nextmsg);
+ }
}
}
}
- }
- if (!res)
- res = wait_file2(chan, vms, "vm-message");
- } else {
- if (!strcasecmp(chan->language, "se")) /* SWEDISH syntax */
- res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */
- else /* DEFAULT syntax */
- res = wait_file2(chan, vms, "vm-message");
- if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
if (!res)
- res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
+ res = wait_file2(chan, vms, "vm-message");
+ } else {
+ if (!strcasecmp(chan->language, "se")) /* SWEDISH syntax */
+ res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */
+ else /* DEFAULT syntax */ {
+ res = wait_file2(chan, vms, "vm-message");
+ }
+ if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
+ if (!res) {
+ res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
+ }
+ }
}
}
- }
-
- /* Retrieve info from VM attribute file */
- make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
- snprintf(filename, sizeof(filename), "%s.txt", vms->fn2);
- RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
- msg_cfg = ast_config_load(filename, config_flags);
- if (!msg_cfg) {
- ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
- return 0;
- }
-
- if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
- ast_log(LOG_WARNING, "No origtime?!\n");
- DISPOSE(vms->curdir, vms->curmsg);
- ast_config_destroy(msg_cfg);
- return 0;
- }
-
- cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
- duration = ast_variable_retrieve(msg_cfg, "message", "duration");
- category = ast_variable_retrieve(msg_cfg, "message", "category");
-
- context = ast_variable_retrieve(msg_cfg, "message", "context");
- if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
- context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
- if (!res)
- res = play_message_category(chan, category);
- if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
- res = play_message_datetime(chan, vmu, origtime, filename);
- if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
- res = play_message_callerid(chan, vms, cid, context, 0);
- if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
- res = play_message_duration(chan, vms, duration, vmu->saydurationm);
- /* Allow pressing '1' to skip envelope / callerid */
- if (res == '1')
- res = 0;
- ast_config_destroy(msg_cfg);
- if (!res) {
- make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
- vms->heard[vms->curmsg] = 1;
- if ((res = wait_file(chan, vms, vms->fn)) < 0) {
- ast_log(LOG_WARNING, "Playback of message %s failed\n", vms->fn);
- res = 0;
+ /* Retrieve info from VM attribute file */
+ make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
+ snprintf(filename, sizeof(filename), "%s.txt", vms->fn2);
+ RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
+ msg_cfg = ast_config_load(filename, config_flags);
+ if (!msg_cfg) {
+ ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
+ return 0;
}
- }
- DISPOSE(vms->curdir, vms->curmsg);
- return res;
-}
-#endif
-#ifdef IMAP_STORAGE
-static void imap_mailbox_name(char *spec, size_t len, struct vm_state *vms, int box, int use_folder)
-{
- char tmp[256], *t = tmp;
- size_t left = sizeof(tmp);
-
- if (box == OLD_FOLDER) {
- ast_copy_string(vms->curbox, mbox(NEW_FOLDER), sizeof(vms->curbox));
- } else {
- ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
- }
-
- if (box == NEW_FOLDER) {
- ast_copy_string(vms->vmbox, "vm-INBOX", sizeof(vms->vmbox));
- } else {
- snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", mbox(box));
- }
-
- /* Build up server information */
- ast_build_string(&t, &left, "{%s:%s/imap", imapserver, imapport);
-
- /* Add authentication user if present */
- if (!ast_strlen_zero(authuser))
- ast_build_string(&t, &left, "/authuser=%s", authuser);
-
- /* Add flags if present */
- if (!ast_strlen_zero(imapflags))
- ast_build_string(&t, &left, "/%s", imapflags);
-
- /* End with username */
- ast_build_string(&t, &left, "/user=%s}", vms->imapuser);
-
- if (box == NEW_FOLDER || box == OLD_FOLDER)
- snprintf(spec, len, "%s%s", tmp, use_folder? imapfolder: "INBOX");
- else if (box == GREETINGS_FOLDER)
- snprintf(spec, len, "%s%s", tmp, greetingfolder);
- else /* Other folders such as Friends, Family, etc... */
- if (!ast_strlen_zero(imapparentfolder)) {
- /* imapparentfolder would typically be set to INBOX */
- snprintf(spec, len, "%s%s%c%s", tmp, imapparentfolder, delimiter, mbox(box));
- } else {
- snprintf(spec, len, "%s%s", tmp, mbox(box));
+ if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
+ ast_log(LOG_WARNING, "No origtime?!\n");
+ DISPOSE(vms->curdir, vms->curmsg);
+ ast_config_destroy(msg_cfg);
+ return 0;
}
-}
-static int init_mailstream(struct vm_state *vms, int box)
-{
- MAILSTREAM *stream = NIL;
- long debug;
- char tmp[256];
-
- if (!vms) {
- ast_log(LOG_ERROR, "vm_state is NULL!\n");
- return -1;
- }
- ast_debug(3, "vm_state user is:%s\n", vms->imapuser);
- if (vms->mailstream == NIL || !vms->mailstream) {
- ast_debug(1, "mailstream not set.\n");
- } else {
- stream = vms->mailstream;
- }
- /* debug = T; user wants protocol telemetry? */
- debug = NIL; /* NO protocol telemetry? */
+ cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
+ duration = ast_variable_retrieve(msg_cfg, "message", "duration");
+ category = ast_variable_retrieve(msg_cfg, "message", "category");
- if (delimiter == '\0') { /* did not probe the server yet */
- char *cp;
-#ifdef USE_SYSTEM_IMAP
-#include <imap/linkage.c>
-#elif defined(USE_SYSTEM_CCLIENT)
-#include <c-client/linkage.c>
-#else
-#include "linkage.c"
-#endif
- /* Connect to mailbox to get mailstream so we can get delimiter */
- imap_mailbox_name(tmp, sizeof(tmp), vms, 0, 1);
- ast_mutex_lock(&vms->lock);
- stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
- ast_mutex_unlock(&vms->lock);
- if (stream == NIL) {
- ast_log(LOG_ERROR, "Can't connect to imap server %s\n", tmp);
- return -1;
- }
- get_mailbox_delimiter(stream);
- /* update delimiter in imapfolder */
- for (cp = imapfolder; *cp; cp++) {
- if (*cp == '/')
- *cp = delimiter;
+ context = ast_variable_retrieve(msg_cfg, "message", "context");
+ if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
+ context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
+ if (!res) {
+ res = play_message_category(chan, category);
}
- }
- /* Now connect to the target folder */
- imap_mailbox_name(tmp, sizeof(tmp), vms, box, 1);
- ast_debug(3, "Before mail_open, server: %s, box:%d\n", tmp, box);
- ast_mutex_lock(&vms->lock);
- vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
- ast_mutex_unlock(&vms->lock);
- if (vms->mailstream == NIL) {
- return -1;
- } else {
- return 0;
- }
-}
-
-static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
-{
- SEARCHPGM *pgm;
- SEARCHHEADER *hdr;
- int ret;
-
- ast_copy_string(vms->imapuser, vmu->imapuser, sizeof(vms->imapuser));
- ast_debug(3, "Before init_mailstream, user is %s\n", vmu->imapuser);
-
- if ((ret = init_mailstream(vms, box)) || !vms->mailstream) {
- ast_log(LOG_ERROR, "Could not initialize mailstream\n");
- return -1;
- }
-
- /* Check Quota */
- if (box == 0) {
- ast_debug(3, "Mailbox name set to: %s, about to check quotas\n", mbox(box));
- check_quota(vms, (char *)mbox(box));
- }
-
- pgm = mail_newsearchpgm();
-
- /* Check IMAP folder for Asterisk messages only... */
- hdr = mail_newsearchheader("X-Asterisk-VM-Extension", vmu->mailbox);
- pgm->header = hdr;
- pgm->deleted = 0;
- pgm->undeleted = 1;
+ if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
+ res = play_message_datetime(chan, vmu, origtime, filename);
+ if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
+ res = play_message_callerid(chan, vms, cid, context, 0);
+ if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
+ res = play_message_duration(chan, vms, duration, vmu->saydurationm);
+ /* Allow pressing '1' to skip envelope / callerid */
+ if (res == '1')
+ res = 0;
+ ast_config_destroy(msg_cfg);
- /* if box = NEW_FOLDER, check for new, if box = OLD_FOLDER, check for read */
- if (box == NEW_FOLDER) {
- pgm->unseen = 1;
- pgm->seen = 0;
- } else if (box == OLD_FOLDER) {
- pgm->seen = 1;
- pgm->unseen = 0;
+ if (!res) {
+ make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
+ vms->heard[vms->curmsg] = 1;
+ if ((res = wait_file(chan, vms, vms->fn)) < 0) {
+ ast_log(LOG_WARNING, "Playback of message %s failed\n", vms->fn);
+ res = 0;
+ }
+ }
+ DISPOSE(vms->curdir, vms->curmsg);
+ return res;
}
- ast_debug(3, "Before mail_search_full, user is %s\n", vmu->imapuser);
-
- vms->vmArrayIndex = 0;
- mail_search_full (vms->mailstream, NULL, pgm, NIL);
- vms->lastmsg = vms->vmArrayIndex - 1;
- mail_free_searchpgm(&pgm);
-
- return 0;
-}
-
+#ifdef IMAP_STORAGE
static int imap_remove_file(char *dir, int msgnum)
{
char fn[PATH_MAX];
char full_fn[PATH_MAX];
- char msgnums[80];
if (msgnum > -1) {
- snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
make_file(fn, sizeof(fn), dir, msgnum);
} else
ast_copy_string(fn, dir, sizeof(fn));
if ((msgnum < 0 && imapgreetings) || msgnum > -1) {
- ast_filedelete(fn, NULL);
+ ast_filedelete(fn, NULL);
snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
unlink(full_fn);
}
return 0;
}
-static int imap_retrieve_file (char *dir, int msgnum, const char *mailbox, char *context)
-{
- struct ast_vm_user *vmu;
- struct vm_state *vms_p;
- char *file, *filename;
- char *attachment;
- int ret = 0, i;
- BODY *body;
-
- /* This function is only used for retrieval of IMAP greetings
- * regular messages are not retrieved this way, nor are greetings
- * if they are stored locally*/
- if (msgnum > -1 || !imapgreetings) {
- return 0;
- } else {
- file = strrchr(ast_strdupa(dir), '/');
- if (file)
- *file++ = '\0';
- else {
- ast_debug(1, "Failed to procure file name from directory passed.\n");
- return -1;
- }
- }
- /* We have to get the user before we can open the stream! */
- /* ast_log(LOG_DEBUG, "Before find_user, context is %s and mailbox is %s\n", context, mailbox); */
- vmu = find_user(NULL, context, mailbox);
- if (!vmu) {
- ast_log(LOG_ERROR, "Couldn't find mailbox %s in context %s\n", mailbox, context);
- return -1;
- } else {
- /* No IMAP account available */
- if (vmu->imapuser[0] == '\0') {
- ast_log(LOG_WARNING, "IMAP user not set for mailbox %s\n", vmu->mailbox);
- free_user(vmu);
- return -1;
- }
- }
-
- /* check if someone is accessing this box right now... */
- vms_p = get_vm_state_by_mailbox(mailbox, 0);
- if (!vms_p) {
- ast_log(LOG_ERROR, "Voicemail state not found!\n");
- return -1;
- }
-
- ret = init_mailstream(vms_p, GREETINGS_FOLDER);
- if (!vms_p->mailstream) {
- ast_log(LOG_ERROR, "IMAP mailstream is NULL\n");
- free_user(vmu);
- return -1;
- }
-
- for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
- mail_fetchstructure(vms_p->mailstream, i + 1, &body);
- /* We have the body, now we extract the file name of the first attachment. */
- if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
- attachment = ast_strdupa(body->nested.part->next->body.parameter->value);
- } else {
- ast_log(LOG_ERROR, "There is no file attached to this IMAP message.\n");
- return -1;
- }
- filename = strsep(&attachment, ".");
- if (!strcmp(filename, file)) {
- ast_copy_string(vms_p->fn, dir, sizeof(vms_p->fn));
- vms_p->msgArray[vms_p->curmsg] = i + 1;
- save_body(body, vms_p, "2", attachment);
- free_user(vmu);
- return 0;
- }
- }
-
- free_user(vmu);
- return -1;
-}
-
static int imap_delete_old_greeting (char *dir, struct vm_state *vms)
{
char *file, *filename;
@@ -5346,6 +5848,7 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms)
}
#else
+#ifndef IMAP_STORAGE
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
{
int res = 0;
@@ -5394,6 +5897,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
return 0;
}
#endif
+#endif
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
{
@@ -5446,7 +5950,7 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
if (EXISTS(vms->curdir, x, vms->fn, NULL))
- DELETE(vms->curdir, x, vms->fn);
+ DELETE(vms->curdir, x, vms->fn, vmu);
}
}
@@ -5455,7 +5959,7 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
for (x = vms->curmsg + 1; x <= nummsg; x++) {
make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
if (EXISTS(vms->curdir, x, vms->fn, NULL))
- DELETE(vms->curdir, x, vms->fn);
+ DELETE(vms->curdir, x, vms->fn, vmu);
}
ast_unlock_path(vms->curdir);
#else
@@ -5463,7 +5967,7 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
for (x = 0; x < vmu->maxmsg; x++) {
if (vms->deleted[x]) {
ast_debug(3, "IMAP delete of %d\n", x);
- IMAP_DELETE(vms->curdir, x, vms->fn, vms);
+ DELETE(vms->curdir, x, vms->fn, vmu);
}
}
}
@@ -6572,11 +7076,7 @@ static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct
if (ast_test_flag(vmu, VM_FORCENAME)) {
snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
if (ast_fileexists(prefile, NULL, NULL) < 1) {
-#ifndef IMAP_STORAGE
- cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
-#else
cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
-#endif
if (cmd < 0 || cmd == 't' || cmd == '#')
return cmd;
}
@@ -6586,22 +7086,14 @@ static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct
if (ast_test_flag(vmu, VM_FORCEGREET)) {
snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
if (ast_fileexists(prefile, NULL, NULL) < 1) {
-#ifndef IMAP_STORAGE
- cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
-#else
cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
-#endif
if (cmd < 0 || cmd == 't' || cmd == '#')
return cmd;
}
snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
if (ast_fileexists(prefile, NULL, NULL) < 1) {
-#ifndef IMAP_STORAGE
- cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
-#else
cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
-#endif
if (cmd < 0 || cmd == 't' || cmd == '#')
return cmd;
}
@@ -6635,27 +7127,15 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct
switch (cmd) {
case '1':
snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
-#ifndef IMAP_STORAGE
- cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
-#else
cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
-#endif
break;
case '2':
snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
-#ifndef IMAP_STORAGE
- cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
-#else
cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
-#endif
break;
case '3':
snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
-#ifndef IMAP_STORAGE
- cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
-#else
cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
-#endif
break;
case '4':
cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
@@ -6753,23 +7233,15 @@ static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, st
retries = 0;
RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
if (ast_fileexists(prefile, NULL, NULL) <= 0) {
-#ifndef IMAP_STORAGE
- play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
-#else
play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
-#endif
cmd = 't';
} else {
switch (cmd) {
case '1':
-#ifndef IMAP_STORAGE
- cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
-#else
cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
-#endif
break;
case '2':
- DELETE(prefile, -1, prefile);
+ DELETE(prefile, -1, prefile, vmu);
ast_play_and_wait(chan, "vm-tempremoved");
cmd = 't';
break;
@@ -7186,7 +7658,6 @@ static int vm_execmain(struct ast_channel *chan, void *data)
/* Set language from config to override channel language */
if (!ast_strlen_zero(vmu->language))
ast_string_field_set(chan, language, vmu->language);
- create_dirpath(vms.curdir, sizeof(vms.curdir), vmu->context, vms.username, "");
/* Retrieve old and new message counts */
ast_debug(1, "Before open_mailbox\n");
res = open_mailbox(&vms, vmu, OLD_FOLDER);
@@ -7478,12 +7949,10 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (cmd == ERROR_LOCK_PATH) {
res = cmd;
goto out;
-#ifdef IMAP_STORAGE
- } else if (cmd == 10) {
- goto out;
-#endif
+#ifndef IMAP_STORAGE
} else if (!cmd) {
vms.deleted[vms.curmsg] = 1;
+#endif
} else {
vms.deleted[vms.curmsg] = 0;
vms.heard[vms.curmsg] = 0;
@@ -7495,7 +7964,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(box));
if (!cmd) {
cmd = ast_play_and_wait(chan, "vm-message");
- if (!cmd)
+ if (!cmd)
cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
if (!cmd)
cmd = ast_play_and_wait(chan, "vm-savedto");
@@ -9059,62 +9528,16 @@ static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num,
static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
{
int res = 0;
-#ifdef IMAP_STORAGE
- char origtimeS[256], cidN[256], cid[256], contextS[256];
- char *header_content, *temp;
- char buf[1024];
-#else
- char *cid;
- struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
-#endif
char filename[PATH_MAX];
struct ast_config *msg_cfg = NULL;
const char *origtime, *context;
char *name, *num;
int retries = 0;
+ char *cid;
+ struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
vms->starting = 0;
-#ifdef IMAP_STORAGE
- /* START HERE */
-
- /* get the message info!! */
- ast_debug(3, "Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", vms->curmsg, vms->msgArray[vms->curmsg]);
-
- if (!vms->msgArray[vms->curmsg]) {
- ast_log(LOG_WARNING, "Trying to access unknown message\n");
- return -1;
- }
-
- /* This will only work for new messages... */
- if (!(header_content = mail_fetchheader(vms->mailstream, vms->msgArray[vms->curmsg])) || ast_strlen_zero(header_content)) {
- ast_log(LOG_ERROR, "Could not fetch header for message number %ld\n", vms->msgArray[vms->curmsg]);
- return -1;
- }
-
- /* Get info from headers!! */
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Name:", buf, sizeof(buf))))
- ast_copy_string(cidN, temp, sizeof(cidN));
- else
- cidN[0] = '\0';
-
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:", buf, sizeof(buf))))
- snprintf(cid, sizeof(cid), "\"%s\" <%s>", cidN, temp);
- else if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Context:", buf, sizeof(buf))))
- ast_copy_string(contextS, temp, sizeof(contextS));
- else
- contextS[0] = '\0';
-
- context = &contextS[0];
- if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:", buf, sizeof(buf))))
- ast_copy_string(origtimeS, temp, sizeof(origtimeS));
- else
- origtimeS[0] = '\0';
-
- origtime = &origtimeS[0];
-
- ast_copy_string(filename, "IMAP_STORAGE", sizeof(filename));
-#else
make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
/* Retrieve info from VM attribute file */
@@ -9139,7 +9562,6 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
context = ast_variable_retrieve(msg_cfg, "message", "context");
if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
-#endif
switch (option) {
case 3:
if (!res)
@@ -9442,7 +9864,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
cmd = '0';
} else {
ast_play_and_wait(chan, "vm-deleted");
- DELETE(recordfile, -1, recordfile);
+ DELETE(recordfile, -1, recordfile, vmu);
cmd = '0';
}
}
@@ -9487,541 +9909,6 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
return cmd;
}
-#ifdef IMAP_STORAGE
-
-static void write_file(char *filename, char *buffer, unsigned long len)
-{
- FILE *output;
-
- output = fopen (filename, "w");
- fwrite (buffer, len, 1, output);
- fclose (output);
-}
-
-static void update_messages_by_imapuser(const char *user, unsigned long number)
-{
- struct vmstate *vlist = NULL;
-
- AST_LIST_LOCK(&vmstates);
- AST_LIST_TRAVERSE(&vmstates, vlist, list) {
- if (!vlist->vms) {
- ast_debug(3, "error: vms is NULL for %s\n", user);
- continue;
- }
- if (!vlist->vms->imapuser) {
- ast_debug(3, "error: imapuser is NULL for %s\n", user);
- continue;
- }
- ast_debug(3, "saving mailbox message number %lu as message %d. Interactive set to %d\n", number, vlist->vms->vmArrayIndex, vlist->vms->interactive);
- vlist->vms->msgArray[vlist->vms->vmArrayIndex++] = number;
- }
- AST_LIST_UNLOCK(&vmstates);
-}
-
-void mm_searched(MAILSTREAM *stream, unsigned long number)
-{
- char *mailbox = stream->mailbox, buf[1024] = "", *user;
-
- if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))))
- return;
-
- update_messages_by_imapuser(user, number);
-}
-
-static struct ast_vm_user *find_user_realtime_imapuser(const char *imapuser)
-{
- struct ast_variable *var;
- struct ast_vm_user *vmu;
-
- vmu = ast_calloc(1, sizeof *vmu);
- if (!vmu)
- return NULL;
- ast_set_flag(vmu, VM_ALLOCED);
- populate_defaults(vmu);
-
- var = ast_load_realtime("voicemail", "imapuser", imapuser, NULL);
- if (var) {
- apply_options_full(vmu, var);
- ast_variables_destroy(var);
- return vmu;
- } else {
- ast_free(vmu);
- return NULL;
- }
-}
-
-/* Interfaces to C-client */
-
-void mm_exists(MAILSTREAM * stream, unsigned long number)
-{
- /* mail_ping will callback here if new mail! */
- ast_debug(4, "Entering EXISTS callback for message %ld\n", number);
- if (number == 0) return;
- set_update(stream);
-}
-
-
-void mm_expunged(MAILSTREAM * stream, unsigned long number)
-{
- /* mail_ping will callback here if expunged mail! */
- ast_debug(4, "Entering EXPUNGE callback for message %ld\n", number);
- if (number == 0) return;
- set_update(stream);
-}
-
-
-void mm_flags(MAILSTREAM * stream, unsigned long number)
-{
- /* mail_ping will callback here if read mail! */
- ast_debug(4, "Entering FLAGS callback for message %ld\n", number);
- if (number == 0) return;
- set_update(stream);
-}
-
-
-void mm_notify(MAILSTREAM * stream, char *string, long errflg)
-{
- ast_debug(5, "Entering NOTIFY callback, errflag is %ld, string is %s\n", errflg, string);
- mm_log (string, errflg);
-}
-
-
-void mm_list(MAILSTREAM * stream, int delim, char *mailbox, long attributes)
-{
- if (delimiter == '\0') {
- delimiter = delim;
- }
-
- ast_debug(5, "Delimiter set to %c and mailbox %s\n", delim, mailbox);
- if (attributes & LATT_NOINFERIORS)
- ast_debug(5, "no inferiors\n");
- if (attributes & LATT_NOSELECT)
- ast_debug(5, "no select\n");
- if (attributes & LATT_MARKED)
- ast_debug(5, "marked\n");
- if (attributes & LATT_UNMARKED)
- ast_debug(5, "unmarked\n");
-}
-
-
-void mm_lsub(MAILSTREAM * stream, int delimiter, char *mailbox, long attributes)
-{
- ast_debug(5, "Delimiter set to %c and mailbox %s\n", delimiter, mailbox);
- if (attributes & LATT_NOINFERIORS)
- ast_debug(5, "no inferiors\n");
- if (attributes & LATT_NOSELECT)
- ast_debug(5, "no select\n");
- if (attributes & LATT_MARKED)
- ast_debug(5, "marked\n");
- if (attributes & LATT_UNMARKED)
- ast_debug(5, "unmarked\n");
-}
-
-
-void mm_status(MAILSTREAM * stream, char *mailbox, MAILSTATUS * status)
-{
- ast_log(LOG_NOTICE, " Mailbox %s", mailbox);
- if (status->flags & SA_MESSAGES)
- ast_log(LOG_NOTICE, ", %lu messages", status->messages);
- if (status->flags & SA_RECENT)
- ast_log(LOG_NOTICE, ", %lu recent", status->recent);
- if (status->flags & SA_UNSEEN)
- ast_log(LOG_NOTICE, ", %lu unseen", status->unseen);
- if (status->flags & SA_UIDVALIDITY)
- ast_log(LOG_NOTICE, ", %lu UID validity", status->uidvalidity);
- if (status->flags & SA_UIDNEXT)
- ast_log(LOG_NOTICE, ", %lu next UID", status->uidnext);
- ast_log(LOG_NOTICE, "\n");
-}
-
-
-void mm_log(char *string, long errflg)
-{
- switch ((short) errflg) {
- case NIL:
- ast_debug(1, "IMAP Info: %s\n", string);
- break;
- case PARSE:
- case WARN:
- ast_log(LOG_WARNING, "IMAP Warning: %s\n", string);
- break;
- case ERROR:
- ast_log(LOG_ERROR, "IMAP Error: %s\n", string);
- break;
- }
-}
-
-
-void mm_dlog(char *string)
-{
- ast_log(LOG_NOTICE, "%s\n", string);
-}
-
-
-void mm_login(NETMBX * mb, char *user, char *pwd, long trial)
-{
- struct ast_vm_user *vmu;
-
- ast_debug(4, "Entering callback mm_login\n");
-
- ast_copy_string(user, mb->user, MAILTMPLEN);
-
- /* We should only do this when necessary */
- if (!ast_strlen_zero(authpassword)) {
- ast_copy_string(pwd, authpassword, MAILTMPLEN);
- } else {
- AST_LIST_TRAVERSE(&users, vmu, list) {
- if (!strcasecmp(mb->user, vmu->imapuser)) {
- ast_copy_string(pwd, vmu->imappassword, MAILTMPLEN);
- break;
- }
- }
- if (!vmu) {
- if ((vmu = find_user_realtime_imapuser(mb->user))) {
- ast_copy_string(pwd, vmu->imappassword, MAILTMPLEN);
- free_user(vmu);
- }
- }
- }
-}
-
-
-void mm_critical(MAILSTREAM * stream)
-{
-}
-
-
-void mm_nocritical(MAILSTREAM * stream)
-{
-}
-
-
-long mm_diskerror(MAILSTREAM * stream, long errcode, long serious)
-{
- kill (getpid (), SIGSTOP);
- return NIL;
-}
-
-
-void mm_fatal(char *string)
-{
- ast_log(LOG_ERROR, "IMAP access FATAL error: %s\n", string);
-}
-
-/* C-client callback to handle quota */
-static void mm_parsequota(MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pquota)
-{
- struct vm_state *vms;
- char *mailbox = stream->mailbox, *user;
- char buf[1024] = "";
- unsigned long usage = 0, limit = 0;
-
- while (pquota) {
- usage = pquota->usage;
- limit = pquota->limit;
- pquota = pquota->next;
- }
-
- if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))) || !(vms = get_vm_state_by_imapuser(user, 2))) {
- ast_log(LOG_ERROR, "No state found.\n");
- return;
- }
-
- ast_debug(3, "User %s usage is %lu, limit is %lu\n", user, usage, limit);
-
- vms->quota_usage = usage;
- vms->quota_limit = limit;
-}
-
-static char *get_header_by_tag(char *header, char *tag, char *buf, size_t len)
-{
- char *start, *eol_pnt;
- int taglen;
-
- if (ast_strlen_zero(header) || ast_strlen_zero(tag))
- return NULL;
-
- taglen = strlen(tag) + 1;
- if (taglen < 1)
- return NULL;
-
- if (!(start = strstr(header, tag)))
- return NULL;
-
- /* Since we can be called multiple times we should clear our buffer */
- memset(buf, 0, len);
-
- ast_copy_string(buf, start+taglen, len);
- if ((eol_pnt = strchr(buf, '\r')) || (eol_pnt = strchr(buf, '\n')))
- *eol_pnt = '\0';
- return buf;
-}
-
-static char *get_user_by_mailbox(char *mailbox, char *buf, size_t len)
-{
- char *start, *quote, *eol_pnt;
-
- if (ast_strlen_zero(mailbox))
- return NULL;
-
- if (!(start = strstr(mailbox, "/user=")))
- return NULL;
-
- ast_copy_string(buf, start + 6, len);
-
- if (!(quote = strchr(buf, '\"'))) {
- if (!(eol_pnt = strchr(buf, '/')))
- eol_pnt = strchr(buf, '}');
- *eol_pnt = '\0';
- return buf;
- } else {
- eol_pnt = strchr(buf + 1, '\"');
- *eol_pnt = '\0';
- return buf + 1;
- }
-}
-
-static struct vm_state *create_vm_state_from_user(struct ast_vm_user *vmu, char *mailbox)
-{
- struct vm_state *vms_p;
-
- if (option_debug > 4)
- ast_log(LOG_DEBUG,"Adding new vmstate for %s\n",vmu->imapuser);
- if (!(vms_p = ast_calloc(1, sizeof(*vms_p))))
- return NULL;
- ast_copy_string(vms_p->imapuser,vmu->imapuser, sizeof(vms_p->imapuser));
- ast_copy_string(vms_p->username, mailbox, sizeof(vms_p->username)); /* save for access from interactive entry point */
- vms_p->mailstream = NIL; /* save for access from interactive entry point */
- if (option_debug > 4)
- ast_log(LOG_DEBUG,"Copied %s to %s\n",vmu->imapuser,vms_p->imapuser);
- vms_p->updated = 1;
- /* set mailbox to INBOX! */
- ast_copy_string(vms_p->curbox, mbox(0), sizeof(vms_p->curbox));
- init_vm_state(vms_p);
- vmstate_insert(vms_p);
- return vms_p;
-}
-
-static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive)
-{
- struct vmstate *vlist = NULL;
-
- AST_LIST_LOCK(&vmstates);
- AST_LIST_TRAVERSE(&vmstates, vlist, list) {
- if (!vlist->vms) {
- ast_debug(3, "error: vms is NULL for %s\n", user);
- continue;
- }
- if (!vlist->vms->imapuser) {
- ast_debug(3, "error: imapuser is NULL for %s\n", user);
- continue;
- }
-
- if (!strcmp(vlist->vms->imapuser, user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
- AST_LIST_UNLOCK(&vmstates);
- return vlist->vms;
- }
- }
- AST_LIST_UNLOCK(&vmstates);
-
- ast_debug(3, "%s not found in vmstates\n", user);
-
- return NULL;
-}
-
-static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, int interactive)
-{
-
- struct vmstate *vlist = NULL;
-
- AST_LIST_LOCK(&vmstates);
- AST_LIST_TRAVERSE(&vmstates, vlist, list) {
- if (!vlist->vms) {
- ast_debug(3, "error: vms is NULL for %s\n", mailbox);
- continue;
- }
- if (!vlist->vms->username) {
- ast_debug(3, "error: username is NULL for %s\n", mailbox);
- continue;
- }
-
- ast_debug(3, "comparing mailbox %s (i=%d) to vmstate mailbox %s (i=%d)\n", mailbox, interactive, vlist->vms->username, vlist->vms->interactive);
-
- if (!strcmp(vlist->vms->username, mailbox) && vlist->vms->interactive == interactive) {
- ast_debug(3, "Found it!\n");
- AST_LIST_UNLOCK(&vmstates);
- return vlist->vms;
- }
- }
- AST_LIST_UNLOCK(&vmstates);
-
- ast_debug(3, "%s not found in vmstates\n", mailbox);
-
- return NULL;
-}
-
-static void vmstate_insert(struct vm_state *vms)
-{
- struct vmstate *v;
- struct vm_state *altvms;
-
- /* If interactive, it probably already exists, and we should
- use the one we already have since it is more up to date.
- We can compare the username to find the duplicate */
- if (vms->interactive == 1) {
- altvms = get_vm_state_by_mailbox(vms->username, 0);
- if (altvms) {
- ast_debug(3, "Duplicate mailbox %s, copying message info...\n", vms->username);
- vms->newmessages = altvms->newmessages;
- vms->oldmessages = altvms->oldmessages;
- ast_debug(3, "check_msgArray before memcpy\n");
- check_msgArray(vms);
- /* memcpy(vms->msgArray, altvms->msgArray, sizeof(long) * 256); */
- copy_msgArray(vms, altvms);
- ast_debug(3, "check_msgArray after memcpy\n");
- check_msgArray(vms);
- vms->vmArrayIndex = altvms->vmArrayIndex;
- vms->lastmsg = altvms->lastmsg;
- vms->curmsg = altvms->curmsg;
- /* get a pointer to the persistent store */
- vms->persist_vms = altvms;
- /* Reuse the mailstream? */
- vms->mailstream = altvms->mailstream;
- /* vms->mailstream = NIL; */
- }
- }
-
- if (!(v = ast_calloc(1, sizeof(*v))))
- return;
-
- v->vms = vms;
-
- ast_debug(3, "Inserting vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->username);
-
- AST_LIST_LOCK(&vmstates);
- AST_LIST_INSERT_TAIL(&vmstates, v, list);
- AST_LIST_UNLOCK(&vmstates);
-}
-
-static void vmstate_delete(struct vm_state *vms)
-{
- struct vmstate *vc = NULL;
- struct vm_state *altvms = NULL;
-
- /* If interactive, we should copy pertinent info
- back to the persistent state (to make update immediate) */
- if (vms->interactive == 1 && (altvms = vms->persist_vms)) {
- ast_debug(3, "Duplicate mailbox %s, copying message info...\n", vms->username);
- altvms->newmessages = vms->newmessages;
- altvms->oldmessages = vms->oldmessages;
- altvms->updated = 1;
- }
-
- ast_debug(3, "Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->username);
-
- AST_LIST_LOCK(&vmstates);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&vmstates, vc, list) {
- if (vc->vms == vms) {
- AST_LIST_REMOVE_CURRENT(list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&vmstates);
-
- if (vc) {
- ast_mutex_destroy(&vc->vms->lock);
- ast_free(vc);
- }
- else
- ast_log(LOG_ERROR, "No vmstate found for user:%s, mailbox %s\n", vms->imapuser, vms->username);
-}
-
-static void set_update(MAILSTREAM * stream)
-{
- struct vm_state *vms;
- char *mailbox = stream->mailbox, *user;
- char buf[1024] = "";
-
- if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))) || !(vms = get_vm_state_by_imapuser(user, 0))) {
- if (user && option_debug > 2)
- ast_log(LOG_WARNING, "User %s mailbox not found for update.\n", user);
- return;
- }
-
- ast_debug(3, "User %s mailbox set for update.\n", user);
-
- vms->updated = 1; /* Set updated flag since mailbox changed */
-}
-
-static void init_vm_state(struct vm_state *vms)
-{
- int x;
- vms->vmArrayIndex = 0;
- for (x = 0; x < 256; x++) {
- vms->msgArray[x] = 0;
- }
- ast_mutex_init(&vms->lock);
-}
-
-static void check_msgArray(struct vm_state *vms)
-{
- int x;
- for (x = 0; x < 256; x++) {
- if (vms->msgArray[x] != 0) {
- ast_debug(1, "Item %d set to %ld\n", x, vms->msgArray[x]);
- }
- }
-}
-
-static void copy_msgArray(struct vm_state *dst, struct vm_state *src)
-{
- int x;
- for (x = 0; x < 256; x++) {
- dst->msgArray[x] = src->msgArray[x];
- }
-}
-
-static int save_body(BODY *body, struct vm_state *vms, char *section, char *format)
-{
- char *body_content;
- char *body_decoded;
- unsigned long len;
- unsigned long newlen;
- char filename[256];
-
- if (!body || body == NIL)
- return -1;
- body_content = mail_fetchbody(vms->mailstream, vms->msgArray[vms->curmsg], section, &len);
- if (body_content != NIL) {
- snprintf(filename, sizeof(filename), "%s.%s", vms->fn, format);
- /* ast_debug(1, body_content); */
- body_decoded = rfc822_base64((unsigned char *)body_content, len, &newlen);
- write_file(filename, (char *) body_decoded, newlen);
- }
- return 0;
-}
-
-/* get delimiter via mm_list callback */
-static void get_mailbox_delimiter(MAILSTREAM *stream) {
- char tmp[50];
- snprintf(tmp, sizeof(tmp), "{%s}", imapserver);
- mail_list(stream, tmp, "*");
-}
-
-/* Check Quota for user */
-static void check_quota(struct vm_state *vms, char *mailbox) {
- mail_parameters(NULL, SET_QUOTA, (void *) mm_parsequota);
- ast_debug(3, "Mailbox name set to: %s, about to check quotas\n", mailbox);
- if (vms && vms->mailstream != NULL) {
- imap_getquotaroot(vms->mailstream, mailbox);
- } else {
- ast_log(LOG_WARNING, "Mailstream not available for mailbox: %s\n", mailbox);
- }
-}
-
-#endif /* IMAP_STORAGE */
-
/* This is a workaround so that menuselect displays a proper description
* AST_MODULE_INFO(, , "Comedian Mail (Voicemail System)"
*/