[asterisk-commits] mmichelson: branch 1.6.0 r136719 - in /branches/1.6.0: ./ apps/app_voicemail.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Aug 7 18:26:25 CDT 2008
Author: mmichelson
Date: Thu Aug 7 18:26:24 2008
New Revision: 136719
URL: http://svn.digium.com/view/asterisk?view=rev&rev=136719
Log:
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
........
Modified:
branches/1.6.0/ (props changed)
branches/1.6.0/apps/app_voicemail.c
Propchange: branches/1.6.0/
------------------------------------------------------------------------------
automerge = *
Propchange: branches/1.6.0/
------------------------------------------------------------------------------
automerge-email = mmichelson at digium.com
Propchange: branches/1.6.0/
------------------------------------------------------------------------------
Binary property 'trunk-merged' - no diff available.
Modified: branches/1.6.0/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/branches/1.6.0/apps/app_voicemail.c?view=diff&rev=136719&r1=136718&r2=136719
==============================================================================
--- branches/1.6.0/apps/app_voicemail.c (original)
+++ branches/1.6.0/apps/app_voicemail.c Thu Aug 7 18:26:24 2008
@@ -140,19 +140,16 @@
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 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 @@
#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 @@
#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 @@
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)
-{
- 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);
- }
+/*!
+ * \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)
+{
return snprintf(dest, len, "%s/msg%04d", dir, num);
}
-static void vm_imap_delete(int msgnum, struct vm_state *vms)
-{
- 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;
- }
- 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);
+/* 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;
}
/*! \brief basically mkdir -p $dest/$context/$ext/$folder
@@ -1101,622 +1092,1907 @@
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 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",
+ "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;
+
+ /* 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;
+ }
+ }
+
+ /* 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)
+{
+ 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;
+
+ if (!(vmu = find_user(NULL, context, mailbox))) {
+ ast_log(LOG_WARNING, "Couldn't find user with mailbox %s@%s\n", mailbox, context);
+ return -1;
+ }
+
+ 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;
+ }
+
+ /* 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]");
+
+ 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 folder_int(const char *folder)
+{
+ /*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 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, "|");
+
+ 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;
+ }
+ }
+
+ /* 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;
+ }
+ if (fold == 1) { /* Old messages */
+ return vms_p->oldmessages;
+ }
+ }
+
+ /* 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;
+ }
+ 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;
+ }
+ 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;
+ }
+ }
+ }
+ 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;
+}
+
+/**
+* \brief Determines if the given folder has messages.
+* \param mailbox The @ delimited string for user at 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 vm_lock_path(const char *path)
-{
- switch (ast_lock_path(path)) {
- case AST_LOCK_TIMEOUT:
+
+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, ',')) {
+ 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;
- default:
+ }
+ 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 (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));
+ }
+ }
+}
+
+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;
+ }
+ 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? */
+
+ 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;
+ }
+ 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;
+ }
+ 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 {
+ 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)
+{
+ 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, 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 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);
[... 6958 lines stripped ...]
More information about the asterisk-commits
mailing list