[asterisk-commits] mmichelson: branch mmichelson/imap_consistency_trunk r134248 - /team/mmichels...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jul 29 13:43:33 CDT 2008


Author: mmichelson
Date: Tue Jul 29 13:43:32 2008
New Revision: 134248

URL: http://svn.digium.com/view/asterisk?view=rev&rev=134248
Log:
This is app_voicemail completely conflicted. I admit
that it's silly to commit a file full of conflicts, but
now I can just "svn revert" to get to the original 
conflicted file


Modified:
    team/mmichelson/imap_consistency_trunk/apps/app_voicemail.c

Modified: team/mmichelson/imap_consistency_trunk/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/mmichelson/imap_consistency_trunk/apps/app_voicemail.c?view=diff&rev=134248&r1=134247&r2=134248
==============================================================================
--- team/mmichelson/imap_consistency_trunk/apps/app_voicemail.c (original)
+++ team/mmichelson/imap_consistency_trunk/apps/app_voicemail.c Tue Jul 29 13:43:32 2008
@@ -140,19 +140,22 @@
 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);
+<<<<<<< .working
 static int save_body(BODY *body, struct vm_state *vms, char *section, char *format, char *altfile);
 static int make_gsm_file(char *dest, size_t len, char *imapuser, char *dir, int num, char *prefix);
+=======
+static int save_body(BODY *body, struct vm_state *vms, char *section, char *format);
+>>>>>>> .merge-right.r134223
 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);
@@ -447,31 +450,44 @@
 #ifdef ODBC_STORAGE
 static char odbc_database[80];
 static char odbc_table[80];
+<<<<<<< .working
 #define RETRIEVE(a,b,c,d) retrieve_file(a,b)
+=======
+#define RETRIEVE(a,b,c) retrieve_file(a,b)
+>>>>>>> .merge-right.r134223
 #define DISPOSE(a,b) remove_file(a,b)
 #define STORE(a,b,c,d,e,f,g,h,i,j,k) store_file(a,b,c,d)
 #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
+<<<<<<< .working
 #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,j,k) (imap_store_file(a,b,c,d,e,f,g,h,i,j,k))
+=======
+#define RETRIEVE(a,b,c) imap_retrieve_file(a,b,c)
+#define DISPOSE(a,b) 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))
+>>>>>>> .merge-right.r134223
 #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_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
+<<<<<<< .working
 #define RETRIEVE(a,b,c,d)
+=======
+#define RETRIEVE(a,b,c)
+>>>>>>> .merge-right.r134223
 #define DISPOSE(a,b)
 #define STORE(a,b,c,d,e,f,g,h,i,j,k)
 #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
 
@@ -1242,19 +1258,28 @@
 	return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
 }
 
+<<<<<<< .working
 #ifdef IMAP_STORAGE
 static int make_gsm_file(char *dest, size_t len, char *imapuser, char *dir, int num, char *prefix)
-{
+=======
+static int make_file(char *dest, const int len, const char *dir, const int num)
+>>>>>>> .merge-right.r134223
+{
+<<<<<<< .working
 	int res;
 	if ((res = ast_mkdir(dir, 01777))) {
 		ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dir, strerror(res));
 		return snprintf(dest, len, "%s/%s%04d", dir, prefix, num);
 	}
+=======
+>>>>>>> .merge-right.r134223
 	return snprintf(dest, len, "%s/%s%04d", dir, prefix, 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)
+{
+<<<<<<< .working
 	unsigned long messageNum = 0;
 	char arg[10];
 
@@ -1265,17 +1290,26 @@
 	if (messageNum == 0) {
 		ast_log(AST_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;
+		}
+>>>>>>> .merge-right.r134223
+	}
+<<<<<<< .working
 	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;
+>>>>>>> .merge-right.r134223
 }
 
 /*! \brief basically mkdir -p $dest/$context/$ext/$folder
@@ -1299,8 +1333,1167 @@
 	return 0;
 }
 
+<<<<<<< .working
 /*! \brief Lock file path
     only return failure if ast_lock_path returns 'timeout',
+=======
+static const char *mbox(int id)
+{
+	static const char *msgs[] = {
+		"INBOX",
+		"Old",
+		"Work",
+		"Family",
+		"Friends",
+		"Cust1",
+		"Cust2",
+		"Cust3",
+		"Cust4",
+		"Cust5",
+	};
+	return (id >= 0 && id < (sizeof(msgs)/sizeof(msgs[0]))) ? msgs[id] : "tmp";
+}
+
+static void free_user(struct ast_vm_user *vmu)
+{
+	if (ast_test_flag(vmu, VM_ALLOCED))
+		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;
+	}
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "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_file(const char *dir, const int msgnum, const struct ast_vm_user *vmu)
+{
+	BODY *body;
+	char *header_content;
+	char *attachedfilefmt;
+	const char *cid_num;
+	const char *cid_name;
+	const char *duration;
+	const char *context;
+	const char *category;
+	const char *origtime;
+	struct vm_state *vms;
+	char text_file[PATH_MAX];
+	FILE *text_file_ptr;
+
+	/* Greetings are not stored on the IMAP server, so we should not
+	 * attempt to retrieve them.
+	 */
+	if (msgnum < 0) {
+		return 0;
+	}
+	
+	/* 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);
+	}
+	
+	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) {
+		return 0;
+	}
+
+	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");
+		return -1;
+	}
+
+	/* 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]);
+		return -1;
+	}
+
+	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");
+		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);
+
+	/* 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]");
+
+	cid_num = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:");
+	cid_name = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Name:");
+	fprintf(text_file_ptr, "callerid=\"%s\" <%s>\n", S_OR(cid_name, ""), S_OR(cid_num, ""));
+	context = get_header_by_tag(header_content, "X-Asterisk-VM-Context:");
+	fprintf(text_file_ptr, "context=%s\n", S_OR(context, ""));
+	origtime = get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:");
+	fprintf(text_file_ptr, "origtime=%s\n", S_OR(origtime, ""));
+	duration = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:");
+	fprintf(text_file_ptr, "duration=%s\n", S_OR(origtime, ""));
+	category = get_header_by_tag(header_content, "X-Asterisk-VM-Category:");
+	fprintf(text_file_ptr, "category=%s\n", S_OR(category, ""));
+	
+	fclose(text_file_ptr);
+	return 0;
+}
+
+static int folder_int(const char *folder)
+{
+	/*assume a NULL folder means INBOX*/
+	if (!folder)
+		return 0;
+	if (!strcasecmp(folder, "INBOX"))
+		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 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;
+		}
+	}
+
+	/* 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) {
+		if (option_debug > 2)
+			ast_log (LOG_DEBUG,"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) {
+		if (!(vms_p = create_vm_state_from_user(vmu))) {
+			ast_log(LOG_WARNING, "Unable to allocate space for new vm_state!\n");
+			return -1;
+		}
+	}
+	ret = init_mailstream(vms_p, fold);
+	if (!vms_p->mailstream) {
+		ast_log (LOG_ERROR,"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 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;
+
+	/*Greetings are not retrieved from IMAP, so there is no reason to attempt storing them there either*/
+	if (msgnum < 0)
+		return 0;
+
+	/* Attach only the first format */
+	fmt = ast_strdupa(fmt);
+	stringp = fmt;
+	strsep(&stringp, "|");
+
+	if (!ast_strlen_zero(vmu->serveremail))
+		myserveremail = vmu->serveremail;
+
+	make_file(fn, sizeof(fn), dir, msgnum);
+
+	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";
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "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)) == NULL) {
+		ast_log(LOG_WARNING, "Unable to store '%s' (can't create temporary file)\n", fn);
+		if (tempcopy)
+			*(vmu->email) = '\0';
+		return -1;
+	} else {
+		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)) == NIL) {
+			ast_log(LOG_ERROR, "Can't allocate %ld bytes to read message\n", len+1);
+			fclose(p);
+			return -1;
+		}
+		fread(buf, len, 1, p);
+		((char *)buf)[len] = '\0';
+		INIT(&str, mail_string, buf, len);
+		init_mailstream(vms, 0);
+		imap_mailbox_name(mailbox, sizeof(mailbox), vms, 0, 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);
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "%s stored\n", fn);
+		/* Using messagecount to populate the last place in the msgArray
+		 * is less than optimal, but it's the only way given the current setup
+		 */
+		messagecount(vmu->context, vmu->mailbox, "INBOX");
+	}
+	if (tempcopy)
+		*(vmu->email) = '\0';
+	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;
+
+	if (option_debug > 2)
+	 	ast_log (LOG_DEBUG,"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, "INBOX")) < 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, ',')) {
+		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;
+}
+
+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 (box == 1) {
+		ast_copy_string(vms->curbox, mbox(0), sizeof(vms->curbox));
+		snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", mbox(1));
+	} else {
+		ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
+		snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
+	}
+
+	/* 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 == 0 || box == 1)
+		snprintf(spec, len, "%s%s", tmp, use_folder? imapfolder: "INBOX");
+	else
+		snprintf(spec, len, "%s%s%c%s", tmp, imapfolder, delimiter, 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;
+
+	ast_copy_string(vms->imapuser,vmu->imapuser, sizeof(vms->imapuser));
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG,"Before init_mailstream, user is %s\n",vmu->imapuser);
+	ret = init_mailstream(vms, box);
+	if (ret != 0 || !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)  {
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "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 = 0, check for new, if box = 1, check for read */
+	if (box == 0) {
+		pgm->unseen = 1;
+		pgm->seen = 0;
+	} else if (box == 1) {
+		pgm->seen = 1;
+		pgm->unseen = 0;
+	}
+
+	vms->vmArrayIndex = 0;
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG,"Before mail_search_full, user is %s\n",vmu->imapuser);
+	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;
+
+	output = fopen (filename, "w");
+	fwrite (buffer, len, 1, output);
+	fclose (output);
+}
+
+void mm_searched(MAILSTREAM *stream, unsigned long number)
+{
+	struct vm_state *vms;
+	char *mailbox;
+	char *user;
+	mailbox = stream->mailbox;
+	user = get_user_by_mailbox(mailbox);
+	vms = get_vm_state_by_imapuser(user,2);
+	if (vms) {
+		if (option_debug > 2)
+			ast_log (LOG_DEBUG, "saving mailbox message number %lu as message %d. Interactive set to %d\n",number,vms->vmArrayIndex,vms->interactive);
+		vms->msgArray[vms->vmArrayIndex++] = number;
+	} else {
+		ast_log (LOG_ERROR, "No state found.\n");
+	}
+}
+
+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! */
+	if (option_debug > 3)
+		ast_log (LOG_DEBUG, "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! */
+	if (option_debug > 3)
+		ast_log (LOG_DEBUG, "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! */
+	if (option_debug > 3)
+		ast_log (LOG_DEBUG, "Entering FLAGS callback for message %ld\n", number);
+	if (number == 0) return;
+	set_update(stream);
+}
+
+
+void mm_notify(MAILSTREAM * stream, char *string, long errflg)
+{
+	mm_log (string, errflg);
+}
+
+
+void mm_list(MAILSTREAM * stream, int delim, char *mailbox, long attributes)
+{
+	if (delimiter == '\0') {
+		delimiter = delim;
+	}
+	if (option_debug > 4) {
+		ast_log(LOG_DEBUG, "Delimiter set to %c and mailbox %s\n",delim, mailbox);
+		if (attributes & LATT_NOINFERIORS)
+			ast_log(LOG_DEBUG, "no inferiors\n");
+		if (attributes & LATT_NOSELECT)
+			ast_log(LOG_DEBUG, "no select\n");
+		if (attributes & LATT_MARKED)
+			ast_log(LOG_DEBUG, "marked\n");
+		if (attributes & LATT_UNMARKED)
+			ast_log(LOG_DEBUG, "unmarked\n");
+	}
+}
+
+
+void mm_lsub(MAILSTREAM * stream, int delimiter, char *mailbox, long attributes)
+{
+	if (option_debug > 4) {
+		ast_log(LOG_DEBUG, "Delimiter set to %c and mailbox %s\n",delimiter, mailbox);
+		if (attributes & LATT_NOINFERIORS)
+			ast_log(LOG_DEBUG, "no inferiors\n");
+		if (attributes & LATT_NOSELECT)
+			ast_log(LOG_DEBUG, "no select\n");
+		if (attributes & LATT_MARKED)
+			ast_log(LOG_DEBUG, "marked\n");
+		if (attributes & LATT_UNMARKED)
+			ast_log(LOG_DEBUG, "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:
+			if (option_debug)
+				ast_log(LOG_DEBUG,"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;
+
+	if (option_debug > 3)
+		ast_log(LOG_DEBUG, "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;
+	char *user;
+	unsigned long usage = 0;
+	unsigned long limit = 0;
+	
+	while (pquota) {
+		usage = pquota->usage;
+		limit = pquota->limit;
+		pquota = pquota->next;
+	}
+	
+	mailbox = stream->mailbox;
+	user = get_user_by_mailbox(mailbox);
+	vms = get_vm_state_by_imapuser(user,2);
+	if (vms) {
+		if (option_debug > 2)
+			ast_log (LOG_DEBUG, "User %s usage is %lu, limit is %lu\n",user,usage,limit);
+		vms->quota_usage = usage;
+		vms->quota_limit = limit;
+	} else {
+		ast_log (LOG_ERROR, "No state found.\n");
+	}
+}
+
+static char *get_header_by_tag(char *header, char *tag)
+{
+	char *start;
+	int taglen;
+	char *eol_pnt;
+
+	if (!header || !tag)
+		return NULL;
+
+	taglen = strlen(tag) + 1;
+	if (taglen < 1)
+		return NULL;
+
+	start = strstr(header, tag);
+	if (!start)
+		return NULL;
+
+	ast_mutex_lock(&imaptemp_lock);
+	ast_copy_string(imaptemp, start+taglen, sizeof(imaptemp));
+	ast_mutex_unlock(&imaptemp_lock);
+	if ((eol_pnt = strchr(imaptemp,'\r')) || (eol_pnt = strchr(imaptemp,'\n')))
+		*eol_pnt = '\0';
+	return imaptemp;
+}
+
+static char *get_user_by_mailbox(char *mailbox)
+{
+	char *start, *quote;
+	char *eol_pnt;
+
+	if (!mailbox)
+		return NULL;
+
+	start = strstr(mailbox,"/user=");
+	if (!start)
+		return NULL;
+
+	ast_mutex_lock(&imaptemp_lock);
+	ast_copy_string(imaptemp, start+6, sizeof(imaptemp));
+	ast_mutex_unlock(&imaptemp_lock);
+
+	quote = strchr(imaptemp,'\"');
+	if (!quote) {  /* if username is not in quotes */
+		eol_pnt = strchr(imaptemp,'/');
+		if (!eol_pnt) {
+			eol_pnt = strchr(imaptemp,'}');
+		}
+		*eol_pnt = '\0';
+		return imaptemp;
+	} else {
+		eol_pnt = strchr(imaptemp+1,'\"');
+		*eol_pnt = '\0';
+		return imaptemp+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_mutex_lock(&vmstate_lock);
+	vlist = vmstates;
+	while (vlist) {
+		if (vlist->vms) {
+			if (vlist->vms->imapuser) {
+				if (!strcmp(vlist->vms->imapuser,user)) {
+					if (interactive == 2) {
+						ast_mutex_unlock(&vmstate_lock);
+						return vlist->vms;
+					} else if (vlist->vms->interactive == interactive) {
+						ast_mutex_unlock(&vmstate_lock);
+						return vlist->vms;
+					}
+				}
+			} else {
+				if (option_debug > 2)
+					ast_log(LOG_DEBUG, "	error: imapuser is NULL for %s\n",user);
+			}
+		} else {
+			if (option_debug > 2)
+				ast_log(LOG_DEBUG, "	error: vms is NULL for %s\n",user);
+		}
+		vlist = vlist->next;
+	}
+	ast_mutex_unlock(&vmstate_lock);
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "%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_mutex_lock(&vmstate_lock);
+	vlist = vmstates;
+	if (option_debug > 2) 
+		ast_log(LOG_DEBUG, "Mailbox set to %s\n",mailbox);
+	while (vlist) {
+		if (vlist->vms) {
+			if (vlist->vms->username) {
+				if (option_debug > 2)
+					ast_log(LOG_DEBUG, "	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) {
+					if (option_debug > 2)
+						ast_log(LOG_DEBUG, "	Found it!\n");
+					ast_mutex_unlock(&vmstate_lock);
+					return vlist->vms;
+				}
+			} else {
+				if (option_debug > 2)
+					ast_log(LOG_DEBUG, "	error: username is NULL for %s\n",mailbox);
+			}
+		} else {
+			if (option_debug > 2)
+				ast_log(LOG_DEBUG, "	error: vms is NULL for %s\n",mailbox);
+		}
+		vlist = vlist->next;
+	}
+	ast_mutex_unlock(&vmstate_lock);
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "%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) {
+			if (option_debug > 2)
+				ast_log(LOG_DEBUG, "Duplicate mailbox %s, copying message info...\n",vms->username);
+			vms->newmessages = altvms->newmessages;
+			vms->oldmessages = altvms->oldmessages;
+			/* memcpy(vms->msgArray, altvms->msgArray, sizeof(long)*256); */
+			copy_msgArray(vms, altvms);
+			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; */
+		}
+	}
+
+	v = (struct vmstate *)malloc(sizeof(struct vmstate));
+	if (!v) {
+		ast_log(LOG_ERROR, "Out of memory\n");
+	}
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "Inserting vm_state for user:%s, mailbox %s\n",vms->imapuser,vms->username);
+	ast_mutex_lock(&vmstate_lock);
+	v->vms = vms;
+	v->next = vmstates;
+	vmstates = v;
+	ast_mutex_unlock(&vmstate_lock);
+}
+
+static void vmstate_delete(struct vm_state *vms) 
+{
+	struct vmstate *vc, *vf = NULL, *vl = NULL;
+	struct vm_state *altvms;
+
+	/* If interactive, we should copy pertainent info
+	   back to the persistent state (to make update immediate) */
+	if (vms->interactive == 1) {
+		altvms = vms->persist_vms;
+		if (altvms) {
+			if (option_debug > 2)
+				ast_log(LOG_DEBUG, "Duplicate mailbox %s, copying message info...\n",vms->username);
+			altvms->newmessages = vms->newmessages;
+			altvms->oldmessages = vms->oldmessages;
+			altvms->updated = 1;
+		}
+	}
+
+	ast_mutex_lock(&vmstate_lock);
+	vc = vmstates;
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "Removing vm_state for user:%s, mailbox %s\n",vms->imapuser,vms->username);
+	while (vc) {
+		if (vc->vms == vms) {
+			vf = vc;
+			if (vl)
+				vl->next = vc->next;
+			else
+				vmstates = vc->next;
+			break;
+		}
+		vl = vc;
+		vc = vc->next;
+	}
+	if (!vf) {
+		ast_log(LOG_ERROR, "No vmstate found for user:%s, mailbox %s\n",vms->imapuser,vms->username);
+	} else {
+		ast_mutex_destroy(&vf->vms->lock);
+		free(vf);
+	}
+	ast_mutex_unlock(&vmstate_lock);
+}
+
+static void set_update(MAILSTREAM * stream) 
+{
+	struct vm_state *vms;
+	char *mailbox;
+	char *user;
+
+	mailbox = stream->mailbox;
+	user = get_user_by_mailbox(mailbox);
+	vms = get_vm_state_by_imapuser(user, 0);
+	if (vms) {
+		if (option_debug > 2)
+			ast_log (LOG_DEBUG, "User %s mailbox set for update.\n",user);
+		vms->updated = 1; /* set updated flag since mailbox changed */
+	} else {
+		if (option_debug > 2)
+			ast_log (LOG_WARNING, "User %s mailbox not found for update.\n",user);
+	}
+}
+
+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 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_log (LOG_DEBUG,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);
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "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
+
+/* only return failure if ast_lock_path returns 'timeout',
+>>>>>>> .merge-right.r134223
    not if the path does not exist or any other reason
 */
 static int vm_lock_path(const char *path)
@@ -1511,6 +2704,7 @@
 	return x - 1;
 }
 
+<<<<<<< .working
 /*!
  * \brief Removes a voicemail message file.
  * \param dir the path to the message file.
@@ -1542,6 +2736,8 @@
 	return 0;
 }
 
+=======
+>>>>>>> .merge-right.r134223
 /*!
  * \brief Determines the highest message number in use for a given user and mailbox folder.
  * \param vmu 

[... 655 lines stripped ...]



More information about the asterisk-commits mailing list